⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ratecontrol.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 3 页
字号:
        rce->pict_type == B_TYPE ? (rce->f_code + rce->b_code)*0.5 : rce->f_code,
        rce->i_count/mb_num,
        rce->mc_mb_var_sum/mb_num,
        rce->mb_var_sum/mb_num,
        rce->pict_type == I_TYPE,
        rce->pict_type == P_TYPE,
        rce->pict_type == B_TYPE,
        rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type],
        a->qcompress,
/*        rcc->last_qscale_for[I_TYPE],
        rcc->last_qscale_for[P_TYPE],
        rcc->last_qscale_for[B_TYPE],
        rcc->next_non_b_qscale,*/
        rcc->i_cplx_sum[I_TYPE] / (double)rcc->frame_count[I_TYPE],
        rcc->i_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE],
        rcc->p_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE],
        rcc->p_cplx_sum[B_TYPE] / (double)rcc->frame_count[B_TYPE],
        (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type],
        0
    };

    bits= ff_parse_eval(rcc->rc_eq_eval, const_values, rce);
    if (isnan(bits)) {
        av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->avctx->rc_eq);
        return -1;
    }

    rcc->pass1_rc_eq_output_sum+= bits;
    bits*=rate_factor;
    if(bits<0.0) bits=0.0;
    bits+= 1.0; //avoid 1/0 issues

    /* user override */
    for(i=0; i<s->avctx->rc_override_count; i++){
        RcOverride *rco= s->avctx->rc_override;
        if(rco[i].start_frame > frame_num) continue;
        if(rco[i].end_frame   < frame_num) continue;

        if(rco[i].qscale)
            bits= qp2bits(rce, rco[i].qscale); //FIXME move at end to really force it?
        else
            bits*= rco[i].quality_factor;
    }

    q= bits2qp(rce, bits);

    /* I/B difference */
    if     (pict_type==I_TYPE && s->avctx->i_quant_factor<0.0)
        q= -q*s->avctx->i_quant_factor + s->avctx->i_quant_offset;
    else if(pict_type==B_TYPE && s->avctx->b_quant_factor<0.0)
        q= -q*s->avctx->b_quant_factor + s->avctx->b_quant_offset;
    if(q<1) q=1;

    return q;
}

static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, double q){
    RateControlContext *rcc= &s->rc_context;
    AVCodecContext *a= s->avctx;
    const int pict_type= rce->new_pict_type;
    const double last_p_q    = rcc->last_qscale_for[P_TYPE];
    const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type];

    if     (pict_type==I_TYPE && (a->i_quant_factor>0.0 || rcc->last_non_b_pict_type==P_TYPE))
        q= last_p_q    *FFABS(a->i_quant_factor) + a->i_quant_offset;
    else if(pict_type==B_TYPE && a->b_quant_factor>0.0)
        q= last_non_b_q*    a->b_quant_factor  + a->b_quant_offset;
    if(q<1) q=1;

    /* last qscale / qdiff stuff */
    if(rcc->last_non_b_pict_type==pict_type || pict_type!=I_TYPE){
        double last_q= rcc->last_qscale_for[pict_type];
        const int maxdiff= FF_QP2LAMBDA * a->max_qdiff;

        if     (q > last_q + maxdiff) q= last_q + maxdiff;
        else if(q < last_q - maxdiff) q= last_q - maxdiff;
    }

    rcc->last_qscale_for[pict_type]= q; //Note we cannot do that after blurring

    if(pict_type!=B_TYPE)
        rcc->last_non_b_pict_type= pict_type;

    return q;
}

/**
 * gets the qmin & qmax for pict_type
 */
static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type){
    int qmin= s->avctx->lmin;
    int qmax= s->avctx->lmax;

    assert(qmin <= qmax);

    if(pict_type==B_TYPE){
        qmin= (int)(qmin*FFABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);
        qmax= (int)(qmax*FFABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);
    }else if(pict_type==I_TYPE){
        qmin= (int)(qmin*FFABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);
        qmax= (int)(qmax*FFABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);
    }

    qmin= av_clip(qmin, 1, FF_LAMBDA_MAX);
    qmax= av_clip(qmax, 1, FF_LAMBDA_MAX);

    if(qmax<qmin) qmax= qmin;

    *qmin_ret= qmin;
    *qmax_ret= qmax;
}

static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q, int frame_num){
    RateControlContext *rcc= &s->rc_context;
    int qmin, qmax;
    double bits;
    const int pict_type= rce->new_pict_type;
    const double buffer_size= s->avctx->rc_buffer_size;
    const double fps= 1/av_q2d(s->avctx->time_base);
    const double min_rate= s->avctx->rc_min_rate / fps;
    const double max_rate= s->avctx->rc_max_rate / fps;

    get_qminmax(&qmin, &qmax, s, pict_type);

    /* modulation */
    if(s->avctx->rc_qmod_freq && frame_num%s->avctx->rc_qmod_freq==0 && pict_type==P_TYPE)
        q*= s->avctx->rc_qmod_amp;

    bits= qp2bits(rce, q);
//printf("q:%f\n", q);
    /* buffer overflow/underflow protection */
    if(buffer_size){
        double expected_size= rcc->buffer_index;
        double q_limit;

        if(min_rate){
            double d= 2*(buffer_size - expected_size)/buffer_size;
            if(d>1.0) d=1.0;
            else if(d<0.0001) d=0.0001;
            q*= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);

            q_limit= bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index)*3, 1));
            if(q > q_limit){
                if(s->avctx->debug&FF_DEBUG_RC){
                    av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
                }
                q= q_limit;
            }
        }

        if(max_rate){
            double d= 2*expected_size/buffer_size;
            if(d>1.0) d=1.0;
            else if(d<0.0001) d=0.0001;
            q/= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);

            q_limit= bits2qp(rce, FFMAX(rcc->buffer_index/3, 1));
            if(q < q_limit){
                if(s->avctx->debug&FF_DEBUG_RC){
                    av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
                }
                q= q_limit;
            }
        }
    }
//printf("q:%f max:%f min:%f size:%f index:%d bits:%f agr:%f\n", q,max_rate, min_rate, buffer_size, rcc->buffer_index, bits, s->avctx->rc_buffer_aggressivity);
    if(s->avctx->rc_qsquish==0.0 || qmin==qmax){
        if     (q<qmin) q=qmin;
        else if(q>qmax) q=qmax;
    }else{
        double min2= log(qmin);
        double max2= log(qmax);

        q= log(q);
        q= (q - min2)/(max2-min2) - 0.5;
        q*= -4.0;
        q= 1.0/(1.0 + exp(q));
        q= q*(max2-min2) + min2;

        q= exp(q);
    }

    return q;
}

//----------------------------------
// 1 Pass Code

static double predict_size(Predictor *p, double q, double var)
{
     return p->coeff*var / (q*p->count);
}

/*
static double predict_qp(Predictor *p, double size, double var)
{
//printf("coeff:%f, count:%f, var:%f, size:%f//\n", p->coeff, p->count, var, size);
     return p->coeff*var / (size*p->count);
}
*/

static void update_predictor(Predictor *p, double q, double var, double size)
{
    double new_coeff= size*q / (var + 1);
    if(var<10) return;

    p->count*= p->decay;
    p->coeff*= p->decay;
    p->count++;
    p->coeff+= new_coeff;
}

static void adaptive_quantization(MpegEncContext *s, double q){
    int i;
    const float lumi_masking= s->avctx->lumi_masking / (128.0*128.0);
    const float dark_masking= s->avctx->dark_masking / (128.0*128.0);
    const float temp_cplx_masking= s->avctx->temporal_cplx_masking;
    const float spatial_cplx_masking = s->avctx->spatial_cplx_masking;
    const float p_masking = s->avctx->p_masking;
    const float border_masking = s->avctx->border_masking;
    float bits_sum= 0.0;
    float cplx_sum= 0.0;
    float cplx_tab[s->mb_num];
    float bits_tab[s->mb_num];
    const int qmin= s->avctx->mb_lmin;
    const int qmax= s->avctx->mb_lmax;
    Picture * const pic= &s->current_picture;
    const int mb_width = s->mb_width;
    const int mb_height = s->mb_height;

    for(i=0; i<s->mb_num; i++){
        const int mb_xy= s->mb_index2xy[i];
        float temp_cplx= sqrt(pic->mc_mb_var[mb_xy]); //FIXME merge in pow()
        float spat_cplx= sqrt(pic->mb_var[mb_xy]);
        const int lumi= pic->mb_mean[mb_xy];
        float bits, cplx, factor;
        int mb_x = mb_xy % s->mb_stride;
        int mb_y = mb_xy / s->mb_stride;
        int mb_distance;
        float mb_factor = 0.0;
#if 0
        if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune
        if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune
#endif
        if(spat_cplx < 4) spat_cplx= 4; //FIXME finetune
        if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune

        if((s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_INTRA)){//FIXME hq mode
            cplx= spat_cplx;
            factor= 1.0 + p_masking;
        }else{
            cplx= temp_cplx;
            factor= pow(temp_cplx, - temp_cplx_masking);
        }
        factor*=pow(spat_cplx, - spatial_cplx_masking);

        if(lumi>127)
            factor*= (1.0 - (lumi-128)*(lumi-128)*lumi_masking);
        else
            factor*= (1.0 - (lumi-128)*(lumi-128)*dark_masking);

        if(mb_x < mb_width/5){
            mb_distance = mb_width/5 - mb_x;
            mb_factor = (float)mb_distance / (float)(mb_width/5);
        }else if(mb_x > 4*mb_width/5){
            mb_distance = mb_x - 4*mb_width/5;
            mb_factor = (float)mb_distance / (float)(mb_width/5);
        }
        if(mb_y < mb_height/5){
            mb_distance = mb_height/5 - mb_y;
            mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
        }else if(mb_y > 4*mb_height/5){
            mb_distance = mb_y - 4*mb_height/5;
            mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
        }

        factor*= 1.0 - border_masking*mb_factor;

        if(factor<0.00001) factor= 0.00001;

        bits= cplx*factor;
        cplx_sum+= cplx;
        bits_sum+= bits;
        cplx_tab[i]= cplx;
        bits_tab[i]= bits;
    }

    /* handle qmin/qmax clipping */
    if(s->flags&CODEC_FLAG_NORMALIZE_AQP){
        float factor= bits_sum/cplx_sum;
        for(i=0; i<s->mb_num; i++){
            float newq= q*cplx_tab[i]/bits_tab[i];
            newq*= factor;

            if     (newq > qmax){
                bits_sum -= bits_tab[i];
                cplx_sum -= cplx_tab[i]*q/qmax;
            }
            else if(newq < qmin){
                bits_sum -= bits_tab[i];
                cplx_sum -= cplx_tab[i]*q/qmin;
            }
        }
        if(bits_sum < 0.001) bits_sum= 0.001;
        if(cplx_sum < 0.001) cplx_sum= 0.001;
    }

    for(i=0; i<s->mb_num; i++){
        const int mb_xy= s->mb_index2xy[i];
        float newq= q*cplx_tab[i]/bits_tab[i];
        int intq;

        if(s->flags&CODEC_FLAG_NORMALIZE_AQP){
            newq*= bits_sum/cplx_sum;
        }

        intq= (int)(newq + 0.5);

        if     (intq > qmax) intq= qmax;
        else if(intq < qmin) intq= qmin;
//if(i%s->mb_width==0) printf("\n");
//printf("%2d%3d ", intq, ff_sqrt(s->mc_mb_var[i]));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -