www.pudn.com > vcdtools-0_4-os2.zip > mkvcdfs.c


/*
    mkvcdfs: make a VCD image from several MPEG-1 files suitable
             for burning to CDR with cdrdao

    Usage:

      mkvcdfs mpegfile1 mpegfile2 ....

    mkvcdfs creates 2 files:

    vcd.toc          contains the table of contents of the VCD
    vcd_image.bin    contains the CD-Image itself


    Copyright (C) 2000 Rainer Johanni 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include 
#include 
#include 
#include "defaults.h"
#include "ecc.h"

static int maxrec = 0;
static int xa_fd;

static unsigned char outrec[2352];

static void write_record(int rec)
{
   int n;

   lseek(xa_fd,rec*2352,SEEK_SET);
   n = write(xa_fd,outrec,2352);

   if(n!=2352)
   {
      fprintf(stderr,"Error writing to binary MPEG output file\n");
      perror("write");
      exit(1);
   }
}

static void output_zero(int rec)
{
   /* Output a zero record */

   do_encode_L2(outrec, MODE_0, rec+150);
   write_record(rec);
}

void output_form1(int rec, unsigned char *data)
{
   int i;

   /* Output a CDROM XA Mode 2 Form 1 record,
      we fill gaps with zero records */

   if(rec+1>maxrec)
   {
      for(i=maxrec;imaxrec)
   {
      for(i=maxrec;i>24) & 0xff;
   mpeg[1] = (tag>>16) & 0xff;
   mpeg[2] = (tag>> 8) & 0xff;
   mpeg[3] =  tag      & 0xff;
}

/*
   read_mpeg_sec:

   Parse the MPEG file for the next VCD sector.

   returns:
      -1 if an Error occured
      the stream id of the last packet if this was
         a video or audio packet
      0 otherwise

   if tag is set to EOF_INDICATOR on return,
   reading is finished.
*/

static int read_mpeg_sec(FILE *mpeg_file, unsigned char *mpeg)
{
   int c, n, len;
   int retval = 0;

   /* If tag equals EOF_INDICATOR, the last read resulted in an EOF
      condition, this routine shouldn't be called any more */

   if (tag==EOF_INDICATOR)
   {
      fprintf(stderr,"... internal error 1 reading MPEG file\n");
      return -1;
   }

   /* If we are here the first time, we have to get and check the first tag.
      In all other cases, the tag has already been read */

   if (tag==0)
   {
      if(read_tag(mpeg_file))
      {
         fprintf(stderr,"... file is empty!!!\n");
         return -1;
      }
      if(tag != 0x1ba)
      {
         fprintf(stderr,"... this is not an MPEG system stream, starts with 0x%x\n",tag);
         return -1;
      }
   }

   memset(mpeg,0,2324);

   /* Copy the last tag into mpeg data */

   copy_tag(mpeg);

   /* If this tag is an end code, raise EOF_INDICATOR and return */

   if (tag==0x1b9)
   {
      tag = EOF_INDICATOR;
      return retval;
   }

   /* if we are here, the tag must be a pack start code 0x1ba */

   if (tag!=0x1ba)
   {
      fprintf(stderr,"... internal error 2 reading MPEG file\n");
      return -1;
   }

   /* Read the 8 bytes following the pack start code */

   if(fread(mpeg+4,1,8,mpeg_file)!=8)
   {
      fprintf(stderr,"... Unexpected EOF in MPEG file\n");
      tag = EOF_INDICATOR;
      return retval;
   }
   n = 12;

   while(1)
   {
      /* get next tag */

      if(read_tag(mpeg_file))
      {
         /* EOF reading tag */
         tag = EOF_INDICATOR;
         return retval;
      }

      if(tag<0x1b9 || tag>0x1ff)
      {
         /* Illegal tag */
         fprintf(stderr,"... file contains illegal MPEG tag 0x%x\n",tag);
         fprintf(stderr,"... terminating with this file!!!\n");
         tag = EOF_INDICATOR;
         return retval;
      }

      if(tag==0x1ba) return retval; /* found the next pack start */

      if(tag==0x1b9) /* found end tag */
      {
         if(n+4<=2324)
         {
            copy_tag(mpeg+n);
            tag = EOF_INDICATOR;
            return retval;
         }
         return retval; /* reading will be finished with next call */
      }

      /* Read length of next packet */

      c = getc(mpeg_file);
      len = c;
      c = getc(mpeg_file);
      len = (len<<8)|c;
      if(c==EOF)
      {
         fprintf(stderr,"... Unexpected EOF in MPEG file\n");
         tag = EOF_INDICATOR;
         return retval;
      }

      /* Check if next packet fits to buffer */

      if(n+4+2+len>2324)
      {
         fprintf(stderr,"... Record in MPEG file too long for VCD\n");
         fprintf(stderr,"... terminating with this file!!!\n");
         tag = EOF_INDICATOR;
         return retval;
      }

      /* copy this packet to buffer */

      copy_tag(mpeg+n);
      n+=4;

      mpeg[n++] = (len>>8)&0xff;
      mpeg[n++] =  len    &0xff;

      if(fread(mpeg+n,1,len,mpeg_file)!=len)
      {
         fprintf(stderr,"... Unexpected EOF in MPEG file\n");
         tag = EOF_INDICATOR;
         return retval;
      }

      /* if this packet is a system header for one single stream,
         set retval to the stream id */

      if(tag==0x1bb && len==9) retval = mpeg[n+6];

      /* if this packet is a video or audio stream,
         set retval to the stream id */

      if(tag>=0x1c0 && tag<=0x1ff) retval = tag&0xff;

      n += len;
   }
}

#define MAX_MPEG_FILES 32

static unsigned char data[2324];

main(int argc, char **argv)
{
   int num_MPEG_files;
   int MPEG_size   [MAX_MPEG_FILES]; /* in blocks */
   int MPEG_extent [MAX_MPEG_FILES];
   FILE *MPEG_file;
   FILE *fd_toc;
   int n, extent, m, s, f, i, n1, n2, id;

   if(argc<2)
   {
      fprintf(stderr,"Usage: %s MPEG-files ....\n",argv[0]);
      exit(1);
   }

   if(argc>MAX_MPEG_FILES+1)
   {
      fprintf(stderr,"Maximum of %d MPEG files exceeded!\n",MAX_MPEG_FILES);
      exit(1);
   }

   num_MPEG_files = argc-1;

   /* Open binary output file */

   xa_fd = open(BINARY_OUTPUT_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644);
   if(xa_fd<0)
   {
      fprintf(stderr,"Can not open %s\n",BINARY_OUTPUT_FILE);
      perror("open");
      exit(1);
   }

   /* open VCD_TOC_FILE */

   fd_toc = fopen(VCD_TOC_FILE,"w");
   if(fd_toc==0)
   {
      fprintf(stderr,"Can not open VCD toc file %s\n",VCD_TOC_FILE);
      perror("fopen");
      exit(1);
   }

   /* Write the toc file */

   fprintf(fd_toc,"CD_ROM_XA\n\n");
   fprintf(fd_toc,"// Track 1: Header with ISO 9660 file system\n");
   fprintf(fd_toc,"TRACK MODE2_RAW\n");
   f = ISO_FS_BLOCKS + 150;
   s = f/75;
   f = f%75;
   m = s/60;
   s = s%60;
   fprintf(fd_toc,"DATAFILE \"%s\" %2.2d:%2.2d:%2.2d\n\n",BINARY_OUTPUT_FILE,m,s,f);

   extent = ISO_FS_BLOCKS;

   for(n=0;n