📄 ratecontrol.c
字号:
b1 = predict_row_size_sum( h, y, rc->qpm ); } } }}int x264_ratecontrol_qp( x264_t *h ){ return h->rc->qpm;}/* In 2pass, force the same frame types as in the 1st pass */int x264_ratecontrol_slice_type( x264_t *h, int frame_num ){ x264_ratecontrol_t *rc = h->rc; if( h->param.rc.b_stat_read ) { if( frame_num >= rc->num_entries ) { /* We could try to initialize everything required for ABR and * adaptive B-frames, but that would be complicated. * So just calculate the average QP used so far. */ h->param.rc.i_qp_constant = (h->stat.i_slice_count[SLICE_TYPE_P] == 0) ? 24 : 1 + h->stat.i_slice_qp[SLICE_TYPE_P] / h->stat.i_slice_count[SLICE_TYPE_P]; rc->qp_constant[SLICE_TYPE_P] = x264_clip3( h->param.rc.i_qp_constant, 0, 51 ); rc->qp_constant[SLICE_TYPE_I] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) / fabs( h->param.rc.f_ip_factor )) + 0.5 ), 0, 51 ); rc->qp_constant[SLICE_TYPE_B] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, 51 ); x264_log(h, X264_LOG_ERROR, "2nd pass has more frames than 1st pass (%d)\n", rc->num_entries); x264_log(h, X264_LOG_ERROR, "continuing anyway, at constant QP=%d\n", h->param.rc.i_qp_constant); if( h->param.b_bframe_adaptive ) x264_log(h, X264_LOG_ERROR, "disabling adaptive B-frames\n"); rc->b_abr = 0; rc->b_2pass = 0; h->param.rc.i_rc_method = X264_RC_CQP; h->param.rc.b_stat_read = 0; h->param.b_bframe_adaptive = 0; if( h->param.i_bframe > 1 ) h->param.i_bframe = 1; return X264_TYPE_P; } switch( rc->entry[frame_num].pict_type ) { case SLICE_TYPE_I: return rc->entry[frame_num].kept_as_ref ? X264_TYPE_IDR : X264_TYPE_I; case SLICE_TYPE_B: return rc->entry[frame_num].kept_as_ref ? X264_TYPE_BREF : X264_TYPE_B; case SLICE_TYPE_P: default: return X264_TYPE_P; } } 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 ) rc->qpa /= h->mb.i_mb_count; else rc->qpa = rc->qp; h->fdec->f_qp_avg = rc->qpa; if( h->param.rc.b_stat_write ) { char c_type = h->sh.i_type==SLICE_TYPE_I ? (h->fenc->i_poc==0 ? 'I' : 'i') : h->sh.i_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( h->sh.i_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; if( h->param.i_threads == 1 ) accum_p_qp_update( h, 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( h->sh.i_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[h->i_ref1-1]->i_satd, rc->bframe_bits / rc->bframes ); rc->bframe_bits = 0; } } } update_vbv( h, bits );}/**************************************************************************** * 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; x264_zone_t *zone = get_zone( h, frame_num ); 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 if(!isfinite(q) || 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; } if( zone ) { if( zone->b_force_qp ) q = qp2qscale(zone->i_qp); else q /= zone->f_bitrate_factor; } 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 = 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;}// update VBV after encoding a framestatic void update_vbv( x264_t *h, int bits ){ x264_ratecontrol_t *rcc = h->rc; x264_ratecontrol_t *rct = h->thread[0]->rc; if( rcc->last_satd >= h->mb.i_mb_count ) update_predictor( &rct->pred[h->sh.i_type], qp2qscale(rcc->qpa), rcc->last_satd, bits ); if( !rcc->b_vbv ) return; rct->buffer_fill_final += rct->buffer_rate - bits; if( rct->buffer_fill_final < 0 && !rct->b_2pass ) x264_log( h, X264_LOG_WARNING, "VBV underflow (%.0f bits)\n", rct->buffer_fill_final ); rct->buffer_fill_final = x264_clip3f( rct->buffer_fill_final, 0, rct->buffer_size );}// provisionally update VBV according to the planned size of all frames currently in progressstatic void update_vbv_plan( x264_t *h ){ x264_ratecontrol_t *rcc = h->rc; rcc->buffer_fill = h->thread[0]->rc->buffer_fill_final; if( h->param.i_threads > 1 ) { int j = h->rc - h->thread[0]->rc; int i; for( i=1; i<h->param.i_threads; i++ ) { x264_t *t = h->thread[ (j+i)%h->param.i_threads ]; double bits = t->rc->frame_size_planned; if( !t->b_thread_active ) continue; rcc->buffer_fill += rcc->buffer_rate - bits; 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[h->sh.i_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( h->sh.i_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 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -