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

📄 ratecontrol.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Rate control for video encoders
 *
 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg 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.1 of the License, or (at your option) any later version.
 *
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file ratecontrol.c
 * Rate control for video encoders.
 */

#include "avcodec.h"
#include "dsputil.h"
#include "ratecontrol.h"
#include "mpegvideo.h"
#include "eval.h"

#undef NDEBUG // Always check asserts, the speed effect is far too small to disable them.
#include <assert.h>

#ifndef M_E
#define M_E 2.718281828
#endif

static 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){
    snprintf(s->avctx->stats_out, 256, "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 skipcount:%d hbits:%d;\n",
            s->current_picture_ptr->display_picture_number, s->current_picture_ptr->coded_picture_number, 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, s->skip_count, s->header_bits);
}

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;
}

int ff_rate_control_init(MpegEncContext *s)
{
    RateControlContext *rcc= &s->rc_context;
    int i;
    char *error = NULL;
    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
    };
    emms_c();

    rcc->rc_eq_eval = ff_parse(s->avctx->rc_eq, const_names, func1, func1_names, NULL, NULL, &error);
    if (!rcc->rc_eq_eval) {
        av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\": %s\n", s->avctx->rc_eq, error? error : "");
        return -1;
    }

    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_initial_buffer_occupancy;

    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;
        if(i<=0 || i>=INT_MAX / sizeof(RateControlEntry))
            return -1;
        rcc->entry = (RateControlEntry*)av_mallocz(i*sizeof(RateControlEntry));
        rcc->num_entries= i;

        /* init all to skipped 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 unbelievably slow on looong strings //FIXME copy / do not 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 skipcount:%d hbits:%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, &rce->skip_count, &rce->header_bits);
            if(e!=14){
                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;

        //FIXME maybe move to end
        if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) {
#ifdef CONFIG_LIBXVID
            return ff_xvid_rate_control_init(s);
#else
            av_log(s->avctx, AV_LOG_ERROR, "XviD ratecontrol requires libavcodec compiled with XviD support\n");
            return -1;
#endif
        }
    }

    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;

        if(s->avctx->qblur > 1.0){
            av_log(s->avctx, AV_LOG_ERROR, "qblur too large\n");
            return -1;
        }
        /* 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/(1/av_q2d(s->avctx->time_base)); //FIXME misbehaves a little for variable fps
            }
        }

    }

    return 0;
}

void ff_rate_control_uninit(MpegEncContext *s)
{
    RateControlContext *rcc= &s->rc_context;
    emms_c();

    ff_eval_free(rcc->rc_eq_eval);
    av_freep(&rcc->entry);

#ifdef CONFIG_LIBXVID
    if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID)
        ff_xvid_rate_control_uninit(s);
#endif
}

int ff_vbv_update(MpegEncContext *s, int frame_size){
    RateControlContext *rcc= &s->rc_context;
    const double fps= 1/av_q2d(s->avctx->time_base);
    const int 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;

//printf("%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
    if(buffer_size){
        int left;

        rcc->buffer_index-= frame_size;
        if(rcc->buffer_index < 0){
            av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n");
            rcc->buffer_index= 0;
        }

        left= buffer_size - rcc->buffer_index - 1;
        rcc->buffer_index += av_clip(left, min_rate, max_rate);

        if(rcc->buffer_index > buffer_size){
            int stuffing= ceil((rcc->buffer_index - buffer_size)/8);

            if(stuffing < 4 && s->codec_id == CODEC_ID_MPEG4)
                stuffing=4;
            rcc->buffer_index -= 8*stuffing;

            if(s->avctx->debug & FF_DEBUG_RC)
                av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing);

            return stuffing;
        }
    }
    return 0;
}

/**
 * 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;
    AVCodecContext *a= s->avctx;
    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,

⌨️ 快捷键说明

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