//****************************************** // Compute the value that will not change // (duration) // and init the entries for current bitrate //****************************************** void prepare( void ) { float duration=0; aviInfo info; char string[200]; uint16_t mm,hh,ss,ms; AVDMProcessAudioStream *stream; if(frameStart<frameEnd) numberOfVideoFrames=frameEnd-frameStart; else numberOfVideoFrames=frameStart-frameEnd; duration=(float)video_body->getTime (numberOfVideoFrames); duration=duration/1000.; if(duration<0) duration=-duration; video_body->getVideoInfo(&info); videoDuration=(uint32_t)ceil(duration); frame2time(numberOfVideoFrames,info.fps1000, &hh, &mm, &ss, &ms); // now we can set it sprintf(string,"%02d:%02d:%02d",hh,mm,ss); gtk_label_set_text(GTK_LABEL(WID(labelDuration)),string); printf("Video duration :%lu\n",videoDuration); // Now get audio info track1=0; if(audioProcessMode() && currentaudiostream) { stream=buildFakeAudioFilter(currentaudiostream, 0, 0xffffffff); if(stream) { track1=(stream->getInfo()->byterate*8)/1000; } deleteAudioFilter(); }else { if(currentaudiostream) track1=(currentaudiostream->getInfo()->byterate*8)/1000; } track2=0; gtk_write_entry(WID(entry3), track1); gtk_write_entry(WID(entry4), track2); printf("Track1 bitrate :%lu\n",track1); printf("Track2 bitrate :%lu\n",track2); }
//****************************************** // Compute the value that will not change // (duration) // and init the entries for current bitrate //****************************************** void prepare( void ) { #if 0 float duration=0; aviInfo info; char string[200]; uint16_t mm,hh,ss,ms; AVDMGenericAudioStream *stream; if(frameStart<frameEnd) numberOfVideoFrames=frameEnd-frameStart; else numberOfVideoFrames=frameStart-frameEnd; duration=(float)video_body->getTime (numberOfVideoFrames); duration=duration/1000.; if(duration<0) duration=-duration; video_body->getVideoInfo(&info); videoDuration=(uint32_t)ceil(duration); frame2time(numberOfVideoFrames,info.fps1000, &hh, &mm, &ss, &ms); // now we can set it sprintf(string,"%02d:%02d:%02d",hh,mm,ss); gtk_label_set_text(GTK_LABEL(GW(labelDuration),string); printf("Video duration :%lu\n",videoDuration); // Now get audio info track1=0; if(audioProcessMode() && currentaudiostream) { // stream=buildAudioFilter(currentaudiostream,0); if(stream) { track1=(stream->getInfo()->byterate*8)/1000; } // deleteAudioFilter(stream); }else { if(currentaudiostream) track1=(currentaudiostream->getInfo()->byterate*8)/1000; } track2=0; gtk_spin_button_set_value(GTK_SPIN_BUTTON(GW(spinbuttonTrack1)), track1); gtk_spin_button_set_value(GTK_SPIN_BUTTON(GW(spinbuttonTrack2)), track2); printf("Track1 bitrate :%lu\n",track1); printf("Track2 bitrate :%lu\n",track2); #endif }
calculatorDialog::calculatorDialog(QWidget* parent) : QDialog(parent) { ui.setupUi(this); connect(ui.formatComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBox_currentIndexChanged(int))); connect(ui.mediumComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(mediumComboBox_currentIndexChanged(int))); connect(ui.customSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(spinBox_valueChanged(int))); connect(ui.audioTrack1SpinBox, SIGNAL(valueChanged(int)), this, SLOT(spinBox_valueChanged(int))); connect(ui.audioTrack2SpinBox, SIGNAL(valueChanged(int)), this, SLOT(spinBox_valueChanged(int))); float duration = 0; aviInfo info; uint16_t mm, hh, ss, ms; unsigned int track1 = 0; if (frameStart < frameEnd) _videoFrameCount = frameEnd - frameStart; else _videoFrameCount = frameStart - frameEnd; duration = ((float)video_body->getTime(_videoFrameCount) / 1000.); if (duration < 0) duration = -duration; _videoDuration = (uint32_t)ceil(duration); video_body->getVideoInfo(&info); frame2time(_videoFrameCount, info.fps1000, &hh, &mm, &ss, &ms); ui.durationLabel->setText(QString("%1:%2:%3").arg(hh, 2, 10, QLatin1Char('0')).arg(mm, 2, 10, QLatin1Char('0')).arg(ss, 2, 10, QLatin1Char('0'))); if (audioProcessMode() && currentaudiostream) { AVDMGenericAudioStream *stream ; //= buildAudioFilter(currentaudiostream, 0); if (stream) track1 = (stream->getInfo()->byterate * 8) / 1000; // deleteAudioFilter(stream); } else if(currentaudiostream) track1 = (currentaudiostream->getInfo()->byterate * 8) / 1000; ui.audioTrack1SpinBox->setValue(track1); update(); }
//_________________________________________________________________ // // 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; }
AVDMGenericAudioStream *mpt_getAudioStream (void) { AVDMGenericAudioStream *audio = NULL; if (audioProcessMode ()) // else Raw copy mode { if (currentaudiostream->isCompressed ()) { if (!currentaudiostream->isDecompressable ()) { return NULL; } } audio = buildAudioFilter (currentaudiostream, video_body->getTime (frameStart)); } else // copymode { // else prepare the incoming raw stream // audio copy mode here audio = buildAudioFilter (currentaudiostream,video_body->getTime (frameStart)); } return audio; }
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; }
/* 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; }
uint32_t audioFilter_getOuputFrequency(uint32_t inputFrequency) { if(!audioProcessMode()) return inputFrequency; if(audioResampleMode == RESAMPLING_NONE) return inputFrequency; return audioFreq; }
AVDMGenericAudioStream *buildAudioFilter(AVDMGenericAudioStream *currentaudiostream, uint32_t starttime) { AUDMAudioFilter *lastFilter=NULL; AVDMGenericAudioStream *output=NULL; AUDMEncoder *tmpfilter=NULL; ch_route.mode = 0; // if audio is set to copy, we just return the first filter if(!audioProcessMode()) { int32_t timeShiftMs=audioDelay*audioShift; deleteAudioFilter(NULL); output = new AVDMProcessAudio_RawShift(currentaudiostream, starttime, timeShiftMs); return output; } // else we build the full chain lastFilter=buildInternalAudioFilter(currentaudiostream,starttime); // and add encoder... //_______________________________________________________ uint8_t init; ADM_audioEncoderDescriptor *descriptor=getAudioDescriptor( activeAudioEncoder); if(!lastFilter) { printf(" buildInternalAudioFilter failed\n"); return 0; } if(lastFilter->getInfo()->channels > descriptor->maxChannels) { GUI_Error_HIG(_("Codec Error"),_("The number of channels is greater than what the selected audio codec can do.\n" "Either change codec or use the mixer filter to have less channels.")); deleteAudioFilter(NULL); return 0; } switch(activeAudioEncoder) { case AUDIOENC_LPCM: case AUDIOENC_NONE: { AUDMEncoder_PCM *pcm; uint32_t fourcc,revert=0; if(activeAudioEncoder==AUDIOENC_LPCM) fourcc=WAV_LPCM; else fourcc=WAV_PCM; #ifdef ADM_BIG_ENDIAN if(fourcc==WAV_PCM) #else if(fourcc==WAV_LPCM) #endif revert=1; pcm = new AUDMEncoder_PCM(revert,fourcc,lastFilter); tmpfilter=pcm; } break; #ifdef USE_VORBIS case AUDIOENC_VORBIS: { AUDMEncoder_Vorbis *vorbis; vorbis = new AUDMEncoder_Vorbis(lastFilter); tmpfilter=vorbis; break; } #endif #ifdef USE_FAAC case AUDIOENC_FAAC: { AUDMEncoder_Faac *faac; faac = new AUDMEncoder_Faac(lastFilter); tmpfilter=faac; } break; #endif #ifdef HAVE_LIBMP3LAME case AUDIOENC_MP3: { AUDMEncoder_Lame *plame = NULL; plame = new AUDMEncoder_Lame(lastFilter); tmpfilter=plame; } break; #endif case AUDIOENC_AC3: case AUDIOENC_MP2: { AUDMEncoder_Lavcodec *lavcodec = NULL; uint32_t fourc; if(activeAudioEncoder==AUDIOENC_AC3) fourc=WAV_AC3; else fourc=WAV_MP2; lavcodec = new AUDMEncoder_Lavcodec(fourc,lastFilter); tmpfilter=lavcodec; } break; case AUDIOENC_2LAME: { AUDMEncoder_Twolame *toolame_enc = NULL; toolame_enc = new AUDMEncoder_Twolame(lastFilter); tmpfilter=toolame_enc; } break; default: ADM_assert(0); } //_______________________________________________________ if(!tmpfilter->init(descriptor)) { delete tmpfilter; tmpfilter=NULL; GUI_Error_HIG("Encoder initialization failed", "Not activated."); } output=tmpfilter; currentaudiostream->beginDecompress(); return output; }