/* 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; }
/*-------------------------------------------------------------------------------------------------------------------*/ uint8_t mpegWritter::save_dualpass (const char *name, uint32_t final_size, uint32_t bitrate, ADM_MPEGTYPE mpegtype, int matrix, uint8_t interlaced, uint8_t bff, // WLA uint8_t widescreen) { AVDMGenericVideoStream *incoming; char *statname; uint32_t reuse = 0; incoming = getLastVideoFilter (frameStart, frameEnd - frameStart); _w = incoming->getInfo ()->width; _h = incoming->getInfo ()->height; _page = _w * _h; _page += _page >> 1; _fps1000 = incoming->getInfo ()->fps1000; _total = incoming->getInfo ()->nb_frames; if (!_total) return 0; //_buffer =new uint8_t[_w*_h*2]; aImage = new ADMImage (_w, _h); _buffer_out = new uint8_t[_w * _h * 2]; statname = new char[strlen (name) + 4 + 1]; strcpy (statname, name); strcat (statname, ".st"); printf ("Matrix : %d\n\n", matrix); encoding = new DIA_encoding (_fps1000); encoding->setPhasis ("Encoding"); // check if stat file exists ? #if 1 //ndef CYG_MANGLING { FILE *fd; fd = fopen (statname, "rt"); if (fd) { fclose (fd); prefs->get (FEATURE_REUSE_2PASS_LOG, (uint32_t *) & reuse); if (!reuse && GUI_Question (_("Reuse log file ?"))) reuse = 1; } } #endif //_ratecontrol=new ADM_oldXvidRc(_fps1000,statname); _ratecontrol = new ADM_newXvidRc (_fps1000, statname); #if 1 if (!reuse) // if(!dopass1(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,widescreen)) if (!dopass1 (name, statname, final_size, bitrate, mpegtype, matrix, interlaced, bff, widescreen)) // WLA { delete encoding; GUI_Error_HIG (_("Error in pass 1"), NULL); delete[]statname; return 0; } #endif // if(!dopass2(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,widescreen)) if (!dopass2 (name, statname, final_size, bitrate, mpegtype, matrix, interlaced, bff, widescreen)) // WLA { delete encoding; GUI_Error_HIG (_("Error in pass 2"), NULL); delete[]statname; return 0; } delete encoding; delete[]statname; return 1; }
uint8_t computeResize (void) { int targetx,targetxFinal,targetyPAL,targetyNTSC; ADV_Info *info; char *inputratio = NULL; uint8_t res = 0; /* 1 Pal, 2 NSTC or film */ uint32_t targety; // scale as if it was 1:1 -> 4:3 prefs->get (FEATURE_SVCDRES_PREFEREDSOURCERATIO, &inputratio); if(inputratio) { if (inputratio && !strcmp (inputratio, "1:1")) sourceAR=RESWIZ_AR_1_1; if (inputratio && !strcmp (inputratio, "4:3")) sourceAR=RESWIZ_AR_4_3; if (inputratio && !strcmp (inputratio, "16:9")) sourceAR=RESWIZ_AR_16_9; ADM_dealloc (inputratio); inputratio = NULL; } if (!DIA_resizeWiz (&format, &sourceAR, &destinationAR)) return 0; targetx=allFormats[format]->x1; targetxFinal=allFormats[format]->x2; targetyPAL=allFormats[format]->y1; targetyNTSC=allFormats[format]->y2; info = getLastVideoFilter (frameStart, frameEnd - frameStart)->getInfo (); res = identMovieType (info->fps1000); //printf("fps : %lu / %d \n",info->fps1000,res); switch (res) { case FRAME_PAL: res = 1; break; case FRAME_NTSC: case FRAME_FILM: res = 2; break; default: res = 0; return 0; break; } if (res == 2) targety = targetyNTSC; else targety = targetyPAL; double rx, ry; uint32_t newx, newy; uint32_t cropx, cropy; uint32_t original_x, original_y; original_x = info->width; original_y = info->height; // scale as if it was 1:1 -> 4:3 rx = original_x; switch (res) { case 1: //PAL rx = rx *aspectRatio[1][sourceAR]/aspectRatio[1][destinationAR]; break; case 2: // NTSC rx = rx * aspectRatio[0][sourceAR]/aspectRatio[0][destinationAR]; break; } original_x = (uint32_t) floor (rx + 0.49); rx = original_x; rx = rx / targetxFinal; ry = original_y; ry = ry / targety; // which do do we compress less ? if (rx > ry) // resize by X, add border afterward { newx = targetx; ry = original_y; ry = ry / rx; newy = (uint32_t) floor (ry + 0.49); printf (" resize by x\n"); } else { newy = targety; rx = original_x; rx = rx / ry; rx *= targetx; rx /= targetxFinal; newx = (uint32_t) floor (rx + 0.49); printf (" resize by y\n"); } printf ("\n New X x Y = %u x %u\n", newx, newy); // correct odd / even newx -= newx % 4; newy -= newy % 4; // Now correct crop cropx = targetx - newx; cropy = targety - newy; printf ("\n Resized to : %u x %u, add black border %u x %u", newx, newy, cropx, cropy); // now build filter // first resize (if needed) CONFcouple *couple; if (newx != info->width || newy != info->height) { videofilters[nb_active_filter].filter = createResizeFromParam (getLastVideoFilter (), newx, newy); videofilters[nb_active_filter].tag = VF_MPLAYERRESIZE; videofilters[nb_active_filter].filter->getCoupledConf (&couple); videofilters[nb_active_filter].conf = couple;; nb_active_filter++; } // then add crop (if needed) if (cropx || cropy) { videofilters[nb_active_filter].filter = create_addBorder (videofilters[nb_active_filter - 1].filter, cropx >> 1, cropx >> 1, cropy >> 1, cropy >> 1); videofilters[nb_active_filter].tag = VF_ADDBORDER; videofilters[nb_active_filter].filter->getCoupledConf (&couple); videofilters[nb_active_filter].conf = couple;; nb_active_filter++; }
//static uint8_t Vbuffer[7.0*5.6*3]; //AVDMGenericVideoStream *getFirstVideoFilter( void) // //_____________________________________________________________ void GUI_PlayAvi(void) { uint32_t time_e, time_a = 0; uint32_t err = 0, acc = 0; uint32_t max; uint32_t framelen,flags; AVDMGenericVideoStream *filter; vids = 0, auds = 0, dauds = 0; // check we got everything... if (!avifileinfo) return; if((curframe+1)>= avifileinfo->nb_frames-1) { printf("No frame left\n"); return; } if (avifileinfo->fps1000 == 0) return; if (playing) { stop_req = 1; return; } uint32_t priorityLevel; originalPriority = getpriority(PRIO_PROCESS, 0); prefs->get(PRIORITY_PLAYBACK,&priorityLevel); setpriority(PRIO_PROCESS, 0, ADM_getNiceValue(priorityLevel)); uint32_t played_frame=0; uint32_t remaining=avifileinfo->nb_frames-curframe; if(getPreviewMode()==ADM_PREVIEW_OUTPUT) { filter=getLastVideoFilter(curframe,remaining); } else { filter=getFirstVideoFilter(curframe,remaining ); } max=filter->getInfo()->nb_frames; // compute how much a frame lasts in ms one_frame = (uint32_t) floor(1000.*1000.*10. / filter->getInfo()->fps1000); err = one_frame % 10; one_frame /= 10; // Duration of a frame in ms, err =leftover in 1/10 ms // go to RealTime... printf("One frame : %lu, err=%lu ms\n", one_frame, err); // prepare 1st frame stop_req = 0; playing = 1; #ifdef HAVE_AUDIO ComputePreload(); #endif //renderStartPlaying(); // reset timer reference resetTime(); admPreview::deferDisplay(1,curframe); admPreview::update(played_frame); do { vids++; admPreview::displayNow(played_frame);; update_status_bar(); if (time_a == 0) time_a = getTime(0); // mark ! //printf("\n Rendering %lu frame\n",curframe); // read frame in chunk if((played_frame)>=(max-1)) { printf("\nEnd met (%lu / %lu )\n",played_frame,max); goto abort_play; } admPreview::update(played_frame+1);; curframe++; played_frame++; #ifdef HAVE_AUDIO FillAudio(); #endif time_e = getTime(1); acc += err; if (acc > 10) { acc -= 10; time_a++; } time_a += one_frame; // delta a is next frame time // time is is current time delta = time_a - time_e; if (delta <= 0) { //if(delta<-19) // allow 19 ms late without warning... // tick seems to be ~ 18 ms //printf("\n Late ....,due : %lu ms / found : %lu \n", // time_a,time_e); // a call to whatever sleep function will last at leat 10 ms // give some time to GTK } else { // a call to whatever sleep function will last at leat 10 ms // give some time to GTK if (delta > 10) GUI_Sleep(delta - 10); } // UI_purge(); if(getPreviewMode()==ADM_PREVIEW_SEPARATE ) { UI_purge(); UI_purge(); } } while (!stop_req); abort_play: // ___________________________________ // Flush buffer // go back to normal display mode //____________________________________ playing = 0; getFirstVideoFilter( ); admPreview::deferDisplay(0,0); UI_purge(); // Updated by expose ? admPreview::update(curframe); UI_purge(); update_status_bar(); #ifdef HAVE_AUDIO if (currentaudiostream) { if (wavbuf) ADM_dealloc(wavbuf); deleteAudioFilter(NULL); currentaudiostream->endDecompress(); AVDM_AudioClose(); } #endif // done. setpriority(PRIO_PROCESS, 0, originalPriority); };
//static uint8_t Vbuffer[7.0*5.6*3]; //AVDMGenericVideoStream *getFirstVideoFilter( void) // //_____________________________________________________________ void GUI_PlayAvi(void) { uint32_t time_e, time_a = 0; uint32_t err = 0, acc = 0; uint32_t max; uint32_t framelen,flags; AVDMGenericVideoStream *filter; ADMImage *buffer=NULL; vids = 0, auds = 0, dauds = 0; // check we got everything... if (!avifileinfo) return; if((curframe+1)>= avifileinfo->nb_frames-1) { printf("No frame left\n"); return; } if (avifileinfo->fps1000 == 0) return; if (playing) { stop_req = 1; return; } uint32_t played_frame=0; uint32_t remaining=avifileinfo->nb_frames-curframe; if(guiOutputDisplay) { filter=getLastVideoFilter(curframe,remaining); if(mode_preview) { editorKillPreview (); UI_setPreviewToggleStatus( 0 ); mode_preview=0; } } else { filter=getFirstVideoFilter(curframe,remaining ); } max=filter->getInfo()->nb_frames; // compute how much a frame lasts in ms one_frame = (uint32_t) floor(1000.*1000.*10. / filter->getInfo()->fps1000); err = one_frame % 10; one_frame /= 10; // Duration of a frame in ms, err =leftover in 1/10 ms buffer=new ADMImage(filter->getInfo()->width,filter->getInfo()->height); // go to RealTime... printf(" One frame : %lu, err=%lu ms\n", one_frame, err); // read frame in chunk if(!filter->getFrameNumberNoAlloc(1,&framelen,buffer,&flags)) { printf("\n cannot read frame!\n"); goto abort_play; } curframe++; played_frame++; // prepare 1st frame stop_req = 0; playing = 1; #ifdef HAVE_AUDIO ComputePreload(); #endif renderResize(filter->getInfo()->width,filter->getInfo()->height,currentZoom); renderStartPlaying(); // reset timer reference resetTime(); do { vids++; renderUpdateImage(buffer->data); if(mode_preview&&!guiOutputDisplay) { editorUpdatePreview(played_frame); } update_status_bar(buffer); if (time_a == 0) time_a = getTime(0); // mark ! //printf("\n Rendering %lu frame\n",curframe); // read frame in chunk if((played_frame)>=(max-1)) { printf("\n End met (%lu / %lu )\n",played_frame,max); goto abort_play; } if(!filter->getFrameNumberNoAlloc(played_frame+1,&framelen,buffer,&flags)) { printf("\n cannot read frame!\n"); goto abort_play; } curframe++; played_frame++; #ifdef HAVE_AUDIO FillAudio(); #endif time_e = getTime(1); acc += err; if (acc > 10) { acc -= 10; time_a++; } time_a += one_frame; // delta a is next frame time // time is is current time delta = time_a - time_e; if (delta <= 0) { //if(delta<-19) // allow 19 ms late without warning... // tick seems to be ~ 18 ms //printf("\n Late ....,due : %lu ms / found : %lu \n", // time_a,time_e); // a call to whatever sleep function will last at leat 10 ms // give some time to GTK } else { // a call to whatever sleep function will last at leat 10 ms // give some time to GTK if (delta > 10) GUI_Sleep(delta - 10); } // UI_purge(); if(mode_preview) { UI_purge(); UI_purge(); } } while (!stop_req); abort_play: // ___________________________________ // Flush buffer // go back to normal display mode //____________________________________ playing = 0; delete buffer; renderStopPlaying(); renderResize(avifileinfo->width , avifileinfo->height,currentZoom); getFirstVideoFilter( ); //video_body->getUncompressedFrame(curframe, rdr_decomp_buffer,&flags); GUI_getFrame(curframe, rdr_decomp_buffer, &flags); renderUpdateImage(rdr_decomp_buffer->data); renderRefresh(); update_status_bar(rdr_decomp_buffer); if(mode_preview) { editorUpdatePreview(curframe); } #ifdef HAVE_AUDIO if (currentaudiostream) { if (wavbuf) ADM_dealloc(wavbuf); deleteAudioFilter(NULL); currentaudiostream->endDecompress(); AVDM_AudioClose(); } #endif // done. };
uint8_t GenericAviSaveProcess::setupVideo (char *name) { _notnull=0; _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); frametogo=_incoming->getInfo()->nb_frames; encoding_gui->setFps(_incoming->getInfo()->fps1000); // anish if(_incoming->getInfo()->width%8) { if(!GUI_Question("Width is not a multiple of 8\n continue anyway ?")) return 0; } _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; // init compressor TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,frametogo); if (!_encode->configure (_incoming)) { delete _encode; _encode = NULL; GUI_Error_HIG ("Filter init failed", NULL); return 0; }; memcpy (&_bih, video_body->getBIH (), sizeof (_bih)); _bih.biWidth = _incoming->getInfo ()->width; _bih.biHeight = _incoming->getInfo ()->height; _bih.biSize=sizeof(_bih); _bih.biXPelsPerMeter=_bih.biClrUsed=_bih.biYPelsPerMeter=0; _mainaviheader.dwTotalFrames= _incoming->getInfo ()->nb_frames; _mainaviheader.dwMicroSecPerFrame=0; printf("\n Saved as %ld x %ld\n",_bih.biWidth,_bih.biHeight); _bih.biCompression=fourCC::get((uint8_t *)_encode->getCodecName()); encoding_gui->setCodec(_encode->getDisplayName()); // init save avi //-----------------------VBR-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; FILE *tmp; uint8_t reuse=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question("\n Reuse the existing log-file ?")) { reuse=1; } } if(!reuse) { guiSetPhasis ("1st Pass"); aprintf("**Pass 1:%lu\n",frametogo); buffer = new uint8_t[_incoming->getInfo ()->width * _incoming->getInfo ()->height * 3]; _encode->startPass1 (); //__________________________________ // now go to main loop..... //__________________________________ for (uint32_t cf = 0; cf < frametogo; cf++) { if (guiUpdate (cf, frametogo)) { abt: GUI_Error_HIG ("Aborting", NULL); delete[]buffer; return 0; } if (!_encode->encode (cf, &len, buffer, &flag)) { printf("\n Encoding of frame %lu failed !\n",cf); goto abt; } encoding_gui->setQuant(_encode->getLastQz()); encoding_gui->feedFrame(len); } // guiStop (); encoding_gui->reset(); delete[]buffer; aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } } //-------------------------/VBR----------------------------------- // init save avi // now we build the new stream ! aprintf("**main pass:\n"); memcpy(&_videostreamheader,video_body->getVideoStreamHeader (),sizeof(_videostreamheader)); memcpy(&_videostreamheader.fccHandler ,_encode->getFCCHandler(),4); _videostreamheader.fccType =fourCC::get((uint8_t *)"vids"); _videostreamheader.dwScale=1000; _videostreamheader.dwRate= _incoming->getInfo ()->fps1000; memcpy(&_mainaviheader ,video_body->getMainHeader (),sizeof(_mainaviheader)); _mainaviheader.dwWidth=_bih.biWidth; _mainaviheader.dwHeight=_bih.biHeight; _videostreamheader.dwQuality=10000; uint8_t *data; uint32_t dataLen=0; _encode->hasExtraHeaderData( &dataLen,&data); if (!writter->saveBegin (name, &_mainaviheader, frameEnd - frameStart + 1, &_videostreamheader, &_bih, data,dataLen, (AVDMGenericAudioStream *) audio_filter, NULL)) { return 0; } aprintf("Setup video done\n"); return 1; //--------------------- }
uint8_t GenericAviSaveProcess::setupVideo (char *name) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); frametogo=_incoming->getInfo()->nb_frames; encoding_gui->setFps(_incoming->getInfo()->fps1000); // anish if(_incoming->getInfo()->width%8) { if(!GUI_Question(QT_TR_NOOP("Width is not a multiple of 8\n continue anyway ?"))) return 0; } _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; // init compressor TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,frametogo); int reuse = 0; if (_encode->isDualPass()) { FILE *tmp; if ((tmp = fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if (GUI_Question(QT_TR_NOOP("Reuse the existing log file?"))) reuse = 1; } } if (!_encode->configure (_incoming, reuse)) { delete _encode; _encode = NULL; GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL); return 0; }; memcpy (&_bih, video_body->getBIH (), sizeof (_bih)); _bih.biWidth = _incoming->getInfo ()->width; _bih.biHeight = _incoming->getInfo ()->height; _bih.biSize=sizeof(_bih); _bih.biXPelsPerMeter=_bih.biClrUsed=_bih.biYPelsPerMeter=0; _mainaviheader.dwTotalFrames= _incoming->getInfo ()->nb_frames; _mainaviheader.dwMicroSecPerFrame=0; printf("\n Saved as %ld x %ld\n",_bih.biWidth,_bih.biHeight); _bih.biCompression=fourCC::get((uint8_t *)_encode->getCodecName()); encoding_gui->setCodec(_encode->getDisplayName()); // init save avi //-----------------------2 Pass-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; int r, frameDelay = 0; aprintf("\n** Dual pass encoding**\n"); if(!reuse) { guiSetPhasis (QT_TR_NOOP("1st Pass")); aprintf("**Pass 1:%lu\n",frametogo); buffer = new uint8_t[_incoming->getInfo ()->width * _incoming->getInfo ()->height * 3]; _encode->startPass1 (); bitstream.bufferSize = _incoming->getInfo()->width * _incoming->getInfo()->height * 3; bitstream.data=buffer; for (uint32_t cf = 0; cf < frametogo; cf++) { if (guiUpdate (cf, frametogo)) { abt: GUI_Error_HIG (QT_TR_NOOP("Aborting"), NULL); delete[] buffer; return 0; } for (;;) { bitstream.cleanup(cf); if (cf + frameDelay >= frametogo) { if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH) r = _encode->encode(UINT32_MAX, &bitstream); else r = 0; } else r = _encode->encode(cf + frameDelay, &bitstream); if (!r) { printf("Encoding of frame %lu failed!\n", cf); goto abt; } if (bitstream.len == 0 && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)) { printf("skipping frame: %u size: %i\n", cf + frameDelay, bitstream.len); frameDelay++; } else break; } encoding_gui->setFrame(cf,bitstream.len,bitstream.out_quantizer,frametogo); } encoding_gui->reset(); delete[]buffer; aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } } //-------------------------/VBR----------------------------------- // init save avi // now we build the new stream ! aprintf("**main pass:\n"); memcpy(&_videostreamheader,video_body->getVideoStreamHeader (),sizeof(_videostreamheader)); memcpy(&_videostreamheader.fccHandler ,_encode->getFCCHandler(),4); _videostreamheader.fccType =fourCC::get((uint8_t *)"vids"); _videostreamheader.dwScale=1000; _videostreamheader.dwRate= _incoming->getInfo ()->fps1000; memcpy(&_mainaviheader ,video_body->getMainHeader (),sizeof(_mainaviheader)); _mainaviheader.dwWidth=_bih.biWidth; _mainaviheader.dwHeight=_bih.biHeight; _videostreamheader.dwQuality=10000; uint8_t *data; uint32_t dataLen=0; _encode->hasExtraHeaderData( &dataLen,&data); if (!writter->saveBegin (name, &_mainaviheader, frameEnd - frameStart + 1, &_videostreamheader, &_bih, data,dataLen, (AVDMGenericAudioStream *) audio_filter, NULL)) { return 0; } aprintf("Setup video done\n"); bitstream.data=vbuffer; bitstream.bufferSize=MAXIMUM_SIZE * MAXIMUM_SIZE * 3; 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 = NULL; 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 || (videoCodecGetType() == CodecExternal && strcmp(videoCodecPluginGetGuid(), "85FC9CAC-CE6C-4aa6-9D5F-352D6349BA3E") == 0)) // MPEG-1 plugin { 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 encoder = getVideoEncoder(_w, _h, 0); if (encoder == NULL) return 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; case CodecExternal: encoding->setCodec(encoder->getDisplayName()); 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"); if (encoding) 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 ADM_ogmWriteProcess::initVideo(void) { uint32_t w,h,fps1000,fcc; _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _togo=_incoming->getInfo()->nb_frames; _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; _encode->setLogFile(TwoPassLogFile,_togo); if (!_encode->configure (_incoming)) { delete _encode; _encode = NULL; GUI_Alert ("Init of filter failed"); return 0; }; w= _incoming->getInfo ()->width; h=_incoming->getInfo ()->height; fps1000=_incoming->getInfo ()->fps1000; _fps1000=fps1000; fcc= fourCC::get((uint8_t *)_encode->getCodecName()); _videoBuffer=new uint8_t[w*h*3]; encoding_gui->setCodec(_encode->getDisplayName()); //-----------------------VBR-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; FILE *tmp; uint8_t reuse=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question("\n Reuse the existing log-file ?")) { reuse=1; } } if(!reuse) { aprintf("**Pass 1:%lu\n",_togo); _encode->startPass1 (); encoding_gui->setCodec((char *)_encode->getCodecName()); encoding_gui->setPhasis("Pass one"); //__________________________________ // now go to main loop..... //__________________________________ for (uint32_t cf = 0; cf < _togo; cf++) { if (!_encode->encode (cf, &len, _videoBuffer, &flag)) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } encoding_gui->feedFrame(len); encoding_gui->setFrame(cf,_togo); encoding_gui->setQuant(_encode->getLastQz()); if(!encoding_gui->isAlive()) { return 0; } } aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } encoding_gui->setPhasis("Pass 2"); } //-------------------------/VBR----------------------------------- else { encoding_gui->setPhasis("Encoding"); } // init save avi // now we build the new stream ! aprintf("**main pass:\n"); stream_header header; memset(&header,0,sizeof(header)); memcpy(&(header.streamtype),"video\0\0\0",8); memcpy(&(header.subtype),&fcc,4); header.size=sizeof(header); header.video.width=w; header.video.height=h; // Timing .. double duration; // duration in 10us duration=fps1000; duration=1000./duration; duration*=1000*1000; duration*=10; header.time_unit=(int64_t)duration; header.samples_per_unit=1; header.buffersize=0x10000; header.bits_per_sample=24; header.default_len=1; return videoStream->writeHeaders(sizeof(header),(uint8_t *)&header); // +4 ? }
unsigned int calculatorDialog::getPictureSize(void) { AVDMGenericVideoStream *last = getLastVideoFilter(); return last->getInfo()->width * last->getInfo()->height; }
//________________________________________________ uint8_t ADM_ogmWriteProcess::initVideo(const char *name) { uint32_t w,h,fps1000,fcc; _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _togo=_incoming->getInfo()->nb_frames; _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,_togo); if (!_encode->configure (_incoming)) { delete _encode; _encode = NULL; GUI_Error_HIG (_("Filter init failed"), NULL); return 0; }; w= _incoming->getInfo ()->width; h=_incoming->getInfo ()->height; fps1000=_incoming->getInfo ()->fps1000; _fps1000=fps1000; fcc= fourCC::get((uint8_t *)_encode->getCodecName()); _videoBuffer=new uint8_t[w*h*3]; encoding_gui->setCodec(_encode->getDisplayName()); //-----------------------VBR-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; FILE *tmp; uint8_t reuse=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question(_("\n Reuse the existing log-file ?"))) { reuse=1; } } if(!reuse) { aprintf("**Pass 1:%lu\n",_togo); _encode->startPass1 (); encoding_gui->setCodec((char *)_encode->getCodecName()); encoding_gui->setPhasis("Pass one"); ADMBitstream bitstream; bitstream.data=_videoBuffer; //__________________________________ // now go to main loop..... //__________________________________ for (uint32_t cf = 0; cf < _togo; cf++) { bitstream.cleanup(cf); if (!_encode->encode (cf, &bitstream)) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } encoding_gui->feedFrame(bitstream.len); encoding_gui->setFrame(cf,_togo); encoding_gui->setQuant(bitstream.out_quantizer); if(!encoding_gui->isAlive()) { return 0; } } aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } encoding_gui->setPhasis("Pass 2"); } //-------------------------/VBR----------------------------------- else { encoding_gui->setPhasis("Encoding"); } // init save avi // now we build the new stream ! aprintf("**main pass:\n"); stream_header header; int64_t dur64; uint32_t dur32; uint16_t dur16; memset(&header,0,sizeof(header)); memcpy(&(header.streamtype),"video\0\0\0",8); MEMCPY(&(header.subtype),&fcc,4); //header.size=sizeof(header); dur32=sizeof(header); MEMCPY(&header.size,&dur32,4); MEMCPY(&(header.video.width),&w,4); MEMCPY(&(header.video.height),&h,4); // Timing .. double duration; // duration in 10us duration=fps1000; duration=1000./duration; duration*=1000*1000; duration*=10; dur64=(int64_t)duration; MEMCPY(&header.time_unit,&dur64,8); dur64=1; MEMCPY(&header.samples_per_unit,&dur64,8); dur32=0x10000; MEMCPY(&header.buffersize,&dur32,4); dur16=24; MEMCPY(&header.bits_per_sample,&dur16,2); //header.default_len=1; dur32=1; MEMCPY(&header.default_len,&dur32,4); return videoStream->writeHeaders(sizeof(header),(uint8_t *)&header); // +4 ? }