/************************************************************* * mpgtx an mpeg toolbox * * by Laurent Alacoque * * (c) 2001 * * You may copy, modify and redistribute this * * source file under the terms of the GNU Public License * ************************************************************/ #include "mpegOut.hh" #include "common.hh" #include #include // original was 0.015 #define base_TS_correction 0.015 // hate me for the globals ... Begin philipp mod // extern bool aspect_correction; // flag if corretion is needed extern byte forced_sequence_header; // the new aspect ratio extern bool preserve_header; // flag if junk at the start of a file should be preserved extern bool print_progress; // print more info while processing void print_ts(byte *p); // prints the timestamp of a mpeg2 gop - only for testing // end philipp mod // #define _DEBUG_ #ifdef _DEBUG_ int count=0; #endif mpegOut::mpegOut(char* filename) { BTRACK; // fprintf(stderr, "constructing mpegOut %s\n",filename); if (!access(filename, F_OK)) { // file already exist //fprintf(stderr,"File %s already exist\n",filename); } //open file for writing/truncate MpegOut = fopen(filename, "wb"); if (MpegOut == 0) { // Gosh ! unable to open fprintf(stderr, "Unable to open %s for writing\n", filename); perror("reason: "); } HasAudio = HasVideo = false; FileType = mpeg_EMPTY; } mpegOut::mpegOut(FILE* filehandle) { BTRACK; // fprintf(stderr,"constructing mpegOut with filehandle\n"); MpegOut = filehandle; HasAudio = HasVideo = false; FileType = mpeg_EMPTY; } mpegOut::~mpegOut() { BTRACK; // printf("destructing mpegOut \n"); if (MpegOut != 0) fclose (MpegOut); } void mpegSystemOut::WriteHeader(mpeg* Mpeg){ header_buf *pbfix; int mpeg2stuff_bytes; BTRACK; //Have to write system headers and video sequence if (!MpegOut) return; if (!Mpeg) return; if (preserve_header) { fprintf(stderr,"now reapplying junk-header ....\n"); /* read original bytes of header */ /* from 0 to offset to video */ pbfix = readHeader(MpegOut,0,2); // fprintf(stderr,"Size of header still: 0x%qx\n",pbfix->size); fwrite(pbfix->buf,pbfix->size,1,MpegOut); } mpeg_version = Mpeg->Version(); if (!preserve_header) { // alternatively, create our own header if(Mpeg->System->video_system_header) fwrite(Mpeg->System->video_system_header, 1, Mpeg->System->video_system_header_length, MpegOut); if (Mpeg->System->audio_system_header) fwrite(Mpeg->System->audio_system_header, 1, Mpeg->System->audio_system_header_length, MpegOut); } // okay system headers are written... // let's write the PACK + video packet header // we keep the remaining in mem because we need to // correct the packet length before outputing it (stdout is not // seekable:/ off_t PACKlength = 0; mpeg2stuff_bytes = 4; if ((Mpeg->System->first_video_packet[4] & 0xF0) == 0x20) { //standard mpeg1 pack PACKlength = 12; } else { if ((Mpeg->System->first_video_packet[4] & 0xC0) == 0x40) { //new mpeg2 pack : 14 bytes + what stuffing ? mpeg2stuff_bytes = Mpeg->System->first_video_packet[13] & 0x07; PACKlength = 14; #ifdef _DEBUG_ fprintf(stderr,"packlength %qx\n",PACKlength); fprintf(stderr,"firstVideopacket: \n"); for (count = 0; count < Mpeg->System->first_video_packet_length; ++count) { fprintf(stderr,"%02x ",Mpeg->System->first_video_packet[count]); } fprintf(stderr,"\n-------\n"); #endif } else { //wazup? // May 28 2001: maybe there's no pack at all... byte packetcode = Mpeg->System->first_video_packet[3] & 0xF0; if (packetcode == 0xE0 || packetcode == 0xD0 ) { // this is a video packet that dosnt have a pack before PACKlength = 0; } else { if(Mpeg->System->first_video_packet[3] != 0xba) { //neither a PACK nor a video packet fprintf(stderr, "I'm lost, ciao\n"); exit(1); } fprintf(stderr, "Weird PACK encountered don't seem to be mpeg 1 nor mpeg 2.\n"); fprintf(stderr, "I most certainly crash in a minute but I love risk.\n"); // try to find the end of the pack "manually" i.e. till the first video packet bool endofpackfound = false; PACKlength = 12; for (; PACKlength < Mpeg->System->first_video_packet_length; PACKlength++) { if ( Mpeg->System->first_video_packet[PACKlength] == 0x0 && Mpeg->System->first_video_packet[PACKlength + 1] == 0x0 && Mpeg->System->first_video_packet[PACKlength + 2] == 0x1 && ((Mpeg->System->first_video_packet[PACKlength + 3] & 0xF0) == 0xE0|| (Mpeg->System->first_video_packet[PACKlength + 3] & 0xF0) == 0xD0) ) { endofpackfound=true; break; PACKlength--; // TODO: Laurent what's this? break exits.. } //if } //for if ((!endofpackfound) || (Mpeg->System->first_video_packet_length-PACKlength-4-2 <=0)) { fprintf(stderr,"Now I'm really lost, ciao\n"); exit(1); } } // end May 28 } } fwrite(Mpeg->System->first_video_packet, 1, PACKlength + mpeg2stuff_bytes, MpegOut); // now allocate required mem partial_packet_length = Mpeg->System->first_video_packet_length-PACKlength - mpeg2stuff_bytes - (mpeg2stuff_bytes == 0?0:2); //after the size field partial_packet_length += Mpeg->Video->video_header_size; partial_packet = new byte[partial_packet_length]; // printf("allocating %ld bytes\n",partial_packet_length); memcpy(partial_packet, (Mpeg->System->first_video_packet) + PACKlength + mpeg2stuff_bytes + (mpeg2stuff_bytes == 0?0:2), Mpeg->System->first_video_packet_length - PACKlength - mpeg2stuff_bytes - (mpeg2stuff_bytes == 0?0:2)); memcpy(&partial_packet[(Mpeg->System->first_video_packet_length) - PACKlength - mpeg2stuff_bytes - (mpeg2stuff_bytes == 0?0:2)], Mpeg->Video->video_header, Mpeg->Video->video_header_size); HasAudio = HasVideo = true; FileType = mpeg_SYSTEM; currentTS = Mpeg->System->initial_TS; #ifdef _DEBUG_ fprintf(stderr,"Mpeg initial_TS: %lf\n",currentTS); #endif fflush(MpegOut); } void mpegVideoOut::WriteHeader(mpeg* Mpeg) { BTRACK; //Have to write video sequence if (!MpegOut) return; fwrite(Mpeg->Video->video_header, 1, Mpeg->Video->video_header_size, MpegOut); } int mpegVideoOut::WriteChunk( mpeg* Mpeg, off_t from, bool from_included, off_t to, bool to_included) { BTRACK; if (!MpegOut) return 0; off_t real_from, real_to; if ((from > to) || (from < 0) || (to < 0)) { //pffff return 0; } if (from_included) { real_from = Mpeg->bdFindNextMarker(from, 0xB8); if (real_from == -1) { //couldn't find a GOP before from! real_from = Mpeg->FindNextMarker(from, 0xB8); if (real_from == -1) { //gosh couldn't find GOP at all! return 0; } } } else { real_from = Mpeg->FindNextMarker(from, 0xB8); if (real_from == -1) { real_from = Mpeg->bdFindNextMarker(from, 0xB8); if(real_from == -1) { //couldn't find any GOP! return 0; } } } //okay we have a real from if (to_included) { real_to = Mpeg->FindNextMarker(to, 0xB8); if (real_to == -1) real_to = Mpeg->FileSize; } else { real_to = Mpeg->bdFindNextMarker(to, 0xB8); if (real_to == -1) { //couldn't find any GOP! return 0; } } if (real_from >= real_to) return 0; //now let's Copy from GOP boundary to GOP boundary if (print_progress) fprintf(stderr, " "); Copy(Mpeg->MpegFile, real_from,real_to); return 1; } int mpegAudioOut::WriteChunk( mpeg* Mpeg, off_t from, bool from_included, off_t to,bool to_included) { BTRACK; if (!MpegOut) return 0; off_t real_from,real_to; // 23 March 2001, real_to an real_from are now seeked // because there are plenty of variable bitrates mp3 /* real_from=from -(from% Mpeg->Audio->frame_length); if ((real_from!=from)&&(!from_included)) real_from+=Mpeg->Audio->frame_length; real_to= to -(from%Mpeg->Audio->frame_length); if ((real_to!=to)&&(to_included)) real_to += Mpeg->Audio->frame_length; if (real_to > Mpeg->Size()) real_to=Mpeg->Size(); */ if (from_included) real_from = Mpeg->bdFindMatchingAudio(from); else real_from = Mpeg->FindMatchingAudio(from); if (to_included) real_to=Mpeg->FindMatchingAudio(to); else real_to=Mpeg->bdFindMatchingAudio(to); if (real_to==-1 || real_from==-1 || real_from >= real_to) return false; if(print_progress) fprintf(stderr," "); Copy(Mpeg->MpegFile, real_from, real_to); return 1; } int mpegSystemOut::WriteChunk( mpeg* Mpeg, off_t from, bool from_included, off_t to, bool to_included) { int count; BTRACK; if (!MpegOut) return 0; #ifdef _DEBUG_ fprintf(stderr,"new Chunk: from:0x%qx, to:0x%qx\n",from,to); #endif off_t real_from, real_to; int sequence_header; //given the from and to offsets, find GOP boundaries if ((from > to) || (from < 0) || (to < 0)) { //pffff return 0; } if (from_included) { real_from = Mpeg->bdFindNextMarker(from, 0xB8); if (real_from == -1) { //couldn't find a GOP before from! real_from = Mpeg->FindNextMarker(from, 0xB8); if (real_from == -1) { //gosh couldn't find GOP at all! return 0; } } } else { real_from= Mpeg->FindNextMarker(from, 0xB8); if (real_from == -1) { //couldn't find any GOP! return 0; } } //okay we have a real from if (to_included) { real_to = Mpeg->FindNextMarker(to, 0xB8); if (real_to == -1) real_to = Mpeg->FileSize; } else { real_to = Mpeg->bdFindNextMarker(to, 0xB8); if (real_to == -1) { //couldn't find any GOP! return 0; } } if (real_from >= real_to) return 0; // printf("[%ld - %ld ] becomes [%ld - %ld]\n",from,to, real_from,real_to); // while(getchar()!='\n'); //okay the file is there but artifacts too.. //we have to correct the packet length //we already know the data size we have, //let's compute what we just added : from GOP to end of packet off_t EOP = real_from - 1; marker mark; while (true) { EOP = Mpeg->FindNextMarker(EOP + 1, &mark); if (((mark & 0xF0) != 0x0) && (mark != 0xB8)) { // this is neither a slice, nor a pic nor a gop : // we are then at the end of the packet break; } if (EOP == -1) break; } off_t GOP2EOP = EOP - real_from; //if FindNextMarker returned -1 there was no pack after->take filesize if (GOP2EOP < 0) GOP2EOP = Mpeg->FileSize-real_from; //okay the packet size must now be ::partial_packet_length+GOP2EOP //let's write that off_t real_packet_length = partial_packet_length+GOP2EOP; #ifdef _DEBUG_ fprintf(stderr,"real_packet_length: [" _OFF_x "]\n", real_packet_length ); #endif byte low = real_packet_length & 0xFF; byte high = (real_packet_length >> 8) & 0xFF; //fseeko(MpegOut, size_field_offset, SEEK_SET); if (Mpeg->Version() == 2) { // dont touch valuable data, maybe mpeg1 files have a size here but mpeg2 wont play // if filesize is written here // this is not good, who nows what the effect will be on other mpeg2s ? // but currently I dont know it better ; } else { fwrite(&high, 1, 1, MpegOut); fwrite(&low, 1, 1, MpegOut); //fseeko(MpegOut, 0, SEEK_END); } fflush(MpegOut); //write what we kept in mem and free memory // fprintf(stderr,"partial_packet_length %qd\n",partial_packet_length); // for (count = 0; count < partial_packet_length; ++count) { // fprintf(stderr, "%02x.",*(partial_packet + count)); // } // fprintf(stderr,"\n"); sequence_header = -1; for (count = 0; count < partial_packet_length - 4; ++count) { if ( (*(partial_packet + 0 + count) == 0x00) && (*(partial_packet + 1 + count) == 0x00) && (*(partial_packet + 2 + count) == 0x01) && (*(partial_packet + 3 + count) == 0xb3) ) { sequence_header = count + 4; // fprintf(stderr, "found sequence header at: %d\n",sequence_header); count = partial_packet_length; // this is the important sequence header in the file! } } if ((sequence_header != -1) && ((partial_packet_length - sequence_header) > 4) && (aspect_correction)) { // found it, room to change is there, user wants it if (print_progress) fprintf(stderr,"\nCurrent Value of aspect ratio is: %2x ",*(partial_packet + sequence_header + 3)); // fprintf(stderr, "position: %d is: %2x\n", sequence_header + 3,*(partial_packet + sequence_header + 3)); *(partial_packet + sequence_header + 3) = ((*(partial_packet + sequence_header + 3) & 0xf) | forced_sequence_header ); // fprintf(stderr, "position: %d is new: %2x\n", sequence_header + 3,*(partial_packet + sequence_header + 3)); if (print_progress) fprintf(stderr,"New Value of aspect ratio is: %2x\n",*(partial_packet + sequence_header + 3)); } fwrite(partial_packet, 1, partial_packet_length, MpegOut); fflush(MpegOut); // printf("deleting partial_packet in WriteChunk\n"); delete[] partial_packet; //now recreate buffer with everything from start of packet //to GOP end (real_to) and copy it in partial_packet off_t last_packet_offset= Mpeg->bdFindNextMarker(real_to, 0xE0); // fprintf(stderr,"last_packet_offset: [" _OFF_x "]\n",last_packet_offset); partial_packet_length = real_to-last_packet_offset - 6; partial_packet = new byte[partial_packet_length]; // printf("allocating %ld bytes\n",partial_packet_length); FSEEK(Mpeg->MpegFile, last_packet_offset + 6, SEEK_SET); fread(partial_packet, 1, partial_packet_length, Mpeg->MpegFile); //now let's Copy from start of packet boundary to beg of last packet if (print_progress) fprintf(stderr," "); #ifdef _DEBUG_ fprintf(stderr,"Starting copy %qd %qd \n",real_from,last_packet_offset); #endif Copy(Mpeg->MpegFile, real_from,last_packet_offset + 4); // Copy updated the current time stamp. // we must now correct the partial packet timestamp. byte* OldBuffer = buffer; buffer = partial_packet; if (CorrectTS(partial_packet_length) != 0) { fprintf(stderr,"unhandled result code of CorrectTS, results in playback or sync problem!\n"); } buffer = OldBuffer; return 1; } void mpegSystemOut::Copy(FILE* file, off_t from, off_t to) { BTRACK; #ifdef ENABLE_OPTIMIZATION double Copy_time_start=Clock_Now(); #endif if (!MpegOut) return ; // long DBGsize; off_t size = to - from; off_t read_size = 0; off_t prev_read_size = 0; long rewind_pos = 0; // if buffer at end and TS could not be corrected, reread from correct position float percent; first_TS_correction = true; // fprintf(stderr,"Starting copy @%lx\n",ftell(MpegOut)); size_t size2read = (size > COPYBUFFERSIZE)?COPYBUFFERSIZE:size; buffer = new byte[size2read]; while(read_size < size) { size2read = ((size - read_size) > COPYBUFFERSIZE)?COPYBUFFERSIZE:size-read_size; if (rewind_pos != 0) { // last buffer was at end, and a TS could not be corrected FSEEK(file, from + read_size - (prev_read_size - rewind_pos), SEEK_SET); #ifdef _DEBUG_ // fprintf(stderr,"rewinded by %qd bytes to prevent short buffer problem\n",(prev_read_size - rewind_pos)); #endif prev_read_size = 0; rewind_pos = 0; } else FSEEK(file, from + read_size, SEEK_SET); read_size += fread(buffer, 1, size2read, file); // fprintf(stderr,"read bytes: %qd\n",read_size); if (first_TS_correction) { #ifdef _DEBUG_ fprintf(stderr,"The bytes from start...: %02x %02x %02x %02x %02x %02x\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5] ); #endif // hehe we have to set the broken link flag on the first GOP! // why? because those players will try to play the leading B frames // wich are predicted from former frames (and they're not any, cause // we just happen to cut them, remember?) // broken_link flag is just for that! // we must be on a GOP start here // broken link is 27 bit after GOP start sequence // it is @ 4 + 3 bytes + 3 bits buffer[7] |= 0x20; // pfiouuu that one line was hard to find! // now that broken link is set we must unset the closed gop bit buffer[7] &= 0xBF; //TODO: some players ignore this broken link flag... // (I hate them) // another dirty way to do that is to find all B (and P?) // frames preceding the first I frame and change their type // (offset of frame type : 00 00 01 00 +10bits /3bits // to something like 000b wich is not a valid frame type, // they may be discarded by the player // I guess the best way to make it robust is to parse the whole // GOP, delete the preceding B frames and change the temporal ref // of every other frames... // This is a though job because a single frame can span over multiple // video packets... // final versions of this soft might cut mpg files on frame // boundaries... we'll take care of that at this very moment. } rewind_pos = CorrectTS(size2read); // correct TS of buffer if (rewind_pos) { #ifdef _DEBUG_ // fprintf(stderr,"we now take care of the buffer problem! %ld size2read: %ld\n",rewind_pos,size2read); #endif fwrite(buffer,1,rewind_pos,MpegOut); // only write the part which is ok! prev_read_size = size2read; } else fwrite(buffer, 1, size2read, MpegOut); //printf("Written %ld bytes on %ld wanted\n",DBGsize,size2read); if (print_progress) { START_CLOCK percent = (read_size*1.0) / (size/100.0); percent = (percent>100.0)?100.0:percent; fprintf(stderr,"\b\b\b\b\b\b\b\b%5.2f%% ", percent); fflush(stdout); STOP_CLOCK(PRINTF); } } delete buffer; #ifdef ENABLE_OPTIMIZATION AddTime(Copy_time_start,COPY); #endif } void mpegAudioOut::Finish() { // write id3 tag if present } void mpegSystemOut::Finish(){ BTRACK; if (!MpegOut) return; if (partial_packet) { byte low = partial_packet_length & 0xFF; byte high = (partial_packet_length >> 8) & 0xFF; fwrite(&high, 1, 1, MpegOut); fwrite(&low, 1, 1, MpegOut); fwrite(partial_packet, 1, partial_packet_length, MpegOut); // printf("deleting partial packet in finish\n"); delete[] partial_packet; } fclose(MpegOut); } void mpegVideoOut::Copy(FILE* file, off_t from, off_t to){ BTRACK; #ifdef ENABLE_OPTIMIZATION double Copy_time_start=Clock_Now(); #endif if (!MpegOut) return ; off_t size = to - from; off_t read_size = 0; first_TS_correction = true; float percent; // fprintf(stderr,"Starting copy @%lx\n",ftell(MpegOut)); size_t size2read = (size > COPYBUFFERSIZE)?COPYBUFFERSIZE:size; buffer = new byte[size2read]; while (read_size < size) { size2read = ((size - read_size) > COPYBUFFERSIZE)?COPYBUFFERSIZE:size-read_size; FSEEK(file, from + read_size, SEEK_SET); read_size += fread(buffer, 1, size2read, file); if (first_TS_correction) { buffer[7] |= 0x20; first_TS_correction = false; } fwrite(buffer, 1, size2read, MpegOut); if (print_progress) { //lperc=(read_size*100)/(size/100); START_CLOCK; percent = (read_size*1.0) / (size/100.0); fprintf(stderr, "\b\b\b\b\b\b\b\b%5.2f%% ", percent); fflush(stderr); STOP_CLOCK(PRINTF); } } delete buffer; #ifdef ENABLE_OPTIMIZATION AddTime(Copy_time_start,COPY); #endif } void mpegAudioOut::Copy(FILE* file, off_t from, off_t to) { BTRACK; #ifdef ENABLE_OPTIMIZATION double Copy_time_start=Clock_Now(); #endif if (!MpegOut) return; off_t size = to - from; off_t read_size = 0; float percent; // fprintf(stderr,"Starting copy @%lx\n",ftell(MpegOut)); size_t size2read = (size > COPYBUFFERSIZE)?COPYBUFFERSIZE:size; buffer = new byte[size2read]; while (read_size < size) { size2read = ((size - read_size) > COPYBUFFERSIZE)?COPYBUFFERSIZE:size-read_size; FSEEK(file, from + read_size, SEEK_SET); read_size += fread(buffer, 1, size2read, file); fwrite(buffer, 1, size2read, MpegOut); if (print_progress) { START_CLOCK; //lperc=(read_size*100)/(size/100); percent = (read_size*1.0) / (size/100); percent = (percent>100.0)?100.0:percent; fprintf(stderr, "\b\b\b\b\b\b\b\b%5.2f%% ", percent); fflush(stderr); STOP_CLOCK(PRINTF); } } delete buffer; #ifdef ENABLE_OPTIMIZATION AddTime(Copy_time_start,COPY); #endif } void foo(){ printf("ici"); } #ifndef _WIN32 inline #endif long mpegOutWithVideo::CorrectTS(long bufferlength) { BTRACK; // for each pack we encounter in that buffer, // get the timestamp long nix; // stores the location of the a GOP in the buffer double ts; double ts2; double ts3; //added April 24 2001 if (first_TS_correction) ts_correction = 0.0; //end added int nbofTS; long i; long saved_i; nix = -1; //9 is for 4 bytes PACKstartcode + 5 bytes PACKTS for ( i=0; i < bufferlength - 9; i++){ // printf("i vaut %d\n",i); if ((buffer[i]== 0x00) && (buffer[i + 1] == 0x00) && (buffer[i + 2] == 0x01)) { switch(buffer[i + 3]) { case 0xB3: // found a sequence header if (aspect_correction) { buffer[i + 7] = ((buffer[i + 7] & 0xf ) | forced_sequence_header); } break; case 0xB8: // found a GOP if (mpeg_version != 2) { // it worked before without correction of GOPS in mpeg1 so why change ? break; } else { #ifdef _DEBUG_ fprintf(stderr,"mpeg2 GOP found!\n"); fprintf(stderr,"TS GOP mpeg2: %f before : %f (delta %f) [pack]\n",ts+ts_correction,ts,ts_correction); #endif memReadTS(i + 4, &ts, true); if (first_TS_correction) { // did another GOP appear before a pack ? - problem if (nix != -1) fprintf(stderr,"lost one gop correction, this should not happen!\n"); nix = i; // do that later impossible to know now the correct value // I figured out the the TS of GOPS most time are higher then in the PACKs // TS must be corrected, but if the value would be taken from the GOP TS // that would be wrong, so do it later #ifdef _DEBUG_ fprintf(stderr,"first TS correction delayed\n"); #endif } } break; case 0xBA: //we have a PACK //DBG // printf("PACK "); if (mpeg_version == 2) { memReadTS(i + 4, &ts, true,true); } else memReadTS(i + 4, &ts); if (first_TS_correction) { first_TS_correction = false; ts_correction=currentTS - ts + base_TS_correction; #ifdef _DEBUG_ fprintf(stderr,"FirstTS Corr: current: %f, ts: %f, base_TS_corr %f\n",currentTS,ts,base_TS_correction); #endif if ( nix != -1) { memReadTS(nix + 4, &ts3,true); #ifdef _DEBUG_ fprintf(stderr,"delayed correction executed now: at: %ld ts: %lf tscorrection: %lf TS: %lf \n",nix,ts3,ts_correction, ts3 + ts_correction); #endif memWriteTS(nix + 4, ts3 + ts_correction,true); nix = -1; // clear } } #ifdef _DEBUG_ fprintf(stderr,"TS: %f before : %f (delta %f) [pack]\n",ts+ts_correction,ts,ts_correction); #endif currentTS=ts + ts_correction; #ifdef _DEBUG fprintf(stderr, "pack current TS is now %f\n",currentTS); #endif if (currentTS < 0.0 ){ currentTS = 0.0; fprintf(stderr,"PACK: TS <0, corrected to 0, movie will have problems playing!\n"); } if (mpeg_version == 2) { #ifdef _DEBUG_ fprintf(stderr,"memwriteTS mpeg2\n"); #endif memWriteTS(i + 4, currentTS, true,true); } else memWriteTS(i + 4, currentTS); #ifdef _DEBUG_ // debug fprintf(stderr,"PACK "); memReadTS(i+4,&ts,true); #endif break; // philipp xxx case 0xC0 : // Found a mpeg audio PES header case 0xE0 : // Found a mpeg video PED header // for processing DVDs, this must be expanded in a future version ! #ifdef _DEBUG_ fprintf(stderr,"PES HEADER, "); if (buffer[i + 3] == 0xE0) fprintf(stderr,"video stream\n" ); else fprintf(stderr,"audio stream\n" ); #endif //skip packet start code & length field #ifdef _DEBUG_ fprintf(stderr,"\nOffset: %ld The bytes...: %2x %2x %2x %2x %2x %2x\n",i,buffer[i + 0],buffer[i + 1],buffer[i + 2],buffer[i + 3],buffer[i + 4],buffer[i + 5] ); #endif saved_i = i + 6; i += 6; #ifdef _DEBUG_ fprintf(stderr,"Offset: %ld The bytes...: %2x %2x %2x %2x %2x %2x\n",i,buffer[i + 0],buffer[i + 1],buffer[i + 2],buffer[i + 3],buffer[i + 4],buffer[i + 5] ); #endif nbofTS = memReadPktTS(&i, &ts, &ts2, bufferlength); if (first_TS_correction) { //ooops ts_correction not initialized... cheat. if (nbofTS >= 1) ts_correction=currentTS - ts + base_TS_correction; } #ifdef _DEBUG_ if (nbofTS != 0) fprintf(stderr,"!!!!!!!!1nbofTS: %d\n",nbofTS); #endif if (nbofTS == 1) { //only one pts to change ts += ts_correction; if (ts < 0) { ts = 0; fprintf(stderr,"PES01: TS <0, corrected to 0, movie will have problems playing!\n"); // negative TS are no good, better set to 0 but what about playback ..? } // ts = (ts < 0)?0:ts; //I know this is dirty // for what ever reason my compile did ignore the above statement replaced by above it // printf("pts current TS is now %f\n",ts); if (mpeg_version == 2) memWriteTS(i - 5, ts); else memWriteTS(i - 5, ts); // fprintf(stderr,"1 TS written at %d\n", (i - 5) - saved_i); // if (i - 5 - saved_i == 0) fprintf(stderr, "ZERO FOUND\n"); // fprintf(stderr,"-3"); break; } if (nbofTS == 2) { //two ts to change ts += ts_correction; ts2 += ts_correction; if ( ts < 0 ) { ts = 0; fprintf(stderr,"PES02: TS <0, corrected to 0, movie will have problems playing!\n"); } if ( ts2 < 0 ) { ts2 = 0; fprintf(stderr,"PES03: TS <0, corrected to 0, movie will have problems playing!\n"); } // fprintf(stderr,"pts current TS is now %f\n",ts); // fprintf(stderr,"dts current TS is now %f\n",ts2); /* memWriteTS(i-5,ts); memWriteTS(i,ts2); */ if (mpeg_version == 2) { memWriteTS(i - 10, ts); memWriteTS(i - 5, ts2); } else { memWriteTS(i - 10, ts); memWriteTS(i - 5, ts2); } //fprintf(stderr,"2 TS written at %d and %d\n", // (i - 10) - saved_i, (i - 5) - saved_i); // fprintf(stderr,"--3"); break; } if (nbofTS == -1) { // fprintf(stderr,"buffer problem here not handled, taking care later buffer: %ld\n",i); return i; break; } if (nbofTS) { // all other return codes are impossible! fprintf(stderr,"we should not get to this point please report this error! nbofTS: %d\n",nbofTS); return -1; break; } break; } //switch } //if } //for return 0; } void mpegOutWithVideo::memReadTS(long offset, double* ts, bool mpeg2pack, bool pack){ BTRACK; byte highbit; unsigned long low4Bytes; double TS; byte *nix; #ifdef _DEBUG_ printf("\nReading TS at offset [" _OFF_x "]\n", offset + FTELL(MpegOut)); print_ts(&(buffer[offset ])); #endif //debug if (!mpeg2pack) { // mpeg1 is different from 2! highbit= (buffer[offset]>>3)&0x01; low4Bytes = ((buffer[offset] >> 1) & 0x03) << 30; low4Bytes |= buffer[offset + 1] << 22; // hours low4Bytes |= (buffer[offset + 2] >> 1) <<15; // minutes low4Bytes |= buffer[offset + 3] << 7; low4Bytes |= buffer[offset + 4] >> 1; #define FLOAT_0x10000 (double)((unsigned long)1 << 16) #define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000 TS = (double)(highbit * FLOAT_0x10000 * FLOAT_0x10000); TS += (double)(low4Bytes); TS /= (double)(STD_SYSTEM_CLOCK_FREQ); *ts = TS; #ifdef _DEBUG_ printf("TS1 : base : 0x%d,%032lx ",highbit,low4Bytes); printf ("TS1 : %lf\n",TS); fprintf(stderr,"\nTS mpeg 1 : %02x, %02x %02x %02x %02x, [%lx]\n", highbit, byte((low4Bytes>>24)&0xFF), byte((low4Bytes>>16)&0xFF), byte((low4Bytes>>8)&0xFF), byte((low4Bytes)&0xFF), (unsigned long) (offset) ); fprintf(stderr,"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x highBit=%d low4Bytes=%ld\n", buffer[offset-4], buffer[offset-3], buffer[offset-2], buffer[offset-1], buffer[offset-0], buffer[offset+1], buffer[offset+2], buffer[offset+3], buffer[offset+4], buffer[offset+5], highbit, low4Bytes ); #endif } else { //mpeg2 header PACK or GOP unsigned long sys_clock_ref; highbit= (buffer[offset] & 0x20) >> 5; if (pack) { #ifdef _DEBUG fprintf(stderr,"NO gop!\n"); #endif low4Bytes = ((buffer[offset] & 0x18) >> 3) << 30; low4Bytes |= (buffer[offset] & 0x03) << 28; low4Bytes |= buffer[offset + 1] << 20; low4Bytes |= ((buffer[offset + 2] & 0xF8)) << 12; low4Bytes |= (buffer[offset + 2] & 0x03) << 13; low4Bytes |= buffer[offset + 3] << 5; low4Bytes |= (buffer[offset + 4]) >> 3; } else // a GOP { // move the 32 bit in a long low4Bytes = ( (buffer[offset] & 0x7c) >> 2) << 24; low4Bytes |= (buffer[offset] & 0x3) << 20; low4Bytes |= (buffer[offset +1 ] & 0xF0) << 12; low4Bytes |= (buffer[offset +1 ] & 0x7) << 11; low4Bytes |= (buffer[offset +2 ] & 0xE0) << 3; low4Bytes |= (buffer[offset +2 ] & 0x1F) << 1; low4Bytes |= (buffer[offset +3 ] & 0x80) >> 7; } sys_clock_ref=(buffer[offset + 4] & 0x3) << 7; sys_clock_ref|=(buffer[offset + 5] >> 1); if (pack) { TS = (double)(highbit * FLOAT_0x10000 * FLOAT_0x10000); TS += (double)(low4Bytes); // + (double) ((double) sys_clock_ref / 512); } else { // I love "nix" nix = (byte *) &low4Bytes; TS = 60 * 60 * *nix; TS += 60 * *(nix +1); TS += *(nix +2); TS += ((double) *(nix +3)) / 60; } if (pack) { if (sys_clock_ref == 0) { TS /= (double)(STD_SYSTEM_CLOCK_FREQ); #ifdef _DEBUG_ fprintf(stderr,"**ts divided by std_sysclock_fewq, now: %lf\n",TS); #endif } else { // this is what I understood... CHECK // if not zero, then we have a 27 MHz accuracy with a max of 27 MHz // so clockfreq might well be 27MHz / sys_clock_ref // this is nonsense ... // sysclockref is only the remainder of the division of 27MHZ/300 // I guess we can safely ignore it // fprintf(stderr,"syslockref: %ld\n",sys_clock_ref); // TS /= (double)(27000000 / sys_clock_ref); TS /= (double)(STD_SYSTEM_CLOCK_FREQ); // if sysclock ref != 0, this is the remainder of the divison of 27mhz by300 #ifdef _DEBUG_ fprintf(stderr,"XXts divided by sys_clock_ref, now: %lf\n",TS); #endif } } //debug #ifdef _DEBUG_ printf("TS2 : base : 0x%d,%032lx ref : %016lx\n",highbit,low4Bytes,sys_clock_ref); printf ("TS2 : %lf\n",TS); fprintf(stderr,"\nTS mpeg 2 : %02x, %02x %02x %02x %02x, %lx [%lx]\n", highbit, byte((low4Bytes>>24)&0xFF), byte((low4Bytes>>16)&0xFF), byte((low4Bytes>>8)&0xFF), byte((low4Bytes)&0xFF), sys_clock_ref, (unsigned long) (offset) ); fprintf(stderr,"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x highBit=%d low4Bytes=%ld sysclockref=%ld\n", buffer[offset-4], buffer[offset-3], buffer[offset-2], buffer[offset-1], buffer[offset-0], buffer[offset+1], buffer[offset+2], buffer[offset+3], buffer[offset+4], buffer[offset+5], highbit, low4Bytes, sys_clock_ref ); #endif *ts=TS; } //DBG // fprintf(stderr,"------ TS = %f ",TS); } void mpegOutWithVideo::memWriteTS (long offset, double ts, bool mpeg2pack, bool pack){ BTRACK; // fprintf(stderr, " ts is %f\n",ts); byte uppercode = buffer[offset] & 0xF0; byte hiBit; long lowInt=0; double TS=ts; int hour; int minute; int sec; int pics; if (!mpeg2pack) { ; } TS *= STD_SYSTEM_CLOCK_FREQ; if (TS > FLOAT_0x10000 * FLOAT_0x10000) { hiBit = 1; TS -= FLOAT_0x10000 * FLOAT_0x10000; } else { hiBit = 0; lowInt = (long) TS; } if (!mpeg2pack){ uppercode = uppercode | (hiBit << 3) | ((lowInt & 0xC0000000) >> 29) | 0x01; lowInt = 0x00010001 | ((lowInt & 0x3FFF8000) << 2) | ((lowInt & 0x00007FFF) << 1); buffer[offset] = uppercode; buffer[offset+1] = (byte)(lowInt>>24); buffer[offset+2] = (byte)((lowInt>>16)&0xFF); buffer[offset+3] = (byte)((lowInt>>8)&0xFF); buffer[offset+4] = (byte)(lowInt&0xFF); } else { if (pack) { // mpeg 2 PACK byte work; work = 0x40; //marker bit work |= hiBit << 5; //hiBit work |= lowInt >> 27 ; // two MSBs work |= 0x04; //marker bit work &= 0xFC; // clear the two LSB work |= (lowInt >> 28) & 0x03; // two more MSBs buffer[offset] = work; // marker buffer[offset+1] = (byte)((lowInt>>20)&0xFF); buffer[offset+2] = (byte)((((lowInt>>12)&0xF8))|((lowInt>>13)&0x03)|0x04); buffer[offset+3] = (byte)((lowInt>>5)&0xFF); buffer[offset+4] = (byte)(((lowInt<<3)&0xFF)|0x04); buffer[offset+5] = 0x01;//sys clock ref extension =0 } else { // mpeg2 GOP hour = int(TS / 60 / 60); minute = int(TS / 60); sec = int(TS); pics = int((TS - ((long) TS)) * 60); buffer[offset] &= 0x7f; // clear hour & 2 bits from minute buffer[offset +1] &= 0x8; // clear minutes & seconds buffer[offset +2] &= 0; buffer[offset +3] &= 0x7f; buffer[offset] |= ( hour << 2); buffer[offset] |= ( minute >> 4); buffer[offset +1] |= (( minute & 0xf) << 4); buffer[offset +1] |= ( sec >> 3); buffer[offset +2] |= ( sec & 0x7) << 5; buffer[offset +2] |= ( pics >> 1); buffer[offset +3] |= ( pics & 0x1) << 7; } } // fprintf(stderr,"TS Write %lf ------\n",ts); //if (mpeg2pack) { // fprintf(stderr,"\n xxxxxxxxxxx"); // memReadTS(offset,&ts9,true,true); // fprintf(stderr," xxxxxxxxxxxx\n"); //} } int mpegOutWithVideo::memReadPktTS(long* off, double* pts, double* dts, long bufferlength) { BTRACK; //just after the packet start code. and the length field byte mybyte; off_t offset=*off; //get rid of stuffing bytes mybyte=buffer[offset]; if (mpeg_version != 2) // currenlty I dont believe in stuffing bytes here in case of mpeg2! { // also stuffing bytes should be FF and not 80 ? // next time check if this is not better with mpeg1 also....! while((mybyte & 0x80) && (offset <= bufferlength - 5)) { //this has to be a stuffing byte // fprintf(stderr,"removed a stuffing byte ??\n"); mybyte = buffer[++offset]; } } //here mybyte is the first valid byte if (mpeg_version == 2){ //skip the first byte ++offset; mybyte = buffer[offset]; mybyte >>= 6; switch (mybyte) { case 0: return 0; case 1: #ifdef _DEBUG_ fprintf(stderr,"Invalid PTS DTS flag at [" _OFF_x "]\n", offset); #endif return 0; case 2: //only PTS; if (offset > bufferlength - 7) { // we have a valid header but no room to read the entire TS // fprintf(stderr,"Copy Buffer-problem! -1\n"); return -1; } offset += 2; memReadTS(offset,pts); offset += 5; *off = offset; return 1; case 3: //both PTS and DTS if (offset > bufferlength - 5) { // we have a valid header but no room to read the entire TS // fprintf(stderr,"Copy Buffer-problem! -1\n"); return -1; } offset += 2; memReadTS(offset, pts); offset += 5; if (offset > bufferlength - 5) { // we have a valid header but no room to read the entire TS // fprintf(stderr,"Copy Buffer-problem! -1\n"); return -1; } memReadTS(offset, dts); offset += 5; *off = offset; return 2; } //switch return 0; } else { // MPEG 1 if ((mybyte >> 6) == 0x01) { //std buffer scale stuff... let's skip it offset += 2; mybyte = buffer[offset]; } if ((mybyte >> 4) == 0x02) { // dts Time stamp if (offset > bufferlength - 5) { // we have a valid header but no room to read the entire TS // fprintf(stderr,"Copy Buffer-problem! -1\n"); return -1; } //DBG // printf("PTS "); memReadTS(offset, pts); offset += 5; *off = offset; return 1; } else if ((mybyte >> 4) == 0x03) { //both pts and dts time stamps if (offset > bufferlength - 5) { // we have a valid header but no room to read the entire TS // fprintf(stderr,"Copy Buffer-problem! -2\n"); return -1; } *off = offset; //DBG // printf("PTS "); memReadTS(offset, pts); offset += 5; if (offset > bufferlength - 5) { // we have a valid header but no room to read the entire TS *off = offset; return 1; //1 for one valid TS found } //DBG // printf("DTS "); memReadTS(offset, dts); offset += 5; *off = offset; return 2; } } return 0; } mpegOut* mpegOutFactory::NewMpegFrom(mpeg* MpegIn, char* filename){ BTRACK; mpegOut* object; switch(MpegIn->MpegType) { case mpeg_AUDIO: object = new mpegAudioOut(filename); break; case mpeg_VIDEO: object = new mpegVideoOut(filename); break; case mpeg_SYSTEM: object = new mpegSystemOut(filename); break; default: object = 0; break; } if (object) { if (object->OutFile()) object->WriteHeader(MpegIn); else { delete object; object = 0; } } return object; } mpegOut* mpegOutFactory::NewMpegFrom(mpeg* MpegIn, FILE* filehandle){ BTRACK; mpegOut* object; switch (MpegIn->MpegType) { case mpeg_AUDIO: object = new mpegAudioOut(filehandle); break; case mpeg_VIDEO: object = new mpegVideoOut(filehandle); break; case mpeg_SYSTEM: object = new mpegSystemOut(filehandle); break; default: object = 0; break; } if (object) object->WriteHeader(MpegIn); return object; } /* class demuxer{ public: demuxer(mpeg* _Mpeg,char* videofile, char* audiofile); WriteChunk(off_t from, off_t to, bool from_included, bool to_included); protected: demuxer(){}; FILE* AudioOut; FILE* VideoOut; mpeg* Mpeg; }; */ demuxer::demuxer(mpeg* _Mpeg, char* _basename, bool _confirm) :n_audio(0),n_video(0),n_programs(0),Mpeg(_Mpeg),confirm(_confirm),buffer(0) { BTRACK; basename = new char[strlen(_basename) + 1]; strcpy(basename,_basename); // convention for Audiofile and Videofile : // if Audiofile[i]==0 : file is to be opened with basename // if Audiofile[i]==-1 stream is to be ignored. // this way piping a stream to stdout is eq to Audiofile[i]=stdout for(int i = 0; i < 16; i++){ AudioFile[i] = VideoFile[i] = 0; } } demuxer::~demuxer() { BTRACK; if (buffer) delete[]buffer; for (int i = 0; i < 16; i++) { if (AudioFile[i]) fclose(AudioFile[i]); if (VideoFile[i]) fclose(VideoFile[i]); } } int demuxer::Process(){ BTRACK; if (Mpeg == 0) return 0; // fprintf(stderr,"start demux run \n"); if (Mpeg->MpegType == mpeg_SYSTEM) { // fprintf(stderr,"ProcessProgramStream\n"); return ProcessProgramStream(); } if (Mpeg->MpegType == mpeg_TRANSPORT) { // fprintf(stderr,"ProcessTransportStream\n"); return ProcessTransportStream(); } //else :) fprintf(stderr,"mpeg file %s can not be demultiplexed" " (neither System nor Program stream)\n", Mpeg->FileName); return 0; } int demuxer::ProcessTransportStream() { BTRACK; if (!Mpeg->Transport) return 0; int pr; int stream_num; off_t offset = 0; off_t FileSize = Mpeg->Size(); PID pid; EStream *currentStream; off_t start, end; n_programs = Mpeg->Transport->n_progs; int feedback = 0; while (true) { pid = Mpeg->NextTrPacket(&offset,&start,&end); if (start == -1) { if (print_progress){ fprintf(stderr," Demultiplexing : [Programs %02d audio %02d video %02d] [100.00%%]\n", n_programs,n_audio,n_video); } return n_audio + n_video; } if (start == end) continue; for (pr = 0; pr < Mpeg->Transport->n_progs; pr++) { currentStream = Mpeg->Transport->programs[pr].TStreams; stream_num = 0; while (currentStream !=0){ stream_num++; if (currentStream->pid == pid) { // this is the good one if (currentStream->demuxFileOk) { if (currentStream->demuxFile == 0x0) { // file is not created char* tempname = new char[300]; sprintf(tempname, "%s-%d-%d.", basename, Mpeg->Transport->programs[pr].prog_num, stream_num); switch (currentStream->type) { case 1: strcat(tempname, "m1v"); n_video++; break; case 2: strcat(tempname, "m2v"); n_video++; break; case 3: strcat(tempname, "mp3"); n_audio++; break; case 4: strcat(tempname, "mp3"); n_audio++; break; default: strcat(tempname, "unk"); break; } currentStream->demuxFile = openfile(tempname); delete[] tempname; } // if currentStream->demuxFile still 0 : problem if (currentStream->demuxFile == 0x0) { fprintf(stderr, "skipping Program %d stream %d\n", Mpeg->Transport->programs[pr].prog_num, stream_num); currentStream->demuxFileOk = false; } else { // Copy(currentStream->demuxFile,start,end); DemuxTrPkt(currentStream->demuxFile, start, end); if ((feedback++ == 100)) { feedback = 0; if (print_progress){ fprintf(stderr, " Demultiplexing : [Programs %02d audio %02d video %02d] [%6.2f%%]\r", n_programs, n_audio, n_video, offset*100.0/FileSize); } } } //else } //if } //if currentStream = currentStream->next; } //while } //for #ifdef _DEBUG_ // printf("PID %d has payload [%llx %llx]\n", pid, start, end); #endif } //while (true) return 0; } int demuxer::DemuxTrPkt(FILE* out, off_t start, off_t end){ BTRACK; // we have a transport packet, let's remove the program packet headers marker mark; off_t packetheader = Mpeg->FindNextMarker(start, &mark); off_t packetend = Mpeg->SkipPacketHeader(packetheader); mark &= 0xF0; if (mark==0xC0 || mark==0xE0 || mark==0xD0) { if (packetheader < 0 || packetheader > end) { // no packet header in the boundaries Copy(out, start, end); return 0; } if (packetend > end) { //serious problem return -1; } //here we have to issue two Copy Copy(out, start, packetheader); Copy(out, packetend, end); return 1; } else { Copy(out, start, end); return 1; } } int demuxer::ProcessProgramStream(){ BTRACK; marker mark; off_t from, to; off_t FileSize = Mpeg->Size(); off_t bytestoskip = 1; FILE* outfile; char* filename; int streamnumber; off_t offset; int progress = 0; // fprintf(stderr,"sizeof Mpeg->Size(): %ld \n", sizeof(Mpeg->Size())); // fprintf(stderr,"Mpeg->Size(): %qd \n", Mpeg->Size()); for (offset = 0; offset < Mpeg->Size(); offset += bytestoskip) { // fprintf(stderr,"Mpeg->Size(): %qd, offset: %qd\n", Mpeg->Size(), offset); offset = Mpeg->FindNextMarker(offset,&mark); // fprintf(stderr,"ok, next marker found offset: %qd\n",offset); if (offset == -1) { // either we finished or unrecoverable error if (print_progress){ fprintf(stderr," Demultiplexing : [audio %02d video %02d] [100.00%%]\n", n_audio,n_video); } return n_audio+n_video; } ++progress; if ((print_progress) && (progress % 100 == 0)){ progress = 0; fprintf(stderr," DemultiplexingXXX : [audio %02d video %02d] [%6.2f%%]\r", n_audio,n_video, offset*100.0/FileSize); } fflush(stderr); if (((mark&0xF0) == 0xC0) || ((mark&0xF0) == 0xD0)) { //new in mpeg 2 : audio streams are : 110x xxxx //audio packet streamnumber = mark&0x0F; if (AudioFile[streamnumber]) { //file is already opened or stream has to be ignored } else { //file has to be opened filename = new char[300]; n_audio++; sprintf(filename,"%s-%d.mp%d", basename, streamnumber, Mpeg->Audio->layer); AudioFile[streamnumber] = openfile(filename); delete[] filename; } outfile = AudioFile[streamnumber]; } else if ((mark&0xF0)==0xE0){ // fprintf(stderr,"here 01\n"); //video packet streamnumber=mark&0x0F; if (VideoFile[streamnumber]){ //file is already opened } else{ //file has to be opened filename=new char[300]; n_video++; sprintf(filename,"%s-%d.m%dv",basename,streamnumber,Mpeg->mpeg_version); VideoFile[streamnumber]=openfile(filename); delete[] filename; } outfile=VideoFile[streamnumber]; } else { //neither Audio nor Video continue; } // fprintf(stderr,"here 02\n"); //whatever it is it outfile mustn't be 0 nor 1 // if outfile is still 0 there was a problem opening it // if outfile is -1 we were asked to skip it if (outfile==0 || outfile==(FILE*)(0x1)) { // fprintf(stderr,"skipped stream %x\n",mark); continue; } // now we have to find out where it begins and where it ends int length = ((Mpeg->Byte(offset+4)<<8) | Mpeg->Byte(offset+5)); from = Mpeg->SkipPacketHeader(offset); to = offset + length + 6; if (to <= from) { fprintf(stderr, "Erroneous packet size, skipping\n"); offset++; continue; } START_CLOCK Copy(outfile, from, to); STOP_CLOCK(COPY) offset = to - 1; if (to >= FileSize) offset = FileSize; } START_CLOCK if ((print_progress ) && (progress % 1000 == 0)){ progress = 0; fprintf(stderr," Demultiplexing: [audio %02d video %02d] [100.00%%]\n", n_audio,n_video); } STOP_CLOCK(PRINTF) return 1; } off_t demuxer::Copy(FILE* into, off_t from, off_t to) { BTRACK; off_t size = to -from; off_t read_size = 0; // float percent; // fprintf(stderr,"Starting copy @%lx\n",ftell(MpegOut)); size_t size2read=(size>COPYBUFFERSIZE)?COPYBUFFERSIZE:size; if(!buffer) buffer= new byte[COPYBUFFERSIZE]; while (read_size < size) { size2read = ((size-read_size) > COPYBUFFERSIZE)?COPYBUFFERSIZE:size-read_size; FSEEK(Mpeg->MpegFile, from + read_size, SEEK_SET); read_size += fread(buffer, 1, size2read, Mpeg->MpegFile); fwrite(buffer, 1, size2read, into); // if(print_progress){ //lperc=(read_size*100)/(size/100); // percent= (read_size*1.0)/(size/100); // fprintf(stderr,"\b\b\b\b\b\b\b\b%5.2f%% ",percent); // fflush(stderr); // } } // delete buffer; return to; } FILE* demuxer::openfile(char* filename) { BTRACK; FILE* temp; if (!confirm){ temp = fopen(filename, "wb"); if (temp==0){ // problem fprintf(stderr,"\n"); perror(filename); } return temp; } else { //must check if file exist temp = fopen(filename, "rb"); if (temp != 0) { //file is readable, it exists fprintf(stderr,"file %s exists, overwrite ? [N/y/a]: \b\b\b\b",filename); fflush(stderr); char answer = getchar(); switch (answer) { case 'a': case 'A': confirm = false; break; case 'y': case 'Y': temp = fopen(filename, "wb"); if (temp == 0) { // problem fprintf(stderr, "\n"); perror(filename); } return temp; break; // default: return 0; default: fprintf(stderr,"Aborted\n"); exit(1); } //switch } else { //file does not exist temp = fopen(filename, "wb"); if (temp == 0) { // problem fprintf(stderr, "\n"); perror(filename); } return temp; } } fprintf(stderr,"we should not get here!\n"); return NULL; } void print_ts(byte *p) { int hour, min, sec, pictures, drop, closed, broken; byte *head; head = (byte *) (p); // calculate GOP information .. this is from gop Chop, thanks! /* 4 5 6 7 | | | | 7 65432 107654 3 210765 432107 6 543210 1 11111 111111 1 111111 111111 1 1 d hour min m sec pic c b r a l roken o r osed p k */ fprintf(stderr,"data: %2x %2x %2x %2x\n",head[0],head[1],head[2],head[3]); drop=((head[0]&0x80)>0); hour=((head[0]&0x7C)>>2); min=((head[0]&0x3)<<4)|((head[1]&0xF0)>>4); sec=((head[1]&0x7)<<3)|((head[2]&0xE0)>>6); pictures=((head[2]&0x3F)<<1)|((head[3]&0x80)>>7); closed=((head[3]&0x40)>0); broken=((head[3]&0x20)>0); fprintf(stderr,"TS mpg2 INFO: %02d:%02d:%02d.%02d\n",hour,min,sec,pictures); }