📄 ratecontrol.c
字号:
} } else { return X264_TYPE_AUTO; }}/* After encoding one frame, save stats and update ratecontrol state */void x264_ratecontrol_end( x264_t *h, int bits ){ x264_ratecontrol_t *rc = h->rc; const int *mbs = h->stat.frame.i_mb_count; int i; x264_cpu_restore( h->param.cpu ); h->stat.frame.i_mb_count_skip = mbs[P_SKIP] + mbs[B_SKIP]; h->stat.frame.i_mb_count_i = mbs[I_16x16] + mbs[I_8x8] + mbs[I_4x4]; h->stat.frame.i_mb_count_p = mbs[P_L0] + mbs[P_8x8]; for( i = B_DIRECT; i < B_8x8; i++ ) h->stat.frame.i_mb_count_p += mbs[i]; if( h->mb.b_variable_qp ) { for( i = 1; i < h->param.i_threads; i++ ) rc->qpa += rc[i].qpa; rc->qpa /= h->mb.i_mb_count; } else rc->qpa = (float)rc->qp; h->fdec->f_qp_avg = rc->qpa; if( h->param.rc.b_stat_write ) { char c_type = rc->slice_type==SLICE_TYPE_I ? (h->fenc->i_poc==0 ? 'I' : 'i') : rc->slice_type==SLICE_TYPE_P ? 'P' : h->fenc->b_kept_as_ref ? 'B' : 'b'; int dir_frame = h->stat.frame.i_direct_score[1] - h->stat.frame.i_direct_score[0]; int dir_avg = h->stat.i_direct_score[1] - h->stat.i_direct_score[0]; char c_direct = h->mb.b_direct_auto_write ? ( dir_frame>0 ? 's' : dir_frame<0 ? 't' : dir_avg>0 ? 's' : dir_avg<0 ? 't' : '-' ) : '-'; fprintf( rc->p_stat_file_out, "in:%d out:%d type:%c q:%.2f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c;\n", h->fenc->i_frame, h->i_frame, c_type, rc->qpa, h->stat.frame.i_itex_bits, h->stat.frame.i_ptex_bits, h->stat.frame.i_hdr_bits, h->stat.frame.i_misc_bits, h->stat.frame.i_mb_count_i, h->stat.frame.i_mb_count_p, h->stat.frame.i_mb_count_skip, c_direct); } if( rc->b_abr ) { if( rc->slice_type != SLICE_TYPE_B ) rc->cplxr_sum += bits * qp2qscale(rc->qpa) / rc->last_rceq; else { /* Depends on the fact that B-frame's QP is an offset from the following P-frame's. * Not perfectly accurate with B-refs, but good enough. */ rc->cplxr_sum += bits * qp2qscale(rc->qpa) / (rc->last_rceq * fabs(h->param.rc.f_pb_factor)); } rc->cplxr_sum *= rc->cbr_decay; rc->wanted_bits_window += rc->bitrate / rc->fps; rc->wanted_bits_window *= rc->cbr_decay; rc->accum_p_qp *= .95; rc->accum_p_norm *= .95; rc->accum_p_norm += 1; if( rc->slice_type == SLICE_TYPE_I ) rc->accum_p_qp += rc->qpa * fabs(h->param.rc.f_ip_factor); else rc->accum_p_qp += rc->qpa; } if( rc->b_2pass ) { rc->expected_bits_sum += qscale2bits( rc->rce, qp2qscale(rc->rce->new_qp) ); } if( h->mb.b_variable_qp ) { if( rc->slice_type == SLICE_TYPE_B ) { rc->bframe_bits += bits; if( !h->frames.current[0] || !IS_X264_TYPE_B(h->frames.current[0]->i_type) ) update_predictor( &rc->pred_b_from_p, qp2qscale(rc->qpa), h->fref1[0]->i_satd, rc->bframe_bits / rc->bframes ); } else { /* Update row predictor based on data collected by other threads. */ int y; for( y = rc->last_row+1; y < h->sps->i_mb_height; y++ ) update_predictor( rc->row_pred, qp2qscale(h->fdec->i_row_qp[y]), h->fdec->i_row_satd[y], h->fdec->i_row_bits[y] ); rc->row_preds[rc->slice_type] = *rc->row_pred; } } update_vbv( h, bits ); if( rc->slice_type != SLICE_TYPE_B ) rc->last_non_b_pict_type = rc->slice_type;}/**************************************************************************** * 2 pass functions ***************************************************************************/double x264_eval( char *s, double *const_value, const char **const_name, double (**func1)(void *, double), const char **func1_name, double (**func2)(void *, double, double), char **func2_name, void *opaque );/** * modify the bitrate curve from pass1 for one frame */static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor, int frame_num){ x264_ratecontrol_t *rcc= h->rc; const int pict_type = rce->pict_type; double q; int i; double const_values[]={ rce->i_tex_bits * rce->qscale, rce->p_tex_bits * rce->qscale, (rce->i_tex_bits + rce->p_tex_bits) * rce->qscale, rce->mv_bits * rce->qscale, (double)rce->i_count / rcc->nmb, (double)rce->p_count / rcc->nmb, (double)rce->s_count / rcc->nmb, rce->pict_type == SLICE_TYPE_I, rce->pict_type == SLICE_TYPE_P, rce->pict_type == SLICE_TYPE_B, h->param.rc.f_qcompress, rcc->i_cplx_sum[SLICE_TYPE_I] / rcc->frame_count[SLICE_TYPE_I], rcc->i_cplx_sum[SLICE_TYPE_P] / rcc->frame_count[SLICE_TYPE_P], rcc->p_cplx_sum[SLICE_TYPE_P] / rcc->frame_count[SLICE_TYPE_P], rcc->p_cplx_sum[SLICE_TYPE_B] / rcc->frame_count[SLICE_TYPE_B], (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / rcc->frame_count[pict_type], rce->blurred_complexity, 0 }; static const char *const_names[]={ "iTex", "pTex", "tex", "mv", "iCount", "pCount", "sCount", "isI", "isP", "isB", "qComp", "avgIITex", "avgPITex", "avgPPTex", "avgBPTex", "avgTex", "blurCplx", NULL }; static double (*func1[])(void *, double)={// (void *)bits2qscale, (void *)qscale2bits, NULL }; static const char *func1_names[]={// "bits2qp", "qp2bits", NULL }; q = x264_eval((char*)h->param.rc.psz_rc_eq, const_values, const_names, func1, func1_names, NULL, NULL, rce); // avoid NaN's in the rc_eq
//yzl for CCS test ***************************************** if(!isfinite(q) || rce->i_tex_bits + rce->p_tex_bits + rce->mv_bits == 0)
// if( rce->i_tex_bits + rce->p_tex_bits + rce->mv_bits == 0) q = rcc->last_qscale; else { rcc->last_rceq = q; q /= rate_factor; rcc->last_qscale = q; } for( i = rcc->i_zones-1; i >= 0; i-- ) { x264_zone_t *z = &rcc->zones[i]; if( frame_num >= z->i_start && frame_num <= z->i_end ) { if( z->b_force_qp ) q = qp2qscale(z->i_qp); else q /= z->f_bitrate_factor; break; } } return q;}static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q){ x264_ratecontrol_t *rcc = h->rc; const int pict_type = rce->pict_type; // force I/B quants as a function of P quants const double last_p_q = rcc->last_qscale_for[SLICE_TYPE_P]; const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type]; if( pict_type == SLICE_TYPE_I ) { double iq = q; double pq = qp2qscale( rcc->accum_p_qp / rcc->accum_p_norm ); double ip_factor = fabs( h->param.rc.f_ip_factor ); /* don't apply ip_factor if the following frame is also I */ if( rcc->accum_p_norm <= 0 ) q = iq; else if( h->param.rc.f_ip_factor < 0 ) q = iq / ip_factor; else if( rcc->accum_p_norm >= 1 ) q = pq / ip_factor; else q = rcc->accum_p_norm * pq / ip_factor + (1 - rcc->accum_p_norm) * iq; } else if( pict_type == SLICE_TYPE_B ) { if( h->param.rc.f_pb_factor > 0 ) q = last_non_b_q; if( !rce->kept_as_ref ) q *= fabs( h->param.rc.f_pb_factor ); } else if( pict_type == SLICE_TYPE_P && rcc->last_non_b_pict_type == SLICE_TYPE_P && rce->i_tex_bits + rce->p_tex_bits == 0 ) { q = last_p_q; } /* last qscale / qdiff stuff */ if(rcc->last_non_b_pict_type==pict_type && (pict_type!=SLICE_TYPE_I || rcc->last_accum_p_norm < 1)) { double last_q = rcc->last_qscale_for[pict_type]; double max_qscale = last_q * rcc->lstep; double min_qscale = last_q / rcc->lstep; if (q > max_qscale) q = max_qscale; else if(q < min_qscale) q = min_qscale; } rcc->last_qscale_for[pict_type] = q; if(pict_type!=SLICE_TYPE_B) rcc->last_non_b_pict_type = pict_type; if(pict_type==SLICE_TYPE_I) { rcc->last_accum_p_norm = rcc->accum_p_norm; rcc->accum_p_norm = 0; rcc->accum_p_qp = 0; } if(pict_type==SLICE_TYPE_P) { float mask = (float)(1 - pow( (float)rce->i_count / rcc->nmb, 2 )); rcc->accum_p_qp = mask * (qscale2qp(q) + rcc->accum_p_qp); rcc->accum_p_norm = mask * (1 + rcc->accum_p_norm); } return q;}static double predict_size( predictor_t *p, double q, double var ){ return p->coeff*var / (q*p->count);}static void update_predictor( predictor_t *p, double q, double var, double bits ){ if( var < 10 ) return; p->count *= p->decay; p->coeff *= p->decay; p->count ++; p->coeff += bits*q / var;}static void update_vbv( x264_t *h, int bits ){ x264_ratecontrol_t *rcc = h->rc; if( rcc->last_satd >= h->mb.i_mb_count ) update_predictor( &rcc->pred[rcc->slice_type], qp2qscale(rcc->qpa), rcc->last_satd, bits ); if( !rcc->b_vbv ) return; rcc->buffer_fill += rcc->buffer_rate - bits; if( rcc->buffer_fill < 0 && !rcc->b_2pass ) x264_log( h, X264_LOG_WARNING, "VBV underflow (%.0f bits)\n", rcc->buffer_fill ); rcc->buffer_fill = x264_clip3( rcc->buffer_fill, 0, rcc->buffer_size );}// apply VBV constraints and clip qscale to between lmin and lmaxstatic double clip_qscale( x264_t *h, int pict_type, double q ){ x264_ratecontrol_t *rcc = h->rc; double lmin = rcc->lmin[pict_type]; double lmax = rcc->lmax[pict_type]; double q0 = q; /* B-frames are not directly subject to VBV, * since they are controlled by the P-frames' QPs. * FIXME: in 2pass we could modify previous frames' QP too, * instead of waiting for the buffer to fill */ if( rcc->b_vbv && ( pict_type == SLICE_TYPE_P || ( pict_type == SLICE_TYPE_I && rcc->last_non_b_pict_type == SLICE_TYPE_I ) ) ) { if( rcc->buffer_fill/rcc->buffer_size < 0.5 ) q /= x264_clip3f( 2.0*rcc->buffer_fill/rcc->buffer_size, 0.5, 1.0 ); } if( rcc->b_vbv && rcc->last_satd > 0 ) { /* Now a hard threshold to make sure the frame fits in VBV. * This one is mostly for I-frames. */ double bits = predict_size( &rcc->pred[rcc->slice_type], q, rcc->last_satd ); double qf = 1.0; if( bits > rcc->buffer_fill/2 ) qf = x264_clip3f( rcc->buffer_fill/(2*bits), 0.2, 1.0 ); q /= qf; bits *= qf; if( bits < rcc->buffer_rate/2 ) q *= bits*2/rcc->buffer_rate; q = X264_MAX( q0, q ); /* Check B-frame complexity, and use up any bits that would * overflow before the next P-frame. */ if( rcc->slice_type == SLICE_TYPE_P ) { int nb = rcc->bframes; double pbbits = bits; double bbits = predict_size( &rcc->pred_b_from_p, q * h->param.rc.f_pb_factor, rcc->last_satd ); double space; if( bbits > rcc->buffer_rate ) nb = 0; pbbits += nb * bbits; space = rcc->buffer_fill + (1+nb)*rcc->buffer_rate - rcc->buffer_size; if( pbbits < space ) { q *= X264_MAX( pbbits / space, bits / (0.5 * rcc->buffer_size) ); } q = X264_MAX( q0-5, q ); } } if(lmin==lmax) return lmin; else if(rcc->b_2pass) { double min2 = log(lmin); double max2 = log(lmax); q = (log(q) - min2)/(max2-min2) - 0.5; q = 1.0/(1.0 + exp(-4*q)); q = q*(max2-min2) + min2; return exp(q); } else return x264_clip3f(q, lmin, lmax);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -