//___________________________________ uint8_t A_SaveAudioNVideo(const char *name) { uint32_t needSmart=0,fl; GenericAviSave *nw=NULL; aviInfo info; uint8_t ret=0; video_body->getVideoInfo(&info); printf("\n video process mode : %d",videoProcessMode()); if (!videoProcessMode()) { if(video_body->isMultiSeg()) needSmart=1; video_body->getFlags(frameStart,&fl); if(!(fl&AVI_KEY_FRAME)) needSmart=1; if(needSmart) printf("\n probably need smart copy mode\n"); if( !isMpeg4Compatible( info.fcc) && !isMSMpeg4Compatible(info.fcc)) { printf("\n not encodable, cancelling smart mode\n"); needSmart=0; } int value=video_body->getEnv(ENV_EDITOR_SMART); nw=NULL; if(needSmart) { if(value) { nw=new GenericAviSaveSmart(3); } else { if(GUI_Question(QT_TR_NOOP("You may need smart copy.\n Enable it ?"))) { value=4; if( ! GUI_getIntegerValue(&value, 2, 31, "_Q factor (set 4):")) return 0; nw=new GenericAviSaveSmart(value); } } } if(!nw) nw=new GenericAviSaveCopy; } else { printf("\n Process mode\n"); nw=new GenericAviSaveProcess; } ret=nw->saveAvi(name); delete nw; return ret; }
//_______________________________________________ uint8_t ogmSave(const char *name) { uint8_t ret=0; ADM_ogmWrite *writter; if(videoProcessMode()) writter=new ADM_ogmWriteProcess; else writter=new ADM_ogmWriteCopy; ret=writter->save(name); delete writter; return ret; }
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; }
//************************************* void update( void ) { uint32_t audioSize; uint32_t totalSize; char string[200]; aviInfo info; video_body->getVideoInfo(&info); track1=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GW(spinbuttonTrack1))); track2=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GW(spinbuttonTrack2))); gtk_spin_button_set_value(GTK_SPIN_BUTTON(GW(spinbuttonTrack1)), track1); gtk_spin_button_set_value(GTK_SPIN_BUTTON(GW(spinbuttonTrack2)), track1); // kb->Byte audioSize=(track1+track2)*1000; audioSize/=8; audioSize*=videoDuration; audioSize>>=20; sprintf(string,"%"PRIu32,audioSize); gtk_label_set_text(GTK_LABEL(GW(labelAudio)),string); // Compute total size (for Avi) uint32_t s74,s80,dvd; // For avi/ogm int f = gtk_combo_box_get_active(GTK_COMBO_BOX(GW(comboboxFormat))); if(f==2) { // Mpeg s74=730; s80=790; dvd=4300; } else {//AVI or OGM s74=650; s80=700; dvd=4300; } int j=gtk_combo_box_get_active(GTK_COMBO_BOX(GW(comboboxMedium))); switch(j) { case 2: totalSize=1*s74;break; case 3: totalSize=2*s74;break; case 0: totalSize=1*s80;break; case 1: totalSize=2*s80;break; case 4: totalSize=dvd;break; case 5: totalSize=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GW(spinbuttonCustom))); if(totalSize<1) totalSize=1; break; default: ADM_assert(0); } sprintf(string,"%"PRIu32,totalSize); gtk_label_set_text(GTK_LABEL(GW(labelTotal)),string); // Compute muxing overhead size uint32_t muxingOverheadSize; int numberOfAudioTracks = 0; int numberOfChunks; switch (f) { case 0: // AVI /* Muxing overhead is 8 + 32 = 40 bytes per chunk. More or less: numberOfChunks = (x + 1) * numberOfVideoFrames, where x - the number of audio tracks */ if (track1 != 0) { numberOfAudioTracks++; } if (track2 != 0) { numberOfAudioTracks++; } numberOfChunks = (numberOfAudioTracks + 1) * numberOfVideoFrames; muxingOverheadSize = (uint32_t) ceil((numberOfChunks * 40) / 1048576.0);; break; case 1: // OGM // Muxing overhead is 1.1% to 1.2% of (videoSize + audioSize) muxingOverheadSize = (uint32_t) ceil(totalSize - totalSize / 1.012); break; case 2: // MPEG // Muxing overhead is 1% to 2% of (videoSize + audioSize) muxingOverheadSize = (uint32_t) ceil(totalSize - totalSize / 1.02); break; default: ADM_assert(0); } //sprintf(string,"%lu",muxingOverheadSize); //gtk_label_set_text(GTK_LABEL(GW(labelMux)),string); // and compute // //uint32_t videoSize; if(audioSize>=totalSize) sprintf(string,"** NO ROOM LEFT**"); else { uint32_t picSize; videoSize=totalSize-audioSize - muxingOverheadSize; // Compute average bps float avg; float bpp; avg=videoSize; avg*=1024.*1024.; avg/=videoDuration; // now we have byte /sec // convert to kb per sec avg=(avg*8)/1000; videoBitrate=(uint32_t)avg; sprintf(string,"%"PRIu32,(uint32_t)videoBitrate); gtk_label_set_text(GTK_LABEL(GW(labelBitrate)),string); // sprintf(string,"%"PRIu32,videoSize); gtk_label_set_text(GTK_LABEL(GW(labelVideo)),string); // Bpp bpp=videoBitrate; bpp=bpp*1000000.; // kbit->bit + compensate for fps1000 // Fetch info from filter if(videoProcessMode()) picSize=getPicSize(); else picSize=info.width*info.height; bpp/=picSize; //printf("w:%d h:%d\n",info.width,info.height); bpp/=info.fps1000; sprintf(string,"%1.3f",bpp); gtk_label_set_text(GTK_LABEL(GW(labelBPP)),string); } }
/* * \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; }
int A_Save(const char *name) { uint32_t end; int ret=0; // depending on the type we save a avi, a mpeg or a XVCD CodecFamilty family; family= videoCodecGetFamily(); // in case of copy mode, we stick to avi file format if(!videoProcessMode()) { family=CodecFamilyAVI; if( UI_GetCurrentFormat()==ADM_PS ||UI_GetCurrentFormat()==ADM_TS ) // exception { family=CodecFamilyMpeg; } } else { if(UI_GetCurrentFormat()==ADM_AVI_DUAL) { GUI_Error_HIG(QT_TR_NOOP("Dual audio can only be used in copy mode"),QT_TR_NOOP( "Select Copy as the video codec.")); return 0; } } printf("**saving:**\n"); // Check if we need to do a sanity B frame check if(!videoProcessMode()) { uint32_t pb; end=avifileinfo->nb_frames; // if the last frame is the last frame (!) // we add one to keep it, else we systematically skip // the last frame #if 0 if(frameEnd==end-1) end=frameEnd+1; else end=frameEnd; if(!video_body->sanityCheckRef(frameStart,end,&pb)) { if(pb) { GUI_Error_HIG("Cannot save the file", "The video starts/ends with a lonely B-frame. Please remove it."); return 0; } if(!GUI_Question("Warning !\n Bframe has lost its reference frame\nContinue ?")) return 0; } #endif // Alter frameEnd so that it is not a B frame // as frameEnd -1 position uint32_t tgt=frameEnd;; uint32_t flag=0,found=0; // need to do something ? if(frameEnd>frameStart) { tgt=frameEnd; if(tgt==end-1) tgt++; video_body->getFlags(tgt-1,&flag); if((frameEnd&AVI_B_FRAME)) { printf("Last frame is a B frame, choosing better candidate\n"); // The last real one is not a I/P Frame // Go forward or rewind if(tgt<end-1) { // Try next if possible video_body->getFlags(tgt,&flag); if(!(flag&AVI_B_FRAME)) { printf("Taking next frame as last frame %lu\n",tgt+1); frameEnd=tgt+1; found=1; } } if(!found) // next frame not possible, rewind { if(tgt>=end-2) tgt=end-2; while(tgt>frameStart) { printf("Trying :%lu\n",tgt); video_body->getFlags(tgt,&flag); if(!(flag&AVI_B_FRAME)) { printf("Taking previous frame as last frame %lu\n",tgt+1); frameEnd=tgt+1; found=1; break; } else tgt--; } } ADM_assert(found); } } } printf("Output format:%d\n",UI_GetCurrentFormat()); switch(family) { case CodecFamilyAVI: printf(" AVI family\n"); switch(UI_GetCurrentFormat()) { case ADM_DUMMY: ret=oplug_dummy(name); break; case ADM_FLV: ret=oplug_flv(name); break; case ADM_MP4: case ADM_PSP: case ADM_MATROSKA: ret=oplug_mp4(name,UI_GetCurrentFormat()); break; case ADM_AVI: ret=A_SaveAudioNVideo(name); break; case ADM_OGM: ret=ogmSave(name); break; case ADM_ES: ret=ADM_saveRaw(name); break; case ADM_AVI_DUAL: ret=A_SaveAudioDualAudio(name); break; case ADM_AVI_PAK: ret=A_SavePackedVop(name); break; case ADM_AVI_UNP: ret=A_SaveUnpackedVop(name); break; default: GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL); } break; case CodecFamilyMpeg: printf(" MPEG family\n"); if(!videoProcessMode()) { printf("Using pass through\n"); switch(UI_GetCurrentFormat()) { case ADM_PS: case ADM_TS: ret=mpeg_passthrough(name,UI_GetCurrentFormat()); break; default: GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL); } break; } // THERE IS NO BREAK HERE, NOT A MISTAKE! case CodecFamilyXVCD: switch(UI_GetCurrentFormat()) { case ADM_TS: case ADM_PS: case ADM_ES: ret=oplug_mpegff(name,UI_GetCurrentFormat());; break; default: GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL); } break; default: ADM_assert(0); return 0; } getFirstVideoFilter(0,avifileinfo->nb_frames); return ret; }
void calculatorDialog::update(void) { unsigned int track1, track2; uint32_t audioSize; uint32_t totalSize; aviInfo info; video_body->getVideoInfo(&info); track1 = ui.audioTrack1SpinBox->value(); track2 = ui.audioTrack2SpinBox->value(); // kb->Byte audioSize = ((((track1 + track2) * 1000) / 8) * _videoDuration) >> 20; ui.audioSizeLabel->setText(QString("%1").arg(audioSize)); // Compute total size unsigned int s74, s80, dvd; int formatIndex = ui.formatComboBox->currentIndex(); if (formatIndex == 2) { // Mpeg s74 = 730; s80 = 790; dvd = 4300; } else { //AVI or OGM s74 = 650; s80 = 700; dvd = 4300; } int mediumIndex = ui.mediumComboBox->currentIndex(); switch(mediumIndex) { case 0: totalSize = s80; break; case 1: totalSize = 2 * s80; break; case 2: totalSize = s74; break; case 3: totalSize= 2 * s74; break; case 4: totalSize = dvd; break; case 5: totalSize = ui.customSizeSpinBox->value(); break; } ui.totalSizeLabel->setText(QString("%1").arg(totalSize)); // Compute muxing overhead size unsigned int muxingOverheadSize; int numberOfAudioTracks = 0; int numberOfChunks; switch (formatIndex) { case 0: // AVI // Muxing overhead is 8 + 32 = 40 bytes per chunk. // More or less: numberOfChunks = (x + 1) * _videoFrameCount, // where x - the number of audio tracks if (track1 != 0) numberOfAudioTracks++; if (track2 != 0) numberOfAudioTracks++; numberOfChunks = (numberOfAudioTracks + 1) * _videoFrameCount; muxingOverheadSize = (unsigned int)ceil((numberOfChunks * 40) / 1048576.0); break; case 1: // OGM // Muxing overhead is 1.1% to 1.2% of (videoSize + audioSize) muxingOverheadSize = (unsigned int)ceil(totalSize - totalSize / 1.012); break; case 2: // MPEG // Muxing overhead is 1% to 2% of (videoSize + audioSize) muxingOverheadSize = (unsigned int)ceil(totalSize - totalSize / 1.02); break; } unsigned int videoSize = 0; // and compute if (audioSize + muxingOverheadSize >= totalSize) videoSize = 0; else videoSize = totalSize - audioSize - muxingOverheadSize; unsigned int picSize; // Compute average bps float avg; float bpp; avg = (videoSize * 1024. * 1024.) / _videoDuration; // now we have byte /sec, convert to kb per sec avg = (avg * 8) / 1000; ui.videoBitrateLabel->setText(QString("%1").arg((unsigned int)avg)); ui.videoSizeLabel->setText(QString("%1").arg(videoSize)); // Bpp bpp = avg * 1000000.; // kbit->bit + compensate for fps1000 // Fetch info from filter if(videoProcessMode()) picSize = getPictureSize(); else picSize = info.width * info.height; bpp = (bpp / picSize) / info.fps1000; ui.bppLabel->setText(QString("%1").arg(bpp, 0, 'g', 3)); }