📄 2pass.cpp.svn-base
字号:
} // Foxer: make sure overflow doesn't run away if (overflow > bytes2 * config.twopass_max_overflow_improvement / 100) { bytes2 += (overflow <= bytes2) ? bytes2 * config.twopass_max_overflow_improvement / 100 : overflow * config.twopass_max_overflow_improvement / 100; } else if (overflow < bytes2 * config.twopass_max_overflow_degradation / -100) { bytes2 += bytes2 * config.twopass_max_overflow_degradation / -100; } else { bytes2 += overflow; } if (bytes2 > twopass.max_framesize) { capped_to_max_framesize = 1; bytes2 = twopass.max_framesize; } // make sure to not scale below the minimum framesize if (twopass.nns1.quant & NNSTATS_KEYFRAME) { if (bytes2 < twopass.minisize) bytes2 = twopass.minisize; } else if (twopass.nns1.dd_v & NNSTATS_BFRAME) { if (bytes2 < twopass.minbsize) bytes2 = twopass.minbsize; } else { if (bytes2 < twopass.minpsize) bytes2 = twopass.minpsize; } twopass.bytes1 = bytes1; twopass.bytes2 = bytes2; // very 'simple' quant<->filesize relationship frame->quant = ((twopass.nns1.quant & ~NNSTATS_KEYFRAME) * bytes1) / bytes2; if (frame->quant < 1) { frame->quant = 1; } else if (frame->quant > 31) { frame->quant = 31; } else if (!(frame->frametype==FRAME_TYPE::I)) { // Foxer: aid desired quantizer precision by accumulating decision error if (twopass.nns1.dd_v & NNSTATS_BFRAME) { bquant_error[frame->quant] += ((double)((twopass.nns1.quant & ~NNSTATS_KEYFRAME) * bytes1) / bytes2) - frame->quant; if (bquant_error[frame->quant] >= 1.0) { bquant_error[frame->quant] -= 1.0; ++frame->quant; } } else { pquant_error[frame->quant] += ((double)((twopass.nns1.quant & ~NNSTATS_KEYFRAME) * bytes1) / bytes2) - frame->quant; if (pquant_error[frame->quant] >= 1.0) { pquant_error[frame->quant] -= 1.0; ++frame->quant; } } } // we're done with credits if (codec_is_in_credits( framenum)) { return ICERR_OK; } if ((frame->frametype==FRAME_TYPE::I)) { if (frame->quant < config.q_i_min) { frame->quant = config.q_i_min; DEBUG2P(_l("I-frame quantizer raised")); } if (frame->quant > config.q_i_max) { frame->quant = config.q_i_max; DEBUG2P(_l("I-frame quantizer lowered")); } } else { if (frame->quant > config.q_p_max) { frame->quant = config.q_p_max; } if (frame->quant < config.q_p_min) { frame->quant = config.q_p_min; } // subsequent frame quants can only be +- 2 if ((last_pquant || last_bquant) && capped_to_max_framesize == 0) { if (twopass.nns1.dd_v & NNSTATS_BFRAME) { // this bframe quantizer variation // restriction needs to be redone. if (frame->quant > last_bquant + 2) { frame->quant = last_bquant + 2; DEBUG2P(_l("B-frame quantizer prevented from rising too steeply")); } if (frame->quant < last_bquant - 2) { frame->quant = last_bquant - 2; DEBUG2P(_l("B-frame quantizer prevented from falling too steeply")); } } else { if (frame->quant > last_pquant + 2) { frame->quant = last_pquant + 2; DEBUG2P(_l("P-frame quantizer prevented from rising too steeply")); } if (frame->quant < last_pquant - 2) { frame->quant = last_pquant - 2; DEBUG2P(_l("P-frame quantizer prevented from falling too steeply")); } } } } if (capped_to_max_framesize == 0) { if (twopass.nns1.quant & NNSTATS_KEYFRAME) { last_bquant = frame->quant; last_pquant = frame->quant; } else if (twopass.nns1.dd_v & NNSTATS_BFRAME) last_bquant = frame->quant; else last_pquant = frame->quant; } return ICERR_OK;}int Txvid_2pass::codec_2pass_update(const TencFrameParams *frame){ int credits_pos, tempdiv; char_t* frame_type; if (framenum == 0) { total_size = 0; } if (statsWrite) { NNSTATS nns1; nns1.bytes = frame->length; // total bytes nns1.dd_v = 0; nns1.dd_u = nns1.dd_y = 0; nns1.dk_v = nns1.dk_u = nns1.dk_y = 0; nns1.md_u = nns1.md_y = 0; nns1.mk_u = nns1.mk_y = 0; nns1.quant = frame->quant; // 2 ugly fix for lumi masking in 1st pass returning new quant nns1.lum_noise[0] = nns1.lum_noise[1] = 1; frame_type=_l("inter"); if (frame->frametype ==FRAME_TYPE::I) { nns1.quant |= NNSTATS_KEYFRAME; frame_type=_l("intra"); } else if (frame->frametype==FRAME_TYPE::B) { nns1.dd_v |= NNSTATS_BFRAME; frame_type=_l("bframe"); } else if (frame->frametype==FRAME_TYPE::SKIP) { nns1.dd_v |= NNSTATS_SKIPFRAME; frame_type=_l("skiped"); } else if (frame->frametype==FRAME_TYPE::PAD) { nns1.dd_v |= NNSTATS_PADFRAME; frame_type=_l("padded"); } else if (frame->frametype==FRAME_TYPE::DELAY) { nns1.dd_v |= NNSTATS_DELAYFRAME; frame_type=_l("delayed"); } if (frame->kblks+frame->mblks+frame->ublks==0) { nns1.kblk = 1; nns1.mblk = 1; nns1.ublk = 1; } else { nns1.kblk = frame->kblks; nns1.mblk = frame->mblks; nns1.ublk = frame->ublks; } total_size += frame->length; DEBUG1ST(frame->length, (int)total_size/1024, frame_type, frame->quant, _l(""), 1, 1); if (statsWrite->write(&nns1)!=sizeof(NNSTATS)) { DEBUGERR(_l("stats1: WriteFile error")); return ICERR_ERROR; } } if (config.mode==DLG_MODE_2PASS_2_INT || config.mode==DLG_MODE_2PASS_2_EXT) { credits_pos = codec_is_in_credits(framenum); if (!(twopass.nns1.dd_v & NNSTATS_SKIPFRAME) && !(twopass.nns1.dd_v & NNSTATS_PADFRAME) && !(twopass.nns1.dd_v & NNSTATS_DELAYFRAME)) { if (!credits_pos) { if ((twopass.nns1.quant & NNSTATS_KEYFRAME)) { // calculate how much to distribute per frame in // order to make up for this keyframe's overflow twopass.overflow += twopass.KFoverflow; twopass.KFoverflow = twopass.desired_bytes2 - frame->length; tempdiv = (twopass.keyframe_locations[twopass.KF_idx] - twopass.keyframe_locations[twopass.KF_idx - 1]); if (tempdiv > 1) { // non-consecutive keyframes twopass.KFoverflow_partial = twopass.KFoverflow / (tempdiv - 1); } else { // consecutive keyframes twopass.overflow += twopass.KFoverflow; twopass.KFoverflow = 0; twopass.KFoverflow_partial = 0; } twopass.KF_idx++; } else { // distribute part of the keyframe overflow twopass.overflow += twopass.desired_bytes2 - frame->length + twopass.KFoverflow_partial; twopass.KFoverflow -= twopass.KFoverflow_partial; } } else { twopass.overflow += twopass.desired_bytes2 - frame->length; // ugly fix for credits.. twopass.overflow += twopass.KFoverflow; twopass.KFoverflow = 0; twopass.KFoverflow_partial = 0; // end of ugly fix. } } frame_type=_l("inter"); if (frame->frametype==FRAME_TYPE::I) { frame_type=_l("intra"); } else if (twopass.nns1.dd_v & NNSTATS_BFRAME) { frame_type=_l("bframe"); } else if (twopass.nns1.dd_v & NNSTATS_SKIPFRAME) { frame_type=_l("skipped"); //frame->quant = 2; twopass.bytes1 = 1; twopass.desired_bytes2 = 1; //frame->length = 1; } else if (twopass.nns1.dd_v & NNSTATS_PADFRAME) { frame_type=_l("padded"); //frame->quant = 2; twopass.bytes1 = 7; twopass.desired_bytes2 = 7; //frame->length = 7; } else if (twopass.nns1.dd_v & NNSTATS_DELAYFRAME) { frame_type=_l("delayed"); //frame->quant = 2; twopass.bytes1 = 1; twopass.desired_bytes2 = 1; //frame->length = 1; } DEBUG2ND(frame->quant, _l(""), frame_type, twopass.bytes1, twopass.desired_bytes2, frame->length, twopass.overflow, credits_pos); } return ICERR_OK;}void Txvid_2pass::codec_2pass_finish(void){ twopass.nns_array_length = 0; twopass.nns_array_pos = 0;}Txvid_2pass::Txvid_2pass(void){ statsRead=statsRead2=statsWrite=NULL; ownStatsRead=ownStatsRead2=ownStatsWrite=NULL;}Txvid_2pass::~Txvid_2pass(){ if (ownStatsRead ) delete ownStatsRead ; if (ownStatsRead2) delete ownStatsRead2; if (ownStatsWrite) delete ownStatsWrite;}//================================= T2passFirst ==================================T2passFirst::T2passFirst(const TcoSettings &Iconfig){ config=Iconfig; codec_2pass_init();}T2passFirst::~T2passFirst(){ codec_2pass_finish();}bool T2passFirst::update(const TencFrameParams &frame){ return codec_2pass_update(&frame)==ICERR_OK;}//================================= T2passSecond =================================T2passSecond::T2passSecond(IffdshowEnc *IdeciE,bool Iquiet):quiet(Iquiet),deciE(IdeciE),deci(IdeciE){ start();}T2passSecond::T2passSecond(IffdshowEnc *IdeciE,TxvidStats *IstatsRead,TxvidStats *IstatsRead2,TxvidStats *IstatsWrite,bool Iquiet):quiet(Iquiet),deciE(IdeciE),deci(IdeciE){ statsRead =IstatsRead; statsRead2=IstatsRead2; statsWrite=IstatsWrite; start();}T2passSecond::~T2passSecond(){ codec_2pass_finish();}void T2passSecond::start(void){ const TcoSettings *Iconfig;deciE->getCoSettingsPtr(&Iconfig); config=*Iconfig; twopass.max_framesize=int((double)config.twopass_max_bitrate/8.0/((double)deci->getParam2(IDFF_enc_fpsRate)/(double)deci->getParam2(IDFF_enc_fpsScale))); framenum=0; memset(quant_threshs,0,sizeof(quant_threshs)); codec_2pass_init();}void T2passSecond::DEBUG2P(const char_t*s){ if (!quiet) deci->dbgWrite(_l("%s"),s);}bool T2passSecond::getQuantSecond(TencFrameParams ¶ms){ framenum=params.framenum; int ret=codec_2pass_get_quant(¶ms); return ret==ICERR_OK;}int T2passSecond::getQuantFirst(void){ return twopass.nns1.quant&NNSTATS_QUANTMASK;}unsigned int T2passSecond::getBytesFirst(void){ return twopass.bytes1;}void T2passSecond::writeInfo(const TencFrameParams ¶ms){ deci->dbgWrite(_l("2nd-pass: quant:%d %s %s stats1:%d scaled:%d actual:%d overflow:%d %s\n"),params.quant,encQuantTypes[params.quanttype],FRAME_TYPE::name(params.frametype),twopass.bytes1,twopass.bytes2,params.length,twopass.overflow,config.isInCredits(params.framenum)?_l("credits"):_l("movie"));}bool T2passSecond::update(const TencFrameParams &frame){ codec_2pass_update(&frame); return true;}int T2passSecond::codec_is_in_credits(int framenum){ return config.isInCredits(framenum);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -