/** * * @param p */ void show_info(char *p) { UNUSED_ARG(p); uint32_t war,har; const char *s; if (avifileinfo) { printf("Video\n"); printf(" Video Size: %u x %u\n", avifileinfo->width, avifileinfo->height); printf(" Frame Rate: %2.3f fps\n", (float)avifileinfo->fps1000/1000.F); printf(" Number of frames: %d frames\n", avifileinfo->nb_frames); printf(" Codec FourCC: %s\n", fourCC::tostring(avifileinfo->fcc)); if(avifileinfo->nb_frames){ uint32_t hh, mm, ss, ms; frame2time(avifileinfo->nb_frames, avifileinfo->fps1000,&hh, &mm, &ss, &ms); printf(" Duration: %02d:%02d:%02d.%03d\n", hh, mm, ss, ms); }else{ printf(" Duration: 00:00:00.000\n"); } war=video_body->getPARWidth(); har=video_body->getPARHeight(); getAspectRatioFromAR(war,har, &s); printf(" Aspect Ratio: %s (%u:%u)\n", s,war,har); printf("Audio\n"); ADM_audioStream *s; WAVHeader *wavinfo=NULL; video_body->getDefaultAudioTrack(&s); if(s ) { wavinfo=s->getInfo(); } if( wavinfo ) { printf(" Codec: %s\n",getStrFromAudioCodec(wavinfo->encoding)); printf(" Mode: "); switch( wavinfo->channels ){ case 1: printf("MONO\n"); break; case 2: printf("STEREO\n"); break; default: printf("????\n"); break; } printf(" BitRate: %u Bps / %u kbps\n", wavinfo->byterate, wavinfo->byterate*8/1000); printf(" Frequency: %u Hz\n", wavinfo->frequency); }else{ printf(" Codec: NONE\n"); printf(" Mode: NONE\n"); printf(" BitRate: NONE\n"); printf(" Frequency: NONE\n"); printf(" Duration: NONE\n"); } } else { printf("Nothing to get infos from\n"); } }
//_________________________________________________________________ // // Set up audio system //_________________________________________________________________ uint8_t GenericAviSave::setupAudio (void) { // 1- Prepare audio filter //__________________________ _audioInBuffer = 0; _audioTarget=_audioCurrent=0; _audioTotal=0; audio_filter=NULL; if(!currentaudiostream) { encoding_gui->setAudioCodec("None"); return 1; } printf (" mux mode : %d mux param %d\n", muxMode, muxParam); if (audioProcessMode) // else Raw copy mode { if (currentaudiostream->isCompressed ()) { if (!currentaudiostream->isDecompressable ()) { GUI_Alert ("I cannot decompress that \n audio stream!"); return 0; } } audio_filter = buildAudioFilter (currentaudiostream,video_body->getTime (frameStart), (uint32_t) 0xffffffff); // if ((audio_filter)->getInfo ()->encoding == WAV_PCM) // // if (!GUI_Question ("Audio stream is not compressed\n Continue?")) // // { // // deleteAudioFilter (); // // return 0; // // } encoding_gui->setAudioCodec(getStrFromAudioCodec(audio_filter->getInfo()->encoding)); } else // copymode { // else prepare the incoming raw stream // audio copy mode here int32_t shift=0; if(audioDelay && audioShift) shift=audioDelay; encoding_gui->setAudioCodec("Copy"); audio_filter=buildRawAudioFilter( video_body->getTime (frameStart), 0xffffffff, shift); } return 1; }
void show_info(char *p){ UNUSED_ARG(p); uint32_t war,har; const char *s; if (avifileinfo) { printf("Video\n"); printf(" Video Size: %u x %u\n", avifileinfo->width, avifileinfo->height); printf(" Frame Rate: %2.3f fps\n", (float)avifileinfo->fps1000/1000.F); printf(" Number of frames: %d frames\n", avifileinfo->nb_frames); printf(" Codec FourCC: %s\n", fourCC::tostring(avifileinfo->fcc)); if(avifileinfo->nb_frames){ uint16_t hh, mm, ss, ms; frame2time(avifileinfo->nb_frames, avifileinfo->fps1000,&hh, &mm, &ss, &ms); printf(" Duration: %02d:%02d:%02d.%03d\n", hh, mm, ss, ms); }else{ printf(" Duration: 00:00:00.000\n"); } war=video_body->getPARWidth(); har=video_body->getPARHeight(); getAspectRatioFromAR(war,har, &s); printf(" Aspect Ratio: %s (%u:%u)\n", s,war,har); printf("Audio\n"); if( wavinfo ) { printf(" Codec: %s\n",getStrFromAudioCodec(wavinfo->encoding)); printf(" Mode: "); switch( wavinfo->channels ){ case 1: printf("MONO\n"); break; case 2: printf("STEREO\n"); break; default: printf("????\n"); break; } printf(" BitRate: %u Bps / %u kbps\n", wavinfo->byterate, wavinfo->byterate*8/1000); printf(" Frequency: %u Hz\n", wavinfo->frequency); { double du = video_body->getAudioLength(); uint16_t hh, mm, ss, ms; du*=1000; du/=wavinfo->byterate; ms2time((uint32_t)floor(du), &hh, &mm, &ss, &ms); printf(" Duration: %02d:%02d:%02d.%03d (%lu MBytes)\n", hh, mm, ss, ms, video_body->getAudioLength()>>20); } }else{ printf(" Codec: NONE\n"); printf(" Mode: NONE\n"); printf(" BitRate: NONE\n"); printf(" Frequency: NONE\n"); printf(" Duration: NONE\n"); } }
/** \fn initUI \brief initialize the progress bar */ bool ADM_muxer::initUI(const char *title) { bool useTray = false; if (!prefs->get(FEATURES_USE_SYSTRAY, &useTray)) useTray = false; videoIncrement=vStream->getFrameIncrement(); // Video increment in AVI-Tick videoDuration=vStream->getVideoDuration(); ADM_info("Muxer, creating UI, video duration is %s\n",ADM_us2plain(videoDuration)); encoding=createEncoding(videoDuration,useTray); // Set video stream etc... encoding->setVideoCodec(fourCC::tostring(vStream->getFCC())); if(!nbAStreams) encoding->setAudioCodec("None"); else encoding->setAudioCodec(getStrFromAudioCodec(aStreams[0]->getInfo()->encoding)); return true; }
//_________________________________________________________________ // // Set up audio system //_________________________________________________________________ uint8_t GenericAviSave::setupAudio (void) { // 1- Prepare audio filter //__________________________ _audioInBuffer = 0; _audioTarget=_audioCurrent=0; _audioTotal=0; audio_filter=NULL; if(!currentaudiostream) { encoding_gui->setAudioCodec(QT_TR_NOOP("None")); return 1; } printf (" mux mode : %d mux param %d\n", muxMode, muxParam); if (audioProcessMode()) // else Raw copy mode { audio_filter = buildAudioFilter (currentaudiostream,video_body->getTime (frameStart)); if(!audio_filter) return 0; encoding_gui->setAudioCodec(getStrFromAudioCodec(audio_filter->getInfo()->encoding)); } else // copymode { // else prepare the incoming raw stream // audio copy mode here encoding_gui->setAudioCodec(QT_TR_NOOP("Copy")); audio_filter=buildAudioFilter( currentaudiostream,video_body->getTime (frameStart)); if(!audio_filter) return 0; } /* Setup audioQ */ pthread_t audioThread; _pq=new PacketQueue("AVI audioQ",5000,2*1024*1024); memset(&_context,0,sizeof(_context)); _context.audioEncoder=audio_filter; _context.audioTargetSample=0xFFFF0000; ; //FIXME _context.packetQueue=_pq; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&_context)); ADM_usleep(4000); return 1; }
uint8_t oplug_mpegff(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming; Encoder *encoder=NULL; ADMMpegMuxer *muxer=NULL; FILE *file=NULL; uint8_t audioBuffer[48000]; uint32_t audioLen=0; uint32_t _w,_h,_fps1000,_page,total; AVDMGenericAudioStream *audio=NULL; uint32_t len,flags; uint32_t size; ADM_MUXER_TYPE mux; uint32_t audio_encoding=0; uint32_t real_framenum=0; uint8_t ret=0; uint32_t sample_target=0; uint32_t total_sample=0; ADMBitstream bitstream(0); uint32_t audioSum=0; DIA_encoding *encoding; int reuse = 0; twoPass=new char[strlen(name)+6]; twoFake=new char[strlen(name)+6]; strcpy(twoPass,name); strcat(twoPass,".stat"); strcpy(twoFake,name); strcat(twoFake,".fake"); _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _w=_incoming->getInfo()->width; _h=_incoming->getInfo()->height; _fps1000=_incoming->getInfo()->fps1000; _page=_w*_h; _page+=_page>>1; total=_incoming->getInfo()->nb_frames; if(!total) return 0; switch(type) { default: ADM_assert(0); case ADM_ES: // Else open file (if possible) mux=MUXER_NONE; break; case ADM_TS: if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); goto finishvcdff; } audio=mpt_getAudioStream(); mux=MUXER_TS; break; case ADM_PS: { if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); goto finishvcdff; } audio=mpt_getAudioStream(); // Have to check the type // If it is mpeg2 we use DVD-PS // If it is mpeg1 we use VCD-PS // Later check if it is SVCD if(!audio) { GUI_Error_HIG(QT_TR_NOOP("Audio track is not suitable"), NULL); goto finishvcdff; } // Check WAVHeader *hdr=audio->getInfo(); audio_encoding=hdr->encoding; if (videoCodecGetType() == CodecXVCD || videoCodecGetType() == CodecVCD) { if(hdr->frequency!=44100 || hdr->encoding != WAV_MP2) { GUI_Error_HIG(("Incompatible audio"),QT_TR_NOOP( "For VCD, audio must be 44.1 kHz MP2.")); goto finishvcdff; } mux=MUXER_VCD; printf("X*CD: Using VCD PS\n"); }else { aviInfo info; video_body->getVideoInfo(&info); if(hdr->frequency==44100 && _w==480&&hdr->encoding == WAV_MP2 ) // SVCD ? { mux=MUXER_SVCD; printf("X*VCD: Using SVCD PS\n"); } else { // mpeg2, we do only DVD right now if(hdr->frequency!=48000 || (hdr->encoding != WAV_MP2 && hdr->encoding!=WAV_AC3 && hdr->encoding!=WAV_LPCM)) { GUI_Error_HIG(QT_TR_NOOP("Incompatible audio"), QT_TR_NOOP("For DVD, audio must be 48 kHz MP2, AC3 or LPCM.")); goto finishvcdff; } mux=MUXER_DVD; printf("X*VCD: Using DVD PS\n"); } } } } // Create muxer switch (videoCodecGetType()) { case CodecXVCD: encoder=new EncoderFFMPEGMpeg1(FF_MPEG1,&ffmpeg1Codec); printf("\n Using ffmpeg mpeg1 encoder\n"); break; case CodecXSVCD: encoder=new EncoderFFMPEGMpeg1(FF_MPEG2,&ffmpeg2SVCDCodec); printf("\n Using ffmpeg mpeg2 encoder\n"); break; case CodecXDVD: encoder=new EncoderFFMPEGMpeg1(FF_MPEG2,&ffmpeg2DVDCodec); printf("\n Using ffmpeg mpeg2 encoder (DVD)\n"); break; case CodecDVD: encoder=new EncoderMpeg2enc(MPEG2ENC_DVD,&DVDCodec); printf("\n Using mpeg2enc encoder (DVD)\n"); break; case CodecRequant: if(!isMpeg12Compatible(avifileinfo->fcc)) { GUI_Error_HIG("Incompatible Input","The input file must be mpeg2 to be able to use requant!"); return 0; // Fixme, do some cleanup } encoder=new EncoderRequant(&RequantCodec); printf("\n Using mpeg2 requant\n"); break; break; case CodecSVCD: encoder=new EncoderMpeg2enc(MPEG2ENC_SVCD,&SVCDCodec); printf("\n Using mpeg2enc encoder (SVCD)\n"); break; case CodecVCD: encoder=new EncoderMpeg2enc(MPEG2ENC_VCD,&VCDCodec); printf("\n Using mpeg2enc encoder (VCD)\n"); break; default: ADM_assert(0); } encoder->setLogFile(twoPass,total); if (encoder->isDualPass()) { printf("Verifying log file\n"); if (encoder->verifyLog(twoPass, total) && GUI_Question(QT_TR_NOOP("Reuse the existing log file?"))) reuse = 1; } if(!encoder->configure(_incoming, reuse)) goto finishvcdff; _buffer=new uint8_t[_page]; // Might overflow if _page only _outbuffer=new uint8_t[_page]; ADM_assert( _buffer); ADM_assert( _outbuffer); encoding =new DIA_encoding(_fps1000); switch (videoCodecGetType()) { case CodecVCD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc VCD")); break; case CodecSVCD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc SVCD")); break; case CodecDVD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc DVD")); break; case CodecXVCD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-1 VBR")); break; case CodecXSVCD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-2 SVCD VBR")); break; case CodecXDVD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-2 DVD VBR")); break; case CodecRequant: encoding->setCodec(QT_TR_NOOP("MPEG Requantizer")); break; default: ADM_assert(0); } switch(mux) { case MUXER_NONE:encoding->setContainer(QT_TR_NOOP("MPEG ES"));break; case MUXER_TS: encoding->setContainer(QT_TR_NOOP("MPEG TS"));break; case MUXER_VCD: encoding->setContainer(QT_TR_NOOP("MPEG VCD"));break; case MUXER_SVCD:encoding->setContainer(QT_TR_NOOP("MPEG SVCD"));break; case MUXER_DVD: encoding->setContainer(QT_TR_NOOP("MPEG DVD"));break; default: ADM_assert(0); } // pass 1 if(encoder->isDualPass()) //Cannot be requant { if(!reuse) { encoding->setPhasis (QT_TR_NOOP("Pass 1/2")); encoder->startPass1(); bitstream.data=_buffer; bitstream.bufferSize=_page; for(uint32_t i=0;i<total;i++) { bitstream.cleanup(i); if(!encoder->encode( i, &bitstream))//&len,(uint8_t *) _buffer,&flags)) { GUI_Error_HIG(QT_TR_NOOP("Error in pass 1"), NULL); } encoding->setFrame(i,bitstream.len,bitstream.out_quantizer,total); if(!encoding->isAlive()) goto finishvcdff; } } encoder->startPass2(); encoding->reset(); } switch(type) { case ADM_PS: muxer=new mplexMuxer; break; case ADM_TS: muxer=new tsMuxer; break; case ADM_ES: break; default: ADM_assert(0); } if(muxer) { if(!muxer->open(name,0,mux,avifileinfo,audio->getInfo())) { printf("Muxer init failed\n"); goto finishvcdff; } double sample_time; sample_time=total; sample_time*=1000; sample_time/=_fps1000; // target_time in second sample_time*=audio->getInfo()->frequency; sample_target=(uint32_t)floor(sample_time); } else { file=fopen(name,"wb"); if(!file) { GUI_Error_HIG(QT_TR_NOOP("File error"), QT_TR_NOOP("Cannot open \"%s\" for writing."), name); goto finishvcdff; } } if(encoder->isDualPass()) encoding->setPhasis (QT_TR_NOOP("Pass 2/2")); else encoding->setPhasis (QT_TR_NOOP("Encoding")); // Set info for audio if any if(muxer) { if(!audioProcessMode()) encoding->setAudioCodec(QT_TR_NOOP("Copy")); else encoding->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); } //********************************************************** // In that case we do multithreadedwriting (yes!) //********************************************************** if(mux==MUXER_DVD || mux==MUXER_SVCD || mux==MUXER_VCD) { pthread_t audioThread,videoThread,muxerThread; muxerMT context; // bitstream.data=_outbuffer; bitstream.bufferSize=_page; // memset(&context,0,sizeof(context)); context.videoEncoder=encoder; context.audioEncoder=audio; context.muxer=(mplexMuxer *)muxer; context.nbVideoFrame=total; context.audioTargetSample=sample_target; context.audioBuffer=audioBuffer; context.bitstream=&bitstream; context.opaque=(void *)encoding; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioSlave,&context)); ADM_assert(!pthread_create(&videoThread,NULL,(THRINP)defaultVideoSlave,&context)); while(1) { accessMutex.lock(); if(!encoding->isAlive()) { context.audioAbort=1; context.videoAbort=1; printf("[mpegFF]Waiting for slaves\n"); accessMutex.unlock(); while(1) { accessMutex.lock(); if(context.audioDone && context.videoDone) { printf("[mpegFF]Both audio & video done\n"); if(context.audioDone==1 && context.videoDone==1) ret=1; accessMutex.unlock(); goto finishvcdff; } accessMutex.unlock(); ADM_usleep(50000); } } if(context.audioDone==2 || context.videoDone==2 ) //ERROR { context.audioAbort=1; context.videoAbort=1; } if(context.audioDone && context.videoDone) { printf("[mpegFF]Both audio & video done\n"); if(context.audioDone==1 && context.videoDone==1) ret=1; accessMutex.unlock(); goto finishvcdff; } accessMutex.unlock(); ADM_usleep(1000*1000); } } //********************************************************** // NOT MULTITHREADED //********************************************************** bitstream.data=_outbuffer; bitstream.bufferSize=_page; for(uint32_t i=0;i<total;i++) { // get frame bitstream.cleanup(i); if(!encoder->encode( i,&bitstream))// &len,(uint8_t *) _outbuffer,&flags)) { GUI_Error_HIG(QT_TR_NOOP("Error in pass 2"), NULL); goto finishvcdff; } if(!bitstream.len) continue; if(file) { fwrite(_outbuffer,bitstream.len,1,file); } else { uint32_t samples; //printf("%lu %lu\n",i,dts); muxer->writeVideoPacket(&bitstream); real_framenum++; // _muxer->writeVideoPacket(len,_buffer_out, //i-MPEG_PREFILL,_codec->getCodedPictureNumber()); if(total_sample<sample_target) { while(muxer->needAudio() && total_sample<sample_target) { if(!audio->getPacket(audioBuffer, &audioLen, &samples)) { break; } if(audioLen) { muxer->writeAudioPacket(audioLen,audioBuffer); total_sample+=samples; audioSum+=audioLen; } } } } encoding->setFrame(i,bitstream.len,bitstream.out_quantizer,total); encoding->setAudioSize(audioSum); if(!encoding->isAlive ()) goto finishvcdff; } ret=1; finishvcdff: printf("[MPEGFF] Finishing..\n"); delete encoding; end(); if(file) { fclose(file); file=NULL; } else if(muxer) { muxer->close(); delete muxer; muxer=NULL; } delete encoder; if (audio) deleteAudioFilter(audio); return ret; }
uint8_t mpeg_passthrough(const char *name,ADM_OUT_FORMAT format ) { uint32_t len, flags; AVDMGenericAudioStream *audio=NULL; uint32_t audiolen; DIA_encoding *work; ADM_MUXER_TYPE mux; double total_wanted=0; uint32_t total_got=0; uint8_t ret=0; ADMMpegMuxer *muxer=NULL; ADMBitstream bitstream(0); printf("Saving as mpg PS to file %s\n",name); // First we check it is mpeg if(!isMpeg12Compatible(avifileinfo->fcc)) { GUI_Error_HIG(QT_TR_NOOP("This is not MPEG compatible"), QT_TR_NOOP("You can't use the Copy codec.")); return 0 ; } if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); return 0; } ADM_assert (video_body->getFlags (frameStart, &flags)); if(!(flags&AVI_KEY_FRAME)) { GUI_Error_HIG(QT_TR_NOOP("The first frame is not intra frame"), QT_TR_NOOP("Use the << and the >> buttons to move using Intra frames.")); return 0; } audio=mpt_getAudioStream(); // Have to check the type // If it is mpeg2 we use DVD-PS // If it is mpeg1 we use VCD-PS // Later check if it is SVCD if(!audio) { GUI_Error_HIG(QT_TR_NOOP("Audio track is not suitable"), NULL); return 0; } // Check WAVHeader *hdr=audio->getInfo(); uint32_t isMpeg1; uint32_t isLav; if(!prefs->get(FEATURE_USE_LAVCODEC_MPEG2, &isLav)) { isLav=0; } if(!isLav) { decoderMpeg *mpeghdr; mpeghdr=(decoderMpeg *)video_body->rawGetDecoder(0); isMpeg1=mpeghdr->isMpeg1(); } else { // How to know if it is mpeg 1? // Assume it is not /* decoderFFMpeg12 *mpeghdr; mpeghdr=(decoderFFMpeg12 *)video_body->rawGetDecoder(0); isMpeg1=mpeghdr->isMpeg1(); */ isMpeg1=0; } switch(format) { case ADM_PS: if(isMpeg1) { if(hdr->frequency!=44100 || hdr->encoding != WAV_MP2) { GUI_Error_HIG(QT_TR_NOOP("Incompatible audio"), QT_TR_NOOP("For VCD, audio must be 44.1 kHz MP2.")); return 0 ; } mux=MUXER_VCD; printf("PassThrough: Using VCD PS\n"); }else { // Mpeg2 aviInfo info; video_body->getVideoInfo(&info); if(hdr->frequency==44100 && info.width==480&& hdr->encoding == WAV_MP2 ) // SVCD ? { mux=MUXER_SVCD; printf("PassThrough: Using SVCD PS\n"); } else { uint32_t valid=0; if(!prefs->get(FEATURE_MPEG_NO_LIMIT,&valid)) valid=0; // mpeg2, we do only DVD right now if(hdr->frequency==48000) valid=1; if((hdr->encoding != WAV_MP2 && hdr->encoding!=WAV_AC3 && hdr->encoding!=WAV_LPCM && hdr->encoding!=WAV_DTS)) { valid=0; } if(!valid) { deleteAudioFilter(audio); GUI_Error_HIG(("Incompatible audio"),QT_TR_NOOP( "For DVD, audio must be 48 kHz MP2(stereo), AC3, DTS or LPCM (stereo).")); return 0; } mux=MUXER_DVD; printf("PassThrough: Using DVD PS\n"); } } muxer=new mplexMuxer(); break; case ADM_TS: printf("Using TS output format\n"); muxer=new tsMuxer(); //lavMuxer(); mux=MUXER_TS; break; default: ADM_assert(0); break; } if(!muxer) { printf("No muxer ?\n"); return 0; } if(!muxer->open(name,0,mux,avifileinfo,audio->getInfo())) { delete muxer; muxer=NULL; printf("Muxer init failed\n"); return 0; } // In copy mode it is better to recompute the gop timestamp muxer->forceRestamp(); ///____________________________ work=new DIA_encoding(avifileinfo->fps1000); work->setCodec(QT_TR_NOOP("Copy")); work->setAudioCodec(QT_TR_NOOP("---")); work->setPhasis(QT_TR_NOOP("Saving")); if(!audioProcessMode()) work->setAudioCodec(QT_TR_NOOP("Copy")); else work->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); switch(mux) { case MUXER_TS: work->setContainer(QT_TR_NOOP("MPEG TS"));break; case MUXER_VCD: work->setContainer(QT_TR_NOOP("MPEG VCD"));break; case MUXER_SVCD: work->setContainer(QT_TR_NOOP("MPEG SVCD"));break; case MUXER_DVD: work->setContainer(QT_TR_NOOP("MPEG DVD"));break; default: ADM_assert(0); } uint32_t cur=0; uint32_t target_sample=0; double target_time; aviInfo info; video_body->getVideoInfo(&info); target_time=frameEnd-frameStart+1; target_time*=1000; target_time/=info.fps1000; // target_time in second target_time*=audio->getInfo()->frequency; target_sample=(uint32_t)floor(target_time); uint8_t *buffer = new uint8_t[avifileinfo->width * avifileinfo->height * 3]; uint8_t *audiobuffer = new uint8_t[4*48000*2]; // 2 sec worth of lpcm uint32_t position; EncoderCopy *copy=NULL; bitstream.data=buffer; bitstream.bufferSize=avifileinfo->width * avifileinfo->height * 3; /*************************** Special case : Multithreaded ***************************/ if(mux==MUXER_VCD || mux==MUXER_SVCD || mux==MUXER_DVD) { pthread_t audioThread,videoThread,muxerThread; copy=new EncoderCopy(NULL); muxerMT context; copy->configure(NULL); // memset(&context,0,sizeof(context)); context.videoEncoder=copy; context.audioEncoder=audio; context.muxer=( mplexMuxer *)muxer; context.nbVideoFrame=copy->getNbFrame(); context.audioTargetSample=target_sample; context.audioBuffer=audiobuffer; context.bitstream=&bitstream; context.opaque=(void *)work; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioSlave,&context)); ADM_assert(!pthread_create(&videoThread,NULL,(THRINP)copyVideoSlave,&context)); while(1) { accessMutex.lock(); if(context.audioDone==2 || context.videoDone==2 || !work->isAlive()) //ERROR { context.audioAbort=1; context.videoAbort=1; printf("[Copy] aborting\n"); } if(context.audioDone && context.videoDone) { printf("[Copy]Both audio & video done\n"); if(context.audioDone==1 && context.videoDone==1) ret=1; else ret=0; accessMutex.unlock(); goto _abt; } // Update UI work->setAudioSize(context.feedAudio); context.feedVideo=0; accessMutex.unlock(); ADM_usleep(1000*1000); } } /**************************************************************************************/ /* If we get here, it means output is MPEG_TS */ /* We must use the audio packet Queue */ /**************************************************************************************/ ADM_assert(mux==MUXER_TS); { PacketQueue *pq; uint32_t mx,sample; pthread_t audioThread; copy=new EncoderCopy(NULL); audioQueueMT context; uint8_t r; copy->configure(NULL); pq=new PacketQueue("TS audioQ",5000,2*1024*1024); memset(&context,0,sizeof(context)); context.audioEncoder=audio; context.audioTargetSample=target_sample; context.packetQueue=pq; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); // Go! ADM_usleep(4000); mx=copy->getNbFrame(); printf("Writing %u frames\n",mx); for(int frame=0;frame<mx;frame++) { while(muxer->needAudio()) { if(pq->Pop(audiobuffer,&audiolen,&sample)) { if(audiolen) { muxer->writeAudioPacket(audiolen,audiobuffer); //work->feedAudioFrame(audiolen); } }else break; } ADM_assert(copy); bitstream.cleanup(frame); r=copy->encode ( frame, &bitstream); if(!r) { printf("TS:Frame %u error\n",frame); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); goto stopit; } muxer->writeVideoPacket( &bitstream); work->setFrame(frame,bitstream.len,bitstream.out_quantizer,mx); // work->feedFrame(bitstream.len); if(!work->isAlive()) { goto stopit; } } ret=1; stopit: context.audioAbort=1; pq->Abort(); // Wait for audio slave to be over while(!context.audioDone) { printf("Waiting Audio thread\n"); ADM_usleep(500000); } delete pq; } // End ts case /************************************** TS End *********************************/ _abt: delete work; muxer->close(); delete muxer; delete [] buffer; delete [] audiobuffer; deleteAudioFilter(audio); if(copy) delete copy; return ret; }
//__________________________________________________ uint8_t ADM_ogmWrite::initAudio(void) { uint32_t tstart; WAVHeader *info=NULL; audioStream=NULL; if(!currentaudiostream) { audioFilter=NULL; _audioBuffer=NULL; encoding_gui->setAudioCodec("None"); return 1; } if(audioProcessMode() && currentaudiostream->isCompressed() && !currentaudiostream->isDecompressable()) { return 0; } audioStream=new ogm_page(_fd,2); // audioFilter=buildAudioFilter(currentaudiostream, video_body->getTime (frameStart)); if(!audioFilter) return 0; if(audioProcessMode()) { uint16_t fcc; fcc=audioFilter->getInfo()->encoding; encoding_gui->setAudioCodec(getStrFromAudioCodec(fcc)); } else // Copymode { encoding_gui->setAudioCodec("Copy"); } //______________ Write headers/ Audio..._____________________ _audioBuffer=new uint8_t[OGM_AUDIO_BUFFER*2]; char string[40]; stream_header header; info=audioFilter->getInfo(); if(audioFilter->getInfo()->encoding!=WAV_OGG) { memset(&header,0,sizeof(header)); uint64_t d64; uint32_t d32; uint16_t d16; memcpy(&(header.streamtype),"audio\0\0\0",8); memset(&(header.subtype),0,4); sprintf(string,"%04X",info->encoding); //memcpy(&(header.subtype),&(info->encoding),2); memcpy(&(header.subtype),string,4); printf("audio encoding:%x\n",info->encoding); #define DO(x,y,z) {d##z=y;MEMCPY(&header.x,&d##z,z>>3);} DO(size,sizeof(header),32); //header.size=sizeof(header); //header.audio.channels=info->channels; DO(audio.channels,info->channels,16); // not reliable header.audio.blockalign=info->blockalign; uint16_t bps; uint16_t blkalign; switch(info->encoding) { case WAV_MP3: case WAV_MP2: bps=0; blkalign=1152;break; case WAV_AC3: bps=2; blkalign=1536;break; default: blkalign=info->blockalign; bps=0; break; } DO(audio.blockalign,blkalign,16); DO(bits_per_sample,bps,16); //header.audio.avgbytespersec=info->byterate; DO(audio.avgbytespersec,info->byterate,32); //header.time_unit=(int64_t)10000000; DO(time_unit,10000000LL,64); //header.samples_per_unit=info->frequency; DO(samples_per_unit,info->frequency,64); //header.buffersize=info->frequency; // half a sec DO(buffersize,info->frequency,32); // half a sec //header.default_len=1; DO(default_len,1,32); audioStream->writeHeaders(sizeof(header),(uint8_t *)&header); // +4 ? _audioTarget=_audioCurrent=0; return 1; } else { uint32_t exlen; uint8_t *exdata; if(!audioProcessMode()) { currentaudiostream->extraData(&exlen,&exdata); } else { audioFilter->extraData(&exlen,&exdata); } uint32_t *p; p=(uint32_t *)exdata; if(!exlen || !exdata) { delete audioFilter; audioFilter=NULL; delete audioStream; audioStream=NULL; printf("Vorbis audio setup failed (len:%lu)\n",exlen); return 0; } exdata+=3*sizeof(uint32_t); audioStream->writeDirect(p[0],exdata); // Header exdata+=p[0]; audioStream->writeDirect(p[1],exdata); // Comment exdata+=p[1]; audioStream->writeDirect(p[2],exdata); // Codebook _audioTarget=_audioCurrent=0; return 1; } }
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming=NULL; AVDMGenericAudioStream *audio=NULL; uint8_t audioBuffer[48000]; uint8_t *videoBuffer=NULL; uint32_t alen;//,flags; uint32_t size; uint8_t ret=0; uint32_t sample_got=0,sample; uint32_t extraDataSize=0; uint8_t *extraData=NULL; lavMuxer *muxer=NULL; aviInfo info; uint32_t width,height; DIA_encoding *encoding_gui=NULL; Encoder *_encode=NULL; char *TwoPassLogFile=NULL; uint32_t total=0; uint32_t videoExtraDataSize=0; uint8_t *videoExtraData=NULL; uint8_t *dummy,err; WAVHeader *audioinfo=NULL; int prefill=0; uint32_t displayFrame=0; ADMBitstream bitstream; uint32_t frameWrite=0; ADM_MUXER_TYPE muxerType=MUXER_MP4; uint8_t dualPass=0; uint8_t r=0; uint32_t skipping=1; if(type==ADM_PSP) muxerType=MUXER_PSP; else muxerType=MUXER_MP4; // Setup video if(videoProcessMode()) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); }else { _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart); } videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3]; // Set global header encoding, needed for H264 _encode = getVideoEncoder (_incoming->getInfo()->width, _incoming->getInfo()->height,1); total= _incoming->getInfo()->nb_frames; encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000); if (!_encode) { GUI_Error_HIG (_("Cannot initialize the video stream"), NULL); goto stopit; } // init compressor encoding_gui->setContainer("MP4"); encoding_gui->setAudioCodec("None"); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,total); if (!_encode->configure (_incoming)) { GUI_Error_HIG (_("Filter init failed"), NULL); goto stopit; }; dualPass=_encode->isDualPass(); if(dualPass) { if(!prepareDualPass(videoBuffer,TwoPassLogFile,encoding_gui,_encode,total)) goto stopit; }else { encoding_gui->setPhasis ("Encoding"); } info.width=_incoming->getInfo()->width; info.height=_incoming->getInfo()->height; info.nb_frames=_incoming->getInfo()->nb_frames; info.fps1000=_incoming->getInfo()->fps1000; info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy); if(videoExtraDataSize) { printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize); videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,dummy,videoExtraDataSize); } // _________________Setup video (cont) _______________ // ___________ Read 1st frame _________________ ADM_assert(_encode); bitstream.data=videoBuffer; preFilling: bitstream.cleanup(0); if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame)) { printf("MP4:First frame error\n"); GUI_Error_HIG (_("Error while encoding"), NULL); goto stopit; } if(!bitstream.len) { prefill++; goto preFilling; } if(!bitstream.flags & AVI_KEY_FRAME) { GUI_Error_HIG (_("KeyFrame error"),_( "The beginning frame is not a key frame.\nPlease move the A marker.")); goto stopit; } //len=bitstream.len; // If needed get VOL header if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len) { // And put them as extradata for esds atom uint32_t voslen=0; if(extractVolHeader(videoBuffer,bitstream.len,&voslen)) { if(voslen) { videoExtraDataSize=voslen; videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,videoBuffer,videoExtraDataSize); } } else printf("Oops should be settings data for esds\n"); } // ____________Setup audio__________________ if(currentaudiostream) { audio=mpt_getAudioStream(); if(!audio) { GUI_Error_HIG (_("Cannot initialize the audio stream"), NULL); goto stopit; } } if(audio) { audioinfo=audio->getInfo(); audio->extraData(&extraDataSize,&extraData); if(audioProcessMode()) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); else encoding_gui->setAudioCodec("Copy"); }else { encoding_gui->setAudioCodec("None"); } // ____________Setup Muxer _____________________ muxer= new lavMuxer; if(!muxer->open( name, 2000000, // Muxrate MUXER_MP4, &info,videoExtraDataSize,videoExtraData, audioinfo,extraDataSize,extraData)) goto stopit; //_____________ Loop _____________________ encoding_gui->setContainer("MP4"); if(audio) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); // if(bitstream.len) { muxer->writeVideoPacket( &bitstream); frameWrite++; } for(int frame=1;frame<total;frame++) { while(muxer->needAudio()) { if(!audio->getPacket(audioBuffer,&alen,&sample)) break; if(alen) { muxer->writeAudioPacket(alen,audioBuffer,sample_got); encoding_gui->feedAudioFrame(alen); sample_got+=sample; } } ADM_assert(_encode); bitstream.cleanup(frameWrite); if(!prefill || frame+prefill<total) { r=_encode->encode ( prefill+frame, &bitstream); } else { r=_encode->encode ( total-1, &bitstream); } if(!r) { printf("MP4:Frame %u error\n",frame); GUI_Error_HIG (_("Error while encoding"), NULL); goto stopit; } if(!bitstream.len && skipping) { printf("Frame skipped (xvid ?)\n"); continue; } skipping=0; // printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame); frameWrite++; muxer->writeVideoPacket( &bitstream); encoding_gui->setFrame(frame,total); encoding_gui->feedFrame(bitstream.len); if(!encoding_gui->isAlive()) { if(GUI_YesNo(_("Stop Request"), _("Do you want to abort encoding ?"))) goto stopit; } } ret=1; stopit: if(muxer) muxer->close(); if(encoding_gui) delete encoding_gui; if(TwoPassLogFile) delete [] TwoPassLogFile; if(videoBuffer) delete [] videoBuffer; if(muxer) delete muxer; if(_encode) delete _encode; if(videoExtraData) delete [] videoExtraData; // Cleanup deleteAudioFilter (audio); return ret; }
/* * \fn Oplug_flv \brief Main function to save in flv format. It is very close to oplug_mp4 but somehow simplified as the following assumptions are made : * No b frame * No 2 pass encoding */ uint8_t oplug_flv(const char *name) { AVDMGenericVideoStream *_incoming=NULL; AVDMGenericAudioStream *audio=NULL; uint8_t audioBuffer[48000]; uint8_t *videoBuffer=NULL; uint32_t alen;//,flags; uint32_t size; uint32_t sample_got=0,sample; uint32_t extraDataSize=0; uint8_t *extraData=NULL; lavMuxer *muxer=NULL; aviInfo info; uint32_t width,height; DIA_encoding *encoding_gui=NULL; Encoder *_encode=NULL; uint32_t total=0; uint32_t videoExtraDataSize=0; uint8_t *videoExtraData=NULL; uint8_t *dummy,err; WAVHeader *audioinfo=NULL; int prefill=0; uint32_t displayFrame=0; ADMBitstream bitstream(0); uint8_t r=0; pthread_t audioThread; audioQueueMT context; PacketQueue *pq=NULL;//("MP4 audioQ",50,2*1024*1024); uint32_t totalAudioSize=0; int frameDelay = 0; bool receivedFrame = false; // Setup video if(videoProcessMode()) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); }else { _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart); } videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3]; // Set global header encoding, needed for H264 _encode = getVideoEncoder (_incoming->getInfo()->width, _incoming->getInfo()->height,1); total= _incoming->getInfo()->nb_frames; info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME // int supported=0; if(isVP6Compatible(info.fcc)) supported=1; if(fourCC::check(info.fcc,(const uint8_t *)"FLV1")) supported=1; if(!supported) { GUI_Error_HIG(QT_TR_NOOP("Unsupported video"),QT_TR_NOOP("Only FLV1 and VP6 video are supported")); goto stopit; } /* Check audio, we support only mp3 right now * 44100, 22050, 11025 only! * */ if(currentaudiostream) { uint32_t audioCodec=0; uint32_t fq=currentaudiostream->getInfo()->frequency; if(audioProcessMode()) { audioCodec=audioFilter_getOuputCodec(); fq=audioFilter_getOuputFrequency(fq); }else { // copy audioCodec=currentaudiostream->getInfo()->encoding; } if(audioCodec!=WAV_MP3 ) { GUI_Error_HIG(QT_TR_NOOP("Unsupported audio"),QT_TR_NOOP("Audio must be mp3 for flv output.")); goto stopit; } if(fq!=44100 && fq!=22050 && fq!=11025) { GUI_Error_HIG(QT_TR_NOOP("Unsupported audio"),QT_TR_NOOP("Frequency must be 44100, 22050 or 11025 Hz.")); goto stopit; } } encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000); bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3; if (!_encode) { GUI_Error_HIG ("[FLV]",QT_TR_NOOP("Cannot initialize the video stream")); goto stopit; } // init compressor encoding_gui->setContainer(QT_TR_NOOP("FLV")); encoding_gui->setAudioCodec(QT_TR_NOOP("None")); if(!videoProcessMode()) encoding_gui->setCodec(QT_TR_NOOP("Copy")); else encoding_gui->setCodec(_encode->getDisplayName()); if (!_encode->configure (_incoming)) { GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL); goto stopit; }; encoding_gui->setPhasis (QT_TR_NOOP("Encoding")); info.width=_incoming->getInfo()->width; info.height=_incoming->getInfo()->height; info.nb_frames=_incoming->getInfo()->nb_frames; info.fps1000=_incoming->getInfo()->fps1000; _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy); if(videoExtraDataSize) { printf("[FLV]We have extradata for video in copy mode (%d)\n",videoExtraDataSize); videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,dummy,videoExtraDataSize); } ADM_assert(_encode); bitstream.data=videoBuffer; // ____________Setup audio__________________ if(currentaudiostream) { audio=mpt_getAudioStream(); if(!audio) { GUI_Error_HIG ("[FLV]",QT_TR_NOOP("Cannot initialize the audio stream")); goto stopit; } } if(audio) { audioinfo=audio->getInfo(); audio->extraData(&extraDataSize,&extraData); if(audioProcessMode()) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); else encoding_gui->setAudioCodec(QT_TR_NOOP("Copy")); }else { encoding_gui->setAudioCodec(QT_TR_NOOP("None")); } // ____________Setup Muxer _____________________ muxer= new lavMuxer; if(!muxer->open( name, 2000000, // Muxrate MUXER_FLV, &info,videoExtraDataSize,videoExtraData, audioinfo,extraDataSize,extraData)) goto stopit; //_____________ Loop _____________________ encoding_gui->setContainer(QT_TR_NOOP("FLV")); if(!videoProcessMode()) encoding_gui->setCodec(QT_TR_NOOP("Copy")); else encoding_gui->setCodec(_encode->getDisplayName()); // UI_purge(); //_____________ Start Audio thread _____________________ if(audio) { pq=new PacketQueue("[FLV] audioQ",5000,2*1024*1024); memset(&context,0,sizeof(context)); context.audioEncoder=audio; context.audioTargetSample=0xFFFF0000; ; //FIXME context.packetQueue=pq; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); ADM_usleep(4000); } //_____________GO !___________________ for (uint32_t frame = 0; frame < total; frame++) { if (!encoding_gui->isAlive()) { r = 0; break; } while(muxer->needAudio()) { if(pq->Pop(audioBuffer,&alen,&sample)) { if(alen) { muxer->writeAudioPacket(alen,audioBuffer,sample_got); totalAudioSize+=alen; encoding_gui->setAudioSize(totalAudioSize); sample_got+=sample; } } else { r = 0; break; } } for (;;) { bitstream.cleanup(frame); if (frame + frameDelay >= total) { if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH) r = _encode->encode(UINT32_MAX, &bitstream); else r = 0; } else r = _encode->encode(frame + frameDelay, &bitstream); if (!r) { printf("Encoding of frame %lu failed!\n", frame); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); break; } else if (!receivedFrame && bitstream.len > 0) { if (!(bitstream.flags & AVI_KEY_FRAME)) { GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"), QT_TR_NOOP("The beginning frame is not a key frame.\nPlease move the A marker.")); r = 0; break; } else receivedFrame = true; } if (bitstream.len == 0 && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)) { printf("skipping frame: %u size: %i\n", frame + frameDelay, bitstream.len); frameDelay++; } else break; } if (!r) break; muxer->writeVideoPacket(&bitstream); encoding_gui->setFrame(frame, bitstream.len, bitstream.out_quantizer, total); } stopit: // Flush slave Q if(audio&& pq) { context.audioAbort=1; pq->Abort(); // Wait for audio slave to be over while(!context.audioDone) { printf("[FLV]Waiting Audio thread\n"); ADM_usleep(500000); } delete pq; } // if(muxer) muxer->close(); if(encoding_gui) delete encoding_gui; if(videoBuffer) delete [] videoBuffer; if(muxer) delete muxer; if(_encode) delete _encode; if(videoExtraData) delete [] videoExtraData; // Cleanup deleteAudioFilter (audio); return r; }
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming=NULL; AVDMGenericAudioStream *audio=NULL; uint8_t audioBuffer[48000]; uint8_t *videoBuffer=NULL; uint32_t alen;//,flags; uint32_t size; uint8_t ret=0; uint32_t sample_got=0,sample; uint32_t extraDataSize=0; uint8_t *extraData=NULL; lavMuxer *muxer=NULL; aviInfo info; uint32_t width,height; DIA_encoding *encoding_gui=NULL; Encoder *_encode=NULL; char *TwoPassLogFile=NULL; uint32_t total=0; uint32_t videoExtraDataSize=0; uint8_t *videoExtraData=NULL; uint8_t *dummy,err; WAVHeader *audioinfo=NULL; int prefill=0; uint32_t displayFrame=0; ADMBitstream bitstream(0); uint32_t frameWrite=0; ADM_MUXER_TYPE muxerType=MUXER_MP4; uint8_t dualPass=0; uint8_t r=0; uint32_t skipping=1; pthread_t audioThread; audioQueueMT context; PacketQueue *pq;//("MP4 audioQ",50,2*1024*1024); uint32_t totalAudioSize=0; uint32_t sent=0; const char *containerTitle; switch(type) { case ADM_PSP:muxerType=MUXER_PSP;containerTitle="PSP";break; case ADM_MP4:muxerType=MUXER_MP4;containerTitle="MP4";break; case ADM_MATROSKA:muxerType=MUXER_MATROSKA;containerTitle="MKV";break; default: ADM_assert(0); } // Setup video if(videoProcessMode()) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); }else { _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart); } videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3]; // Set global header encoding, needed for H264 _encode = getVideoEncoder (_incoming->getInfo()->width, _incoming->getInfo()->height,1); total= _incoming->getInfo()->nb_frames; encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000); bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3; if (!_encode) { GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the video stream"), NULL); goto stopit; } // init compressor encoding_gui->setContainer(containerTitle); encoding_gui->setAudioCodec("None"); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,total); if (!_encode->configure (_incoming)) { GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL); goto stopit; }; dualPass=_encode->isDualPass(); if(dualPass) { if(!prepareDualPass(bitstream.bufferSize,videoBuffer,TwoPassLogFile,encoding_gui,_encode,total)) goto stopit; }else { encoding_gui->setPhasis ("Encoding"); } info.width=_incoming->getInfo()->width; info.height=_incoming->getInfo()->height; info.nb_frames=_incoming->getInfo()->nb_frames; info.fps1000=_incoming->getInfo()->fps1000; info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy); if(videoExtraDataSize) { printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize); videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,dummy,videoExtraDataSize); } // _________________Setup video (cont) _______________ // ___________ Read 1st frame _________________ ADM_assert(_encode); bitstream.data=videoBuffer; preFilling: bitstream.cleanup(0); if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame)) { printf("MP4:First frame error\n"); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); goto stopit; } sent++; if(!bitstream.len) { prefill++; goto preFilling; } printf("Pass 2 prefill : %u\n",prefill); if(!bitstream.flags & AVI_KEY_FRAME) { GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"),QT_TR_NOOP( "The beginning frame is not a key frame.\nPlease move the A marker.")); goto stopit; } //len=bitstream.len; // If needed get VOL header if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len) { // And put them as extradata for esds atom uint32_t voslen=0; if(extractVolHeader(videoBuffer,bitstream.len,&voslen)) { if(voslen) { videoExtraDataSize=voslen; videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,videoBuffer,videoExtraDataSize); } } else printf("Oops should be settings data for esds\n"); } // ____________Setup audio__________________ if(currentaudiostream) { audio=mpt_getAudioStream(); if(!audio) { GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the audio stream"), NULL); goto stopit; } } if(audio) { audioinfo=audio->getInfo(); audio->extraData(&extraDataSize,&extraData); if(audioProcessMode()) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); else encoding_gui->setAudioCodec("Copy"); }else { encoding_gui->setAudioCodec("None"); } // ____________Setup Muxer _____________________ muxer= new lavMuxer; if(!muxer->open( name, 2000000, // Muxrate muxerType, &info,videoExtraDataSize,videoExtraData, audioinfo,extraDataSize,extraData)) goto stopit; //_____________ Loop _____________________ encoding_gui->setContainer(containerTitle); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); // UI_purge(); if(bitstream.len) { muxer->writeVideoPacket( &bitstream); frameWrite++; } //_____________ Start Audio thread _____________________ if(audio) { pq=new PacketQueue("MP4 audioQ",5000,2*1024*1024); memset(&context,0,sizeof(context)); context.audioEncoder=audio; context.audioTargetSample=0xFFFF0000; ; //FIXME context.packetQueue=pq; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); ADM_usleep(4000); } //_____________GO !___________________ for(int frame=1;frame<total;frame++) { while(muxer->needAudio()) { if(pq->Pop(audioBuffer,&alen,&sample)) { if(alen) { muxer->writeAudioPacket(alen,audioBuffer,sample_got); totalAudioSize+=alen; encoding_gui->setAudioSize(totalAudioSize); sample_got+=sample; } }else break; } ADM_assert(_encode); bitstream.cleanup(frameWrite); if(!prefill || frame+prefill<total) { r=_encode->encode ( prefill+frame, &bitstream); } else { r=_encode->encode ( total-1, &bitstream); } if(!r && frame<total-2) { printf("MP4:Frame %u error\n",frame); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); goto stopit; } if(!bitstream.len && skipping) { printf("Frame skipped (xvid ?)\n"); continue; } sent++; skipping=0; // printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame); frameWrite++; muxer->writeVideoPacket( &bitstream); encoding_gui->setFrame(frame,bitstream.len,bitstream.out_quantizer,total); if(!encoding_gui->isAlive()) { goto stopit; } } ret=1; stopit: printf("2nd pass, sent %u frames\n",sent); // Flush slave Q if(audio) { context.audioAbort=1; pq->Abort(); // Wait for audio slave to be over while(!context.audioDone) { printf("Waiting Audio thread\n"); ADM_usleep(500000); } delete pq; } // if(muxer) muxer->close(); if(encoding_gui) delete encoding_gui; if(TwoPassLogFile) delete [] TwoPassLogFile; if(videoBuffer) delete [] videoBuffer; if(muxer) delete muxer; if(_encode) delete _encode; if(videoExtraData) delete [] videoExtraData; // Cleanup deleteAudioFilter (audio); return ret; }
//**************************************************************** uint8_t mpegWritter::dopass2 (const char *name, char *statname, uint32_t final_size, uint32_t bitrate, ADM_MPEGTYPE mpegtype, int matrix, uint8_t interlaced, uint8_t bff, // WLA uint8_t widescreen) { int intra, q; uint32_t size; AVDMGenericVideoStream *incoming; FILE *fd = NULL; uint64_t total_size = 0; uint32_t len, flags, type, outquant, audiolen; uint32_t sample_target = 0; double sample_time; ADMBitstream bitstream; memset (quantstat, 0, 32); incoming = getLastVideoFilter (frameStart, frameEnd - frameStart); if (!_audio) { if (!(fd = qfopen (name, "wb"))) return 0; } // if(!init(name,mpegtype,interlaced,widescreen)) if (!init (name, mpegtype, interlaced, bff, widescreen)) // WLA { printf ("Mpeg2 init failed\n"); return 0; } printf ("\n mpeg2enc init done \n"); ADM_assert (aImage); ADM_assert (_buffer_out); encoding->reset (); encoding->setFrame (0, _total); /*-------------------- Pass 1 over, go to pass 2 --------------------------------*/ ADM_assert (_ratecontrol->startPass2 (final_size, _total)); encoding->setPhasis ("2nd Pass"); q = 2; //mpegvbr.maxAllowedBitrate=(bitrate*1000)>>3;//(bitrate*1000)>>3; //mpegvbr.maxAllowedBitrate=(9000*1000)>>3; // enable stuff in xvid //-> switch (mpegtype) { case ADM_SVCD: Mpeg2encSVCD * dec; dec = new Mpeg2encSVCD (_w, _h); dec->setMatrix (matrix); // dec->init(q,bitrate,_fps1000,interlaced,widescreen); dec->init (q, bitrate, _fps1000, interlaced, bff, widescreen, 0); // WLA _codec = dec; encoding->setCodec ("SVCD"); printf ("Svcd max bitrate : %d\n", bitrate); break; case ADM_DVD: { Mpeg2encDVD *dec; dec = new Mpeg2encDVD (_w, _h); dec->setMatrix (matrix); // dec->init(q,bitrate,_fps1000,interlaced,widescreen); dec->init (q, bitrate, _fps1000, interlaced, bff, widescreen, 0); // WLA _codec = dec; printf ("DVD max bitrate : %d\n", bitrate); encoding->setCodec ("DVD"); } break; default: ADM_assert (0); break; } encoding->setPhasis ("2nd Pass"); if (_muxer) { encoding-> setAudioCodec (getStrFromAudioCodec (_audio->getInfo ()->encoding)); sample_time = _total; sample_time *= 1000; sample_time /= _fps1000; // target_time in second sample_time *= _audio->getInfo ()->frequency; sample_target = (uint32_t) floor (sample_time); } bitstream.data = _buffer_out; for (uint32_t i = 0; i < _total; i++) { if (!incoming->getFrameNumberNoAlloc (i, &size, aImage, &flags)) { GUI_Error_HIG (_("Encoding error"), NULL); if (!_audio) qfclose (fd); end (); return 0; } encoding->setFrame (i, _total); if (i < MPEG_PREFILL) { _codec->encode (aImage, &bitstream); //_buffer_out , &len,&flags,&outquant); quantstat[bitstream.out_quantizer]++; continue; } // Set // ADM_rframe ftype, ztype; uint32_t qz; ADM_assert (_ratecontrol->getQz (&qz, &ztype)); q = qz; //_codec->setQuantize(q); bitstream.in_quantizer = q; _codec->encode (aImage, &bitstream); //_buffer_out , &len,&flags,&outquant); quantstat[bitstream.out_quantizer]++; encoding->setQuant (bitstream.out_quantizer); switch (bitstream.flags) { case AVI_KEY_FRAME: ftype = RF_I; break; case AVI_B_FRAME: ftype = RF_B; break; default: ftype = RF_P; break; } if (ftype != ztype) { printf ("**Frame type does not match %d %d\n", ztype, ftype); } //aprintf("inquant : %02d outquant %02d Intra %d size :%d flags %x\n", // q,outquant,intra,len,flags); ADM_assert (_ratecontrol-> logPass2 (bitstream.out_quantizer, ftype, bitstream.len)); total_size += bitstream.len; encoding->feedFrame (bitstream.len); if (!_muxer) { qfwrite (_buffer_out, bitstream.len, 1, fd); fflush (fd); } else { // write video _muxer->writeVideoPacket (&bitstream); PACK_AUDIO; } if (!encoding->isAlive ()) { print_quant_stat (name); end (); qfclose (fd); return 0; } } //-- // flush queue for (uint32_t i = 0; i < MPEG_PREFILL; i++) { ADM_rframe ftype; uint32_t qz; ADM_assert (_ratecontrol->getQz (&qz, &ftype)); q = qz; //_codec->setQuantize(q); bitstream.in_quantizer = q; _codec->encode (aImage, &bitstream); //_buffer_out , &len,&flags,&outquant); quantstat[bitstream.out_quantizer]++; encoding->setQuant (bitstream.out_quantizer); switch (bitstream.flags) { case AVI_KEY_FRAME: ftype = RF_I; break; case AVI_B_FRAME: ftype = RF_B; break; default: ftype = RF_P; break; } //aprintf("inquant : %02d outquant %02d Intra %d size :%d flags %x\n", // q,outquant,intra,len,flags); ADM_assert (_ratecontrol-> logPass2 (bitstream.out_quantizer, ftype, bitstream.len)); total_size += bitstream.len; if (!_muxer) { qfwrite (_buffer_out, bitstream.len, 1, fd); fflush (fd); } else { // write video _muxer->writeVideoPacket (&bitstream); PACK_AUDIO; } // printf("\n pipe opened %ld\n",i); encoding->feedFrame (bitstream.len); // Set encoding->setQuant (bitstream.out_quantizer); encoding->setFrame (i, MPEG_PREFILL); } //-- if (!_muxer) qfclose (fd); else { _muxer->close (); delete _muxer; _muxer = NULL; } print_quant_stat (name); end (); return 1; }
/* Save as with the external mpeg2enc */ uint8_t mpegWritter::save_regular (const char *name, ADM_MPEGTYPE mpegtype, int qz, int bitrate, int matrix, uint8_t interlaced, uint8_t bff, // WLA uint8_t widescreen) { uint32_t size; AVDMGenericVideoStream *incoming; FILE *fd = NULL; uint64_t total_size = 0; uint32_t len, flags; uint32_t outquant; uint32_t audiolen = 0; DIA_encoding *encoding; uint32_t sample_target = 0; double sample_time; ADMBitstream bitstream; incoming = getLastVideoFilter (frameStart, frameEnd - frameStart); _total = incoming->getInfo ()->nb_frames; _fps1000 = incoming->getInfo ()->fps1000; if (!_total) { GUI_Error_HIG (_("No frames to encode"), _("Please check markers. Is \"A>\" == \">B\"?")); return 0; } printf ("Br:%d, qz:%d\n", bitrate, qz); if (!_audio) { if (!(fd = qfopen (name, "wb"))) return 0; } else { ADM_assert (_muxer); sample_time = _total; sample_time *= 1000; sample_time /= _fps1000; // target_time in second sample_time *= _audio->getInfo ()->frequency; sample_target = (uint32_t) floor (sample_time); } _w = incoming->getInfo ()->width; _h = incoming->getInfo ()->height; _page = _w * _h; _page += _page >> 1; // if(!init(name,ADM_VCD,interlaced,widescreen)) return 0; if (!init (name, ADM_VCD, interlaced, bff, widescreen)) return 0; //WLA printf ("\n mpeg2enc init done \n"); //_buffer =new uint8_t[_w*_h*2]; aImage = new ADMImage (_w, _h); _buffer_out = new uint8_t[_w * _h * 2]; ADM_assert (aImage); ADM_assert (_buffer_out); encoding = new DIA_encoding (_fps1000); encoding->setPhasis ("Encoding."); encoding->setFrame (0, _total); // printf("Br:%d, qz:%d\n",bitrate,qz); switch (mpegtype) { case ADM_VCD: { encoding->setCodec ("VCD."); Mpeg2encVCD *dec; dec = new Mpeg2encVCD (_w, _h); // dec->init(1,0,_fps1000,interlaced,widescreen); dec->init (1, 0, _fps1000, interlaced, bff, widescreen, 0); // WLA _codec = dec; } break; case ADM_SVCD: Mpeg2encSVCD * dec; dec = new Mpeg2encSVCD (_w, _h); dec->setMatrix (matrix); // dec->init(qz,bitrate,_fps1000,interlaced,widescreen); dec->init (qz, bitrate, _fps1000, interlaced, bff, widescreen, 0); // WLA _codec = dec; encoding->setCodec ("SVCD."); break; case ADM_DVD: { Mpeg2encDVD *dec; dec = new Mpeg2encDVD (_w, _h); dec->setMatrix (matrix); // dec->init(qz,bitrate,_fps1000,interlaced,widescreen); dec->init (qz, bitrate, _fps1000, interlaced, bff, widescreen, 0); // WLA _codec = dec; encoding->setCodec ("DVD."); } break; default: ADM_assert (0); } printf ("\n--encoding started--\n"); if (_muxer) { if (audioProcessMode ()) encoding-> setAudioCodec (getStrFromAudioCodec (_audio->getInfo ()->encoding)); else encoding->setAudioCodec ("Copy"); switch (_outputAs) { case MUXER_TS: encoding->setContainer ("Mpeg TS"); break; case MUXER_VCD: encoding->setContainer ("Mpeg VCD"); break; case MUXER_SVCD: encoding->setContainer ("Mpeg SVCD"); break; case MUXER_DVD: encoding->setContainer ("Mpeg DVD"); break; default: ADM_assert (0); } } else encoding->setContainer ("Mpeg ES"); bitstream.data = _buffer_out; for (uint32_t i = 0; i < _total; i++) { if (!incoming->getFrameNumberNoAlloc (i, &size, aImage, &flags)) { delete encoding; GUI_Error_HIG (_("Encoding error"), NULL); if (fd) qfclose (fd); end (); return 0; } bitstream.cleanup (i); bitstream.in_quantizer=0; _codec->encode (aImage, &bitstream); //_buffer_out , &len,&flags,&outquant); total_size += bitstream.len; encoding->feedFrame (bitstream.len); encoding->setQuant (bitstream.out_quantizer); encoding->setFrame (i, _total); // Null frame are only possible // when in prefill state for mpeg-X if (!len) continue; if (_muxer) { #warning FIXME #warning FIXME #warning FIXME #warning FIXME _muxer->writeVideoPacket (&bitstream); PACK_AUDIO; } else { qfwrite (_buffer_out, bitstream.len, 1, fd); fflush (fd); } aprintf (" outquant %02d size :%d flags %x\n", outquant, len, flags); if (!encoding->isAlive ()) { delete encoding; end (); if (fd) qfclose (fd); return 0; } } encoding->setPhasis ("Finishing"); bitstream.data = _buffer_out; for (uint32_t i = 0; i < MPEG_PREFILL; i++) { bitstream.cleanup (i); _codec->encode (aImage, &bitstream); //_buffer_out , &len,&flags); total_size += bitstream.len; encoding->feedFrame (bitstream.len); if (!_muxer) qfwrite (_buffer_out, bitstream.len, 1, fd); else { _muxer->writeVideoPacket (&bitstream); PACK_AUDIO; } // printf("\n pipe opened %ld\n",i); encoding->setFrame (i, _total); } delete encoding; if (!_muxer) qfclose (fd); else { _muxer->close (); delete _muxer; _muxer = NULL; deleteAudioFilter (_audio); _audio = NULL; } end (); return 1; }
void DIA_properties( void ) { char text[80]; uint16_t hh, mm, ss, ms; GtkWidget *dialog; uint8_t gmc, qpel,vop; uint32_t info=0; const char *yesno[2]={QT_TR_NOOP("No"),QT_TR_NOOP("Yes")}; uint32_t war,har; if (playing) return; text[0] = 0; if (!avifileinfo) return; // Fetch info info=video_body->getSpecificMpeg4Info(); vop=!!(info & ADM_VOP_ON); qpel=!!(info & ADM_QPEL_ON); gmc=!!(info & ADM_GMC_ON); dialog = create_dialog1(); gtk_register_dialog(dialog); sprintf(text, QT_TR_NOOP("%lu x %lu"), avifileinfo->width,avifileinfo->height); FILL_ENTRY(label_size); sprintf(text, QT_TR_NOOP("%2.3f fps"), (float) avifileinfo->fps1000 / 1000.F); FILL_ENTRY(label_fps); sprintf(text, QT_TR_NOOP("%ld frames"), avifileinfo->nb_frames); FILL_ENTRY(label_number); sprintf(text, "%s", fourCC::tostring(avifileinfo->fcc)); FILL_ENTRY(label_videofourcc); if (avifileinfo->nb_frames) { frame2time(avifileinfo->nb_frames, avifileinfo->fps1000, &hh, &mm, &ss, &ms); sprintf(text, QT_TR_NOOP("%02d:%02d:%02d.%03d"), hh, mm, ss, ms); FILL_ENTRY(label_duration); } // Fill in vop, gmc & qpel SET_YES(labelPacked,vop); SET_YES(labelGMC,gmc); SET_YES(labelQP,qpel); // Aspect ratio const char *s; war=video_body->getPARWidth(); har=video_body->getPARHeight(); getAspectRatioFromAR(war,har, &s); sprintf(text, QT_TR_NOOP("%s (%u:%u)"), s,war,har); FILL_ENTRY(labelAspectRatio); // Now audio WAVHeader *wavinfo=NULL; if (currentaudiostream) wavinfo=currentaudiostream->getInfo(); if(wavinfo) { switch (wavinfo->channels) { case 1: sprintf(text, QT_TR_NOOP("Mono")); break; case 2: sprintf(text, QT_TR_NOOP("Stereo")); break; default: sprintf(text, "%d",wavinfo->channels); break; } FILL_ENTRY(label1_audiomode); sprintf(text, QT_TR_NOOP("%lu Hz"), wavinfo->frequency); FILL_ENTRY(label_fq); sprintf(text, QT_TR_NOOP("%lu Bps / %lu kbps"), wavinfo->byterate, wavinfo->byterate * 8 / 1000); FILL_ENTRY(label_bitrate); sprintf(text, "%s", getStrFromAudioCodec(wavinfo->encoding)); FILL_ENTRY(label1_audiofourcc); // Duration in seconds too if(currentaudiostream && wavinfo->byterate>1) { uint32_t l=currentaudiostream->getLength(); double du; du=l; du*=1000; du/=wavinfo->byterate; ms2time((uint32_t)floor(du), &hh, &mm, &ss, &ms); sprintf(text, QT_TR_NOOP("%02d:%02d:%02d.%03d"), hh, mm, ss, ms); FILL_ENTRY(label_audioduration); sprintf(text, QT_TR_NOOP("%.2f MB"), l / 1048576.F); FILL_ENTRY(labelFileSize); } SET_YES(labelVbr, currentaudiostream->isVBR()); } else { DISABLE_WIDGET(frame2); } gtk_dialog_run(GTK_DIALOG(dialog)); gtk_unregister_dialog(dialog); gtk_widget_destroy(dialog); }