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