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

📄 ratecontrol.c

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Rate control for video encoders * * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//** * @file ratecontrol.c * Rate control for video encoders. */ #include "avcodec.h"#include "dsputil.h"#include "mpegvideo.h"#undef NDEBUG // allways check asserts, the speed effect is far too small to disable them#include <assert.h>#ifndef M_E#define M_E 2.718281828#endifstatic int init_pass2(MpegEncContext *s);static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num);void ff_write_pass1_stats(MpegEncContext *s){    sprintf(s->avctx->stats_out, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d;\n",            s->picture_number, s->input_picture_number - s->max_b_frames, s->pict_type,             s->current_picture.quality, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits,             s->f_code, s->b_code, s->current_picture.mc_mb_var_sum, s->current_picture.mb_var_sum, s->i_count);}int ff_rate_control_init(MpegEncContext *s){    RateControlContext *rcc= &s->rc_context;    int i;    emms_c();    for(i=0; i<5; i++){        rcc->pred[i].coeff= FF_QP2LAMBDA * 7.0;        rcc->pred[i].count= 1.0;            rcc->pred[i].decay= 0.4;        rcc->i_cplx_sum [i]=        rcc->p_cplx_sum [i]=        rcc->mv_bits_sum[i]=        rcc->qscale_sum [i]=        rcc->frame_count[i]= 1; // 1 is better cuz of 1/0 and such        rcc->last_qscale_for[i]=FF_QP2LAMBDA * 5;    }    rcc->buffer_index= s->avctx->rc_buffer_size/2;    if(s->flags&CODEC_FLAG_PASS2){        int i;        char *p;        /* find number of pics */        p= s->avctx->stats_in;        for(i=-1; p; i++){            p= strchr(p+1, ';');        }        i+= s->max_b_frames;        rcc->entry = (RateControlEntry*)av_mallocz(i*sizeof(RateControlEntry));        rcc->num_entries= i;                /* init all to skiped p frames (with b frames we might have a not encoded frame at the end FIXME) */        for(i=0; i<rcc->num_entries; i++){            RateControlEntry *rce= &rcc->entry[i];            rce->pict_type= rce->new_pict_type=P_TYPE;            rce->qscale= rce->new_qscale=FF_QP2LAMBDA * 2;            rce->misc_bits= s->mb_num + 10;            rce->mb_var_sum= s->mb_num*100;        }                        /* read stats */        p= s->avctx->stats_in;        for(i=0; i<rcc->num_entries - s->max_b_frames; i++){            RateControlEntry *rce;            int picture_number;            int e;            char *next;            next= strchr(p, ';');            if(next){                (*next)=0; //sscanf in unbelieavle slow on looong strings //FIXME copy / dont write                next++;            }            e= sscanf(p, " in:%d ", &picture_number);            assert(picture_number >= 0);            assert(picture_number < rcc->num_entries);            rce= &rcc->entry[picture_number];            e+=sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d",                   &rce->pict_type, &rce->qscale, &rce->i_tex_bits, &rce->p_tex_bits, &rce->mv_bits, &rce->misc_bits,                    &rce->f_code, &rce->b_code, &rce->mc_mb_var_sum, &rce->mb_var_sum, &rce->i_count);            if(e!=12){                av_log(s->avctx, AV_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);                return -1;            }            p= next;        }                if(init_pass2(s) < 0) return -1;    }         if(!(s->flags&CODEC_FLAG_PASS2)){        rcc->short_term_qsum=0.001;        rcc->short_term_qcount=0.001;            rcc->pass1_rc_eq_output_sum= 0.001;        rcc->pass1_wanted_bits=0.001;                /* init stuff with the user specified complexity */        if(s->avctx->rc_initial_cplx){            for(i=0; i<60*30; i++){                double bits= s->avctx->rc_initial_cplx * (i/10000.0 + 1.0)*s->mb_num;                RateControlEntry rce;                double q;                                if     (i%((s->gop_size+3)/4)==0) rce.pict_type= I_TYPE;                else if(i%(s->max_b_frames+1))    rce.pict_type= B_TYPE;                else                              rce.pict_type= P_TYPE;                rce.new_pict_type= rce.pict_type;                rce.mc_mb_var_sum= bits*s->mb_num/100000;                rce.mb_var_sum   = s->mb_num;                rce.qscale   = FF_QP2LAMBDA * 2;                rce.f_code   = 2;                rce.b_code   = 1;                rce.misc_bits= 1;                if(s->pict_type== I_TYPE){                    rce.i_count   = s->mb_num;                    rce.i_tex_bits= bits;                    rce.p_tex_bits= 0;                    rce.mv_bits= 0;                }else{                    rce.i_count   = 0; //FIXME we do know this approx                    rce.i_tex_bits= 0;                    rce.p_tex_bits= bits*0.9;                    rce.mv_bits= bits*0.1;                }                rcc->i_cplx_sum [rce.pict_type] += rce.i_tex_bits*rce.qscale;                rcc->p_cplx_sum [rce.pict_type] += rce.p_tex_bits*rce.qscale;                rcc->mv_bits_sum[rce.pict_type] += rce.mv_bits;                rcc->frame_count[rce.pict_type] ++;                bits= rce.i_tex_bits + rce.p_tex_bits;                q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i);                rcc->pass1_wanted_bits+= s->bit_rate/(s->avctx->frame_rate / (double)s->avctx->frame_rate_base);            }        }    }        return 0;}void ff_rate_control_uninit(MpegEncContext *s){    RateControlContext *rcc= &s->rc_context;    emms_c();    av_freep(&rcc->entry);}static inline double qp2bits(RateControlEntry *rce, double qp){    if(qp<=0.0){        av_log(NULL, AV_LOG_ERROR, "qp<=0.0\n");    }    return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ qp;}static inline double bits2qp(RateControlEntry *rce, double bits){    if(bits<0.9){        av_log(NULL, AV_LOG_ERROR, "bits<0.9\n");    }    return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ bits;}    static void update_rc_buffer(MpegEncContext *s, int frame_size){    RateControlContext *rcc= &s->rc_context;    const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;    const double buffer_size= s->avctx->rc_buffer_size;    const double min_rate= s->avctx->rc_min_rate/fps;    const double max_rate= s->avctx->rc_max_rate/fps;    if(buffer_size){        rcc->buffer_index-= frame_size;        if(rcc->buffer_index < buffer_size/2 /*FIXME /2 */ || min_rate==0){            rcc->buffer_index+= max_rate;            if(rcc->buffer_index >= buffer_size)                rcc->buffer_index= buffer_size-1;        }else{            rcc->buffer_index+= min_rate;        }                if(rcc->buffer_index < 0)            av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");        if(rcc->buffer_index >= s->avctx->rc_buffer_size)            av_log(s->avctx, AV_LOG_ERROR, "rc buffer overflow\n");    }}/** * modifies the bitrate curve from pass1 for one frame */static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num){    RateControlContext *rcc= &s->rc_context;    double q, bits;    const int pict_type= rce->new_pict_type;    const double mb_num= s->mb_num;      int i;    double const_values[]={        M_PI,        M_E,        rce->i_tex_bits*rce->qscale,        rce->p_tex_bits*rce->qscale,        (rce->i_tex_bits + rce->p_tex_bits)*(double)rce->qscale,        rce->mv_bits/mb_num,        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],        s->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    };    static const char *const_names[]={        "PI",        "E",        "iTex",        "pTex",        "tex",        "mv",        "fCode",        "iCount",        "mcVar",        "var",        "isI",        "isP",        "isB",        "avgQP",        "qComp",/*        "lastIQP",        "lastPQP",        "lastBQP",        "nextNonBQP",*/        "avgIITex",        "avgPITex",        "avgPPTex",        "avgBPTex",        "avgTex",        NULL    };    static double (*func1[])(void *, double)={        (void *)bits2qp,        (void *)qp2bits,        NULL    };    static const char *func1_names[]={        "bits2qp",        "qp2bits",        NULL    };    bits= ff_eval(s->avctx->rc_eq, const_values, const_names, func1, func1_names, NULL, NULL, rce);        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;            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    *ABS(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;    /* 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 cant 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*ABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);        qmax= (int)(qmax*ABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);    }else if(pict_type==I_TYPE){        qmin= (int)(qmin*ABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);        qmax= (int)(qmax*ABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);    }    qmin= clip(qmin, 1, FF_LAMBDA_MAX);    qmax= 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 min_rate= s->avctx->rc_min_rate;    const double max_rate= s->avctx->rc_max_rate;        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;        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= FFMIN(q, bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index)*2, 1)));        }        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);

⌨️ 快捷键说明

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