#if HAVE_CONFIG_H # include #endif #include #include #include #include /* aliases for the exported symbol: recommended by libtool, and required to * coexist with multiple importer plugins on Mac OS X */ //#define anx_media_importer_init anxmpeg_LTX_anx_media_importer_init /* #define DEBUG 1 */ #define MPEG_MIME_TYPE "video/mpeg" /* public interface */ AnxSource *mpeg_open (const char *path, const char * id, int ignore_raw, double start_time, double end_time, AnxImportCallbacks *import_callbacks); long mpeg_seek (AnxSource *media, long offset); long mpeg_read (AnxSource *media, unsigned char *buf, long n, long bound); long mpeg_sizeofnextread (AnxSource *media, long bound); int mpeg_close (AnxSource *media); /* private functions */ static long next_GOP_header_offset (AnxSource *media, long search_from); typedef struct _mpeg_custom_data { FILE *fh; long current_offset; int next_gop_size; double next_gop_starttime; } mpeg_custom_data; /* mpgcut assistants {{{ */ #define GOP_MARKER 0xB8 /* }}} */ /* mpgcut declarations {{{ */ #include //#include #include #include //#include #include //#include #define UNKNOWNFILE 0x00 #define AUDIOFILE 0x01 #define VIDEOFILE 0x02 #define SYSTEMFILE 0X04 #define PACK_H_SIZE 8 #define BUFFSIZE 16384L // 16kB buffer static double picture_rates [9] = { 0., 24000./1001., 24., 25., 30000./1001., 30., 50., 60000./1001., 60. }; static double starttime; static double timecorrect; typedef unsigned char marker; typedef unsigned char Byte; typedef long offset; static char basename[300]; static int chunknumber,chunkcount; static int confirmall; static Byte Buffer[BUFFSIZE]; static int DoWriteHeader; static float Byterate; static offset audioframelength; static int audiolayer; static int EoF; static offset VidSeqStart,VidSeqEnd; static double* startT; static offset* startO; static offset*stopO; static double* stopT; static double Tmax; static int demux; static FILE* InFd,*OutFd; static int splitnum; static int FileType; static offset FileSize; static offset Start,End; //offset of the buffer in file static offset MinimumCut; static double FrameRate; static int CutPart(offset begin,offset end,char* filename); static int Demux(char* name); static int ParseSequence(char* sequence); static int ParseSequenceOffsets(char* sequence); #ifndef _WIN32 inline #endif static int ParseArgs(int ARGC,char** ARGV); static int ParseAudioHdr(offset off); static void ReadGOPHeader(offset off,double* timestamp); #ifndef _WIN32 inline #endif static int ReadPacketTS(offset* off,double* pts,double* dts); static void ParseVidSeq(offset* off); static int ReadTimeStamp(offset off,double* timestamp); #ifndef _WIN32 inline #endif static void Confirm(char* filename); #ifndef _WIN32 inline #endif static void Offset(double time,offset off); static void TimeToOffsets(); static void copy(FILE* InFd,FILE* OutFd,offset from,offset to); static void init(int ARGC,char**ARGV); static void usage(); static unsigned short int GetSize(offset off); #ifndef _WIN32 inline #endif static int FillBuffer(offset off); #ifndef _WIN32 inline #endif static Byte GetByte(offset off); static int FindNext(offset* off, marker mark); static int FindNextMarker(offset* off,marker* mark); #ifndef _WIN32 inline #endif static int EnsureMarker(offset* off,marker* mark); static int FindVideoSeqHeader(offset* off); static int BackwardFindBoundaries(offset from, offset* packetstart, offset* packetend); static int sampling_index [2][4] = { {44100,48000,32000,0}, {22050,24000,16000,0} }; static int bitrate_index [2][3][16] = {{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}, {{0,32,48,56, 64,80 ,96 ,112,128,144,160,176,192,224,256,0}, {0, 8,16,24,32,40,48, 56,64 ,80 ,96 ,112,128,144,160,0}, {0, 8,16,24,32,40,48, 56,64 ,80 ,96 ,112,128,144,160,0}}}; static AnxImporter mpeg_importer; static struct _AnxImporter mpeg_importer = { (AnxImporterOpenFunc) mpeg_open, (AnxImporterOpenFDFunc) NULL, (AnxImporterCloseFunc) mpeg_close, (AnxImporterReadFunc) mpeg_read, (AnxImporterSizeofNextReadFunc) mpeg_sizeofnextread, MPEG_MIME_TYPE }; AnxImporter * anx_importer_init (int i) { if (i == 0) return &mpeg_importer; else return NULL; } AnxSource * mpeg_open (const char *filename, const char * id, int ignore_media, double start_time, double end_time, AnxImportCallbacks *import_callbacks) { AnxSource *media; AnxSourceTrack *track; mpeg_custom_data *mpeg_data; /* this is pure garbage for mpgcut's init() function */ char *my_argv[2] = { "exe_name", "[0:35-0:45]" }; media = (AnxSource *) anx_malloc (sizeof(AnxSource)); if (media == NULL) return NULL; track = (AnxSourceTrack *) anx_malloc (sizeof (AnxSourceTrack)); if (track == NULL) { anx_free (media); return NULL; } /* set up our custom data */ mpeg_data = (mpeg_custom_data *) anx_malloc(sizeof(mpeg_custom_data)); if (mpeg_data == NULL) return NULL; mpeg_data->fh = (FILE *) anx_malloc(sizeof(FILE)); if (mpeg_data->fh == NULL) return NULL; mpeg_data->fh = fopen(filename, "rb"); if (mpeg_data->fh == NULL) { anx_free(media); return NULL; } mpeg_data->current_offset = 0; mpeg_data->next_gop_size = -1; InFd = mpeg_data->fh; /* mpgcut library uses InFd */ init(3, my_argv); /* initialise mpgcut library */ /* set up media object */ media->importer = &mpeg_importer; /* FIXME: shouldn't be NULL ... */ media->tracks = anx_list_append (NULL, track); media->current_track = track; media->eos = 0; media->start_time = start_time; media->end_time = end_time; track->id = (char *) id; /* XXX: dup? */ track->content_type = MPEG_MIME_TYPE; #ifdef DEBUG printf ("anx_import_mpeg: FrameRate %f\n", FrameRate); #endif #if 0 #if 0 track->granule_rate_n = FrameRate; track->granule_rate_d = 1; /* packets/second */ #else track->granule_rate_n = 10; track->granule_rate_d = 3; #endif #else track->granule_rate_n = 1000; track->granule_rate_d = 1; #endif track->start_granule = 0; track->current_granule = 0; track->end_granule = -1; /* XXX: should calculate */ track->eos = 0; media->custom_data = mpeg_data; return media; } int mpeg_close (AnxSource *media) { mpeg_custom_data *mpeg_data; mpeg_data = (mpeg_custom_data *) media->custom_data; anx_free(mpeg_data->fh); anx_free(mpeg_data); anx_free(media); return 0; } /* FIXME: current_packet will be out of sync on seek() ... change "return 0" * at the end of this function */ long mpeg_seek (AnxSource *media, long offset) { long o; mpeg_custom_data *mpeg_data; mpeg_data = (mpeg_custom_data *) media->custom_data; /* XXX: this presumes that offset = number of seconds since start */ if (offset < mpeg_data->next_gop_starttime) { /* TODO: user is trying to seek backward from current position; we * don't deal with this yet. */ return -1; } o = mpeg_data->current_offset; while (mpeg_data->next_gop_starttime < offset) { o = next_GOP_header_offset(media, o); if (o == -1) return -1; } mpeg_data->current_offset = o; return 0; } #define MIN(x,y) (((x) < (y)) ? (x) : (y)) long mpeg_read (AnxSource *media, unsigned char *buf, long n, long bound) { /* TODO: currently ignoring time bound */ mpeg_custom_data *mpeg_data; int read_size; long read_how_many; mpeg_data = (mpeg_custom_data *) media->custom_data; mpeg_data->next_gop_size = mpeg_sizeofnextread(media, bound); /* read size is min(next_gop_size, n) */ read_size = MIN(mpeg_data->next_gop_size, n); if (mpeg_data->next_gop_size < n) { read_size = mpeg_data->next_gop_size; } else { read_size = n; } fseek(mpeg_data->fh, mpeg_data->current_offset, SEEK_SET); read_how_many = fread(buf, 1, read_size, mpeg_data->fh); mpeg_data->current_offset += read_how_many; #ifdef DEBUG fprintf(stderr, "current offset now %ld\n", mpeg_data->current_offset); #endif fseek(mpeg_data->fh, mpeg_data->current_offset, SEEK_SET); if (read_how_many == mpeg_data->next_gop_size) { #if 0 /* XXX: current_granule */ media->current_track->current_granule++; #else media->current_track->current_granule = (long) (mpeg_data->next_gop_starttime * 1000); #endif } /* are we at the end yet? */ if (mpeg_data->next_gop_size <= 0) { #ifdef DEBUG fprintf(stderr, "setting EOS\n"); #endif media->eos = 1; } mpeg_data->next_gop_size = -1; #if DEBUG fprintf (stderr, "mpeg_read: returning %ld\n", read_how_many); #endif return read_how_many; } long mpeg_sizeofnextread (AnxSource *media, long bound) { /* TODO: currently ignoring time bound */ mpeg_custom_data *mpeg_data; mpeg_data = (mpeg_custom_data *) media->custom_data; if (mpeg_data->next_gop_size != -1) return mpeg_data->next_gop_size; #if 0 if (media->need_sync == 0) { mpeg_data->next_gop_size = next_GOP_header_offset(media, mpeg_data->current_offset) - mpeg_data->current_offset; } else { if (media->need_sync == 1 && MinimumCut != -1) { mpeg_data->next_gop_size = MinimumCut; MinimumCut = -1; } } #else mpeg_data->next_gop_size = next_GOP_header_offset(media, mpeg_data->current_offset) - mpeg_data->current_offset; #endif if (mpeg_data->next_gop_size < -1) mpeg_data->next_gop_size = 0; #if DEBUG fprintf(stderr, "mpeg_sizeofnextread: returning %d\n", mpeg_data->next_gop_size); #endif return mpeg_data->next_gop_size; } long next_GOP_header_offset (AnxSource *media, long search_from) { long o; /* tmp offset */ mpeg_custom_data *mpeg_data; mpeg_data = (mpeg_custom_data *) media->custom_data; #if 1 /* if searching from the start of a GOP packet, skip to the next one */ o = search_from + 4; if (!FindNext(&o, GOP_MARKER)) { /* didn't find squat */ #ifdef DEBUG printf("findnext reported zilch.\n"); #endif return -1; } else { ReadGOPHeader(o, &mpeg_data->next_gop_starttime); #ifdef DEBUG fprintf(stderr, "timestamp of next GOP is %f\n", mpeg_data->next_gop_starttime); #endif o -= 4; /* rewind to start of GOP marker */ return o; } #else o = search_from; if (!FindNext (&o, GOP_MARKER)) { return -1; } /* if searching from the start of a GOP packet, skip to the next one */ if (o == search_from + 4) { if (!FindNext (&o, GOP_MARKER)) { return search_from; } } ReadGOPHeader(o, &mpeg_data->next_gop_starttime); fprintf(stderr, "timestamp of next GOP is %f\n", mpeg_data->next_gop_starttime); return o - 4; #endif } static int mpgcut_main(int ARGC,char** ARGV){ /* {{{ */ offset from,to; int i; char filename[300]; printf("\nmpgcut Ver 1.1 - (c)2000 Laurent Alacoque \n\n"); startT=(double*)(calloc(ARGC-1,sizeof(double))); stopO=(offset*)(calloc(ARGC-1,sizeof(offset))); stopT=(double*)(calloc(ARGC-1,sizeof(double))); startO=(offset*)(calloc(ARGC-1,sizeof(offset))); if (!ParseArgs(ARGC,ARGV)) usage(); init(ARGC,ARGV); if(FileType==AUDIOFILE){ for (i= 0; i< chunkcount;i++) { if(chunknumber==0){ sprintf(filename,"%s.mp%d",basename,audiolayer); chunknumber++; }else{ sprintf(filename,"%s%d.mp%d",basename,chunknumber++,audiolayer); } printf("[%1.2fs %1.2fs] -> ",startT[i],stopT[i]); Confirm(filename); printf("%s ",filename); fflush(stdout); OutFd = fopen(filename,"wb"); if (OutFd ==0) { perror("Unable to open output file "); continue; } from= ((offset)(startT[i]*Byterate)/audioframelength)*audioframelength; to= ((offset)(stopT[i]*Byterate)/audioframelength)*audioframelength; copy(InFd,OutFd,from,to); fclose(OutFd); } for (i=0; i ",i+1,splitnum); Confirm(filename); printf("%s ",filename); fflush(stdout); OutFd = fopen(filename,"wb"); if (OutFd ==0) { perror("Unable to open output file "); continue; } from= ((FileSize*i)/(splitnum*audioframelength))*audioframelength; to= ((FileSize*(i+1))/(splitnum*audioframelength))*audioframelength; copy(InFd,OutFd,from,to); fclose(OutFd); } }else{ //system or video file if(chunkcount >0) TimeToOffsets(); for (i= 0; i< chunkcount;i++) { if(chunknumber==0){ sprintf(filename,"%s.mpg",basename); chunknumber++; }else{ sprintf(filename,"%s%d.mpg",basename,chunknumber++); } if((startT[i]==-1)&&(stopT[i]==-1)){ printf("{%ld %ld} -> ",startO[i],stopO[i]); } CutPart(startO[i],stopO[i],filename); } for (i=0; i ",i+1,splitnum); CutPart(FileSize*i/splitnum,FileSize*(i+1)/splitnum,filename); } } if(demux) Demux(basename); if(InFd != 0) fclose(InFd); return 0; } /* }}} */ #ifndef _WIN32 inline #endif int ParseArgs(int ARGC,char** ARGV){ /* {{{ */ int argcount=1; int okfl=0; int fileok=0; long bidule; char* truc; for (;argcountstop)) usage(); startT[chunkcount]=start; startO[chunkcount]=-1; stopT[chunkcount]=stop; stopO[chunkcount]=-1; chunkcount++; // printf("Cut between %1.2f s and %1.2f s\n",start,stop); return 0; } /* }}} */ int ParseSequenceOffsets(char* sequence){ /* {{{ */ char* ptr=sequence; offset start,stop; int number; number=sscanf(ptr,"{%ld-%ld}",&start,&stop); if (number !=2) usage(); if ((start<0)||(start>stop)) usage(); startT[chunkcount]=-1; startO[chunkcount]=start; stopT[chunkcount]=-1; stopO[chunkcount]=stop; chunkcount++; // printf("Cut between %1.2f s and %1.2f s\n",start,stop); return 0; } /* }}} */ void init(int ARGC,char** ARGV){ /* {{{ */ int i; marker mymark; offset myoff=0; demux=0; confirmall=1; splitnum=0; EoF=0; timecorrect=0; MinimumCut=-1; VidSeqStart=VidSeqEnd=-1; sprintf(basename,"chunk"); chunknumber=0; Tmax=0; startT=(double*)(calloc(ARGC-1,sizeof(double))); stopO=(offset*)(calloc(ARGC-1,sizeof(offset))); stopT=(double*)(calloc(ARGC-1,sizeof(double))); startO=(offset*)(calloc(ARGC-1,sizeof(offset))); for(i=0;i (BUFFSIZE-16)) FillBuffer(myoffset); if ( (GetByte(myoffset+0) == 0x00) && (GetByte(myoffset+1) == 0x00) && (GetByte(myoffset+2) == 0x01)){ *off=myoffset+4; *mark=GetByte(myoffset+3); // printf("Trouvé marqueur %02x offset %ld [%04lx]\n", // GetByte(myoffset+3),myoffset,myoffset); return 1; } myoffset++; } // printf("Fin du fichier atteinte :/ \n"); EoF=1; return 0; } /* }}} */ int FindNext(offset* off,marker mark){ /* {{{ */ offset myoffset=*off; while(myoffset (BUFFSIZE-16)) FillBuffer(myoffset); if ( (GetByte(myoffset+0) == 0x00) && (GetByte(myoffset+1) == 0x00) && (GetByte(myoffset+2) == 0x01) && (GetByte(myoffset+3) == mark)){ *off=myoffset+4; // printf("Trouvé marqueur %02x offset %ld [%04lx]\n", // GetByte(myoffset+3),myoffset,myoffset); return 1; } myoffset++; } // printf("Fin du fichier atteinte :/ \n"); EoF=1; return 0; } /* }}} */ #ifndef _WIN32 inline #endif Byte GetByte(offset off){ /* {{{ */ if ((off>=Start)&&(off=FileSize){ printf("(bug) you shouldn't read this" "\n asked me to read at offset %ld" " ,File size %ld\n",off,FileSize);} else{ //really weird! printf("(bug) fread error while reading file offset %ld (Filesize %ld)\nexiting...", off,FileSize); exit(1); } return 0xff; } } } /* }}} */ #ifndef _WIN32 inline #endif int EnsureMarker(offset* off,marker* mark){ /* {{{ */ if ( (GetByte((*off)+0) == 0x00) && (GetByte((*off)+1) == 0x00) && (GetByte((*off)+2) == 0x01)){ *mark=GetByte((*off)+3); *off=(*off)+4; return 1; }else{ return 0; } } /* }}} */ int FindVideoSeqHeader(offset* off){ /* {{{ */ //we're parsing a system file... //ugly way : find 00 00 01 B3 //smart way : parse PACK headers and packets type // try to find a video seq in video packet // let's be ugly :> return FindNext(off,0xb3); } /* }}} */ unsigned short int GetSize(offset off){ /* {{{ */ return GetByte(off)*256 +GetByte(off+1); } void ParseVidSeq(offset* off){ int horsize,versize; int pictrate; marker mymark; offset saveoff=*off; offset pstart,pend; double pts,dts; starttime=-1; VidSeqStart=(*off)-4; horsize=(GetSize(*off)>>4); versize=(GetSize((*off)+1)&0x0fff); #ifdef DEBUG printf("mpeg video is %d x %d\n",horsize,versize); #endif pictrate=(GetByte((*off)+3)&0x0f); if (pictrate>8) { FrameRate=0; printf("invalid picture rate... strange\n"); } else { FrameRate=picture_rates[pictrate]; #ifdef DEBUG printf("picture rate is %f fps\n", picture_rates[pictrate]); #endif } //we'd have to really parse the remaining but too lazy // let's just find next marker which should be a GOP *off+=6; //at least while (1==1){ if(FindNextMarker(off,&mymark)&&(mymark==0xb8)){ //we have it! aren't we too far? if(((*off) - saveoff)<150 ){ //yeah Y 150? -> because (hint 2 matrix) if(FileType==VIDEOFILE) ReadGOPHeader(*off,&starttime); //get time written in first GOP else{ BackwardFindBoundaries(*off,&pstart,&pend); if (GetByte(pstart+3)==0xe0) { // that's a video packet ok offset pstart2=pstart+6; ReadPacketTS(&pstart2,&pts,&dts); if(dts!=-1) starttime=dts; else starttime=pts; } } // printf("Video Sequence header seems to end at [0x%lx]\n", // (*off)-4); VidSeqEnd=(*off-4); if (FileType==SYSTEMFILE){ MinimumCut=VidSeqStart; while(1){ MinimumCut--; if (MinimumCut<=0) { #if 0 printf("lost, exiting\n"); exit(1); #endif } if (EnsureMarker(&MinimumCut,&mymark)) { if (mymark==0xba){ MinimumCut-=4;break; } else {MinimumCut -=4;} } } } else MinimumCut=(*off)-4; break; } else { //mmm it seems we're lost let's givit a try printf("Video Sequence header seems to end at [0x%lx] but we might be lost :/\n", (*off)-4); VidSeqEnd=(*off-4); if (FileType==SYSTEMFILE){ MinimumCut=VidSeqStart; while(1){ MinimumCut--; if (MinimumCut<=0) { #if 0 printf("lost, exiting\n"); exit(1); #endif } if (EnsureMarker(&MinimumCut,&mymark)) { if (mymark==0xba){ MinimumCut-=4;break; } else {MinimumCut -=4;} } } } else MinimumCut=(*off)-4; break; } } if(EoF==1){ // end of file reached :/ printf("couldn't find first GOP! let's die\n"); exit(1); } //printf("Strange I just passed a 00 00 01 %02x sequence...\n", // mymark); } } /* }}} */ int BackwardFindBoundaries(offset from, offset* packetstart, offset* packetend){ /* {{{ */ //find the packet boundaries in which "from" is offset myfrom=from; marker mymark; //TODO : heavy disk load when buffer's not good. FillBuffer starts @0 if ((myfrom <0)||(myfrom >FileSize)) return(0); for(;myfrom>=0;myfrom--){ if (EnsureMarker(&myfrom,&mymark)){ //a marker was found at offset from -4 if((mymark==0xe0)){ //video packet *packetstart=myfrom-4; *packetend=myfrom+GetSize(myfrom)+2; if((from<*packetstart)||(from>*packetend)) // found packet boundaries but // from wasn't inside... return 0; else return 1; } else myfrom -=4; } } return 0; } /* }}} */ void copy(FILE* InFd,FILE* OutFd,offset from,offset to){ /* {{{ */ if ((InFd)&&(OutFd)){ long rsize=0; long size=0; printf("Copying from [%ld] to [%ld] (%ld)\n",from,to,to-from); FillBuffer(from); fseek(OutFd,0L,SEEK_END); while(rsize < to -from){ rsize+=BUFFSIZE; if (rsize >( to-from)) size = (to-from)%BUFFSIZE; else size=BUFFSIZE; fwrite(Buffer,1,size,OutFd); FillBuffer(from+rsize); } } return ; } /* }}} */ void ReadGOPHeader(offset off, double* timestamp){ /* {{{ */ Byte hour,min,sec,count; *timestamp=0; // printf(" [%02x %02x %02x %02x]\n", // GetByte(off),GetByte(off+1),GetByte(off+2),GetByte(off+3)); // printf(" Drop frame marker: "); // if (GetByte(off)&0x80) printf("1\n"); // else printf("0\n"); hour=GetByte(off); hour &= !0x80; //clears drop frame marker bit hour >>=2; //hour :bits[6-2] *timestamp+=hour*3600; // printf(" hour : %d\n",hour); min=GetByte(off+1); min >>=4; hour=GetByte(off); hour <<= 6 ; hour >>=2; min ^= hour; *timestamp+=min*60; // printf(" minutes : %d\n",min); min=GetByte(off+1); min <<= 5; min >>= 2; sec=GetByte(off+2); sec >>=5; sec ^= min; *timestamp+=sec; // printf(" secondes : %d\n",sec); count=GetByte(off+2); count <<=3; count >>=2; sec=GetByte(off+3); if (sec & 0x80) count |= 0x01; *timestamp += count / FrameRate; // printf(" count : %d\n",count); // printf (" Closed GOP flag : "); // if (sec & 0x40) printf("1\n"); // else printf("O\n"); // printf(" Broken link flag : "); // if (sec & 0x20) printf("1\n"); // else printf("O\n"); } /* }}} */ int CutPart(offset begin, offset end, char* filename){ /* {{{ */ offset myoff=0; // double begin,end; // double Goptime=0; // marker mymark; double trash; offset mybeg,myend; offset packetstart,packetend; offset from,GOPbeg,to,GopToEOP; offset packetheaderlength; offset sizeofnewpacket; Byte highsize,lowsize; if((begin >=FileSize)||(begin<0)) { printf(" beyond end of file skiping\n"); return 0; } //write mpeg file headers Confirm(filename); printf("%s ",filename); fflush(stdout); mybeg=begin; myend=end; from=GOPbeg=to=GopToEOP=-1; OutFd = fopen(filename,"wb"); if (OutFd ==0) { perror("Unable to open output file "); return 0; } if (DoWriteHeader == 1) { if((MinimumCut >=0)){ copy(InFd,OutFd,0,MinimumCut); fflush(OutFd); // stuff(OutFd,StuffingQuantum); } else{ return 0; } } else { DoWriteHeader = 0; } myoff=MinimumCut; //finds first pack including gop if(!FindNext(&mybeg,0xb8)){ //couldn't find anything after begining return 0; } else { // I have a gop! if (FileType==VIDEOFILE) { from=mybeg-4; } else{ GOPbeg=mybeg-4; if(!BackwardFindBoundaries(mybeg,&packetstart,&packetend)){ printf("Error couldn't find video packet in file\n"); return 0; } from=packetstart-12; //till PACK start // stufbeg=(myoff-4)-(packetstart+4+5); GopToEOP=packetend-GOPbeg; } } //we have the begining if(!FindNext(&myend,0xb8)){ //couldn't find anything after begining to=FileSize; if(FileType==VIDEOFILE){copy(InFd,OutFd,from,to); fclose(OutFd); printf("\n"); return 1;} } else { // I have a gop! if (FileType==VIDEOFILE) { to=myend-4; copy(InFd,OutFd,from,to);fclose(OutFd);printf("\n"); return 1;} else{ to=myend-4; } } //okay here we are. // we already copied the mandatory headers i.e. until first video pack // what we have to do here is copy the pack and pack header // compute the new packet length // write it along with video packet header // write the Video Sequence header // write the video sequence starting from GOPbeg, til to // then we're done. //computes the packet header length by parsing it and then getting the modified offset //from is the PACK start from +12 +4 +2 has to be after the video packet length field. packetheaderlength=from+12+4+2; ReadPacketTS(&packetheaderlength,&trash,&trash); packetheaderlength-=(from+12+4+2); //compute the new packet size // size of added VideoSequence(i.e. 00 00 01 b3 -> til GOP) // + GOP to end of packet // + packet header length sizeofnewpacket =VidSeqEnd-VidSeqStart+GopToEOP+packetheaderlength; highsize=(Byte)(sizeofnewpacket >> 8); lowsize=(Byte)(sizeofnewpacket & 0xFF); copy(InFd,OutFd,from,from+12+4); fwrite(&highsize,1,1,OutFd); fwrite(&lowsize,1,1,OutFd); fflush(OutFd); copy(InFd,OutFd,(from+12+4+2),(from+12+4+2+packetheaderlength)); fflush(OutFd); copy(InFd,OutFd,VidSeqStart,VidSeqEnd); fflush(OutFd); copy(InFd,OutFd,GOPbeg,to); fclose(OutFd); printf("\n"); return(1); } /* }}} */ #ifndef _WIN32 inline #endif int ReadPacketTS(offset* off,double* pts,double* dts){ /* {{{ */ //just after the packet start code. and the length field offset myoff=*off; Byte mybyte; //get rid of stuffing bytes mybyte=GetByte(myoff); while(mybyte & 0x80){ // printf("sb "); //this has to be a stuffing byte mybyte=GetByte(++myoff); } // printf("->%x ",mybyte); //here mybyte is the first valid byte if((mybyte>>6)==0x01){ //std buffer scale stuff... let's skip it myoff+=2; mybyte=GetByte(myoff); // printf("std buff, skip ->%x ",mybyte); } if((mybyte>>4)==0x02){ // dts Time stamp // printf(" PTS\n"); ReadTimeStamp(myoff,pts); *dts=-1; *off=myoff+5; return 1; } else if ((mybyte>>4)==0x03){ // printf(" PTS & DTS\n"); //both pts and dts time stamps ReadTimeStamp(myoff,pts); myoff+=5; ReadTimeStamp(myoff,dts); *off=myoff+5; return 1; } else { // curious byte, skip it // printf("unknown\n"); myoff++; } *dts=*pts=-1; *off=myoff; return 0; } /* }}} */ int ReadTimeStamp(offset off,double* timestamp){ /* {{{ */ Byte hiBit; unsigned long low4Bytes; hiBit= (GetByte(off)>>3)&0x01; low4Bytes = ((GetByte(off) >> 1)&0x03)<<30; low4Bytes |= GetByte(off+1)<< 22; low4Bytes |= (GetByte(off+2)>>1)<<15; low4Bytes |= GetByte(off+3) << 7; low4Bytes |= GetByte(off+4) >> 1; #define FLOAT_0x10000 (double)((unsigned long)1 << 16) #define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000 if (hiBit != 0 && hiBit != 1) { *timestamp = -1; return 0; } *timestamp = (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes; *timestamp /= (double)STD_SYSTEM_CLOCK_FREQ; return 1; } /* }}} */ void TimeToOffsets(){ /* {{{ */ int i; double pts,dts; double timesave=0; offset myoff=0; offset skipto=0; int counter=0; if(FileType==SYSTEMFILE){ while(FindNext(&myoff,0xe0)&&((timesave+timecorrect-starttime)(timesave+1))) {timecorrect=timecorrect+timesave-dts; //printf("time corrected by %f",timecorrect);} } //printf ("pts %8.3f dts %8.3f\n",pts+timecorrect-starttime,dts+timecorrect-starttime); timesave=dts; Offset(timesave+timecorrect-starttime,myoff); counter--; if (counter<0) { printf("Seeking input file [%1.1f%%] \r",(timesave+timecorrect-starttime)*100.0/Tmax);counter=100; fflush(stdout); } } else { if((pts(timesave+1))) {timecorrect=timecorrect+timesave-pts; //printf("time corrected by %f",timecorrect);} } //printf("pts %8.3f\n",pts+timecorrect-starttime); timesave=pts; Offset(timesave+timecorrect-starttime,myoff); counter--; if (counter<0) { printf("Seeking input file [%1.1f%%] \r",(timesave+timecorrect-starttime)*100.0/Tmax);counter=100; fflush(stdout); } } myoff=skipto; } } }else{ while(FindNext(&myoff,0xb8)&&((timesave+timecorrect-starttime)(timesave+1))) {timecorrect=timecorrect+timesave-pts; } timesave=pts; Offset(timesave+timecorrect-starttime,myoff); counter--; if (counter<0) { printf("Seeking input file [%1.1f%%] %1.3f \r",(timesave+timecorrect-starttime)*100.0/Tmax,timesave+timecorrect-starttime);counter=3; fflush(stdout); } } } for(i=0; i>1); switch(mylayer){ case 1: mylayer=3; break; case 3: mylayer=1; break; } if (!mylayer){ printf("Layer unknown :%d\n",mylayer); return 0; } else audiolayer=mylayer; protect=GetByte(off)&0x01; bitrateind=GetByte(off+1)>>4; samplingind=(GetByte(off+1)&0x0f)>>2; printf("%d kbits/s ",bitrate_index[mympeg-1][mylayer-1][bitrateind]); bitrate=bitrate_index[mympeg-1][mylayer-1][bitrateind]; Byterate =(float)((bitrate*1000)/8.0); sampling=sampling_index[mympeg-1][samplingind]; printf("%d Hz ",sampling_index[mympeg-1][samplingind]); if(GetByte(off+1)&0x02) { padding=1;} else { padding=0; } mode=GetByte(off+2)>>6; // printf ("mode : %d\n",mode); if (mode==1){ modext=(GetByte(off+2)>>4)&0x03; //printf(" extension %d\n",modext); } if(GetByte(off+2)&0x08) printf("(c) "); // else printf("not copyrighted\n"); if(GetByte(off+2)&0x04) printf("[original]\n"); else printf("[copy]\n"); emphasisind=GetByte(off+2)&0x03; // printf("emphasis index : %d\n",emphasisind); if (mympeg==1){ if (mylayer==1){ audioframelength=48000*bitrate/sampling +padding; }else { audioframelength=144000*bitrate/sampling +padding; } }else if (mympeg ==2){ if (mylayer==1){ audioframelength=24000*bitrate/sampling +padding; }else { audioframelength=72000*bitrate/sampling +padding; } } else return 0; // printf("audio frame length %ld\n",audioframelength); return 1; } /* }}} */