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

📄 ratecontrol.c

📁 H.264 source codes
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************-*- coding: iso-8859-1 -*- * ratecontrol.c: h264 encoder library (Rate Control) ***************************************************************************** * Copyright (C) 2005 x264 project * $Id: ratecontrol.c,v 1.1 2004/06/03 19:27:08 fenrir Exp $ * * Authors: Loren Merritt <lorenm@u.washington.edu> *          Michael Niedermayer <michaelni@gmx.at> *          M錸s Rullg錼d <mru@mru.ath.cx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#define _ISOC99_SOURCE#undef NDEBUG // always check asserts, the speed effect is far too small to disable them#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include <limits.h>#include <assert.h>#include "common/common.h"#include "common/cpu.h"#include "common/macroblock.h"#include "ratecontrol.h"#if defined(SYS_FREEBSD) || defined(SYS_BEOS)#define exp2f(x) powf( 2, (x) )#endif#ifdef _MSC_VER#define exp2f(x) pow( 2, (x) )#define sqrtf sqrt#endif#ifdef WIN32 // POSIX says that rename() removes the destination, but win32 doesn't.#define rename(src,dst) (unlink(dst), rename(src,dst))#endiftypedef struct{    int pict_type;    int kept_as_ref;    float qscale;    int mv_bits;    int i_tex_bits;    int p_tex_bits;    int misc_bits;    uint64_t expected_bits;    float new_qscale;    int new_qp;    int i_count;    int p_count;    int s_count;    float blurred_complexity;} ratecontrol_entry_t;typedef struct{    double coeff;    double count;    double decay;} predictor_t;struct x264_ratecontrol_t{    /* constants */    int b_abr;    int b_2pass;    double fps;    double bitrate;    double rate_tolerance;    int nmb;                    /* number of macroblocks in a frame */    int qp_constant[5];    /* current frame */    ratecontrol_entry_t *rce;    int qp;                     /* qp for current frame */    float qpa;                  /* average of macroblocks' qp (same as qp if no adaptive quant) */    int slice_type;    int qp_force;    /* VBV stuff */    double buffer_size;    double buffer_fill;    double buffer_rate;         /* # of bits added to buffer_fill after each frame */    predictor_t pred[5];        /* predict frame size from satd */    /* ABR stuff */    int    last_satd;    double last_rceq;    double cplxr_sum;           /* sum of bits*qscale/rceq */    double expected_bits_sum;   /* sum of qscale2bits after rceq, ratefactor, and overflow */    double wanted_bits_window;  /* target bitrate * window */    double cbr_decay;    double short_term_cplxsum;    double short_term_cplxcount;    /* 2pass stuff */    FILE *p_stat_file_out;    char *psz_stat_file_tmpname;    int num_entries;            /* number of ratecontrol_entry_ts */    ratecontrol_entry_t *entry; /* FIXME: copy needed data and free this once init is done */    double last_qscale;    double last_qscale_for[5];  /* last qscale for a specific pict type, used for max_diff & ipb factor stuff  */    int last_non_b_pict_type;    double accum_p_qp;          /* for determining I-frame quant */    double accum_p_norm;    double last_accum_p_norm;    double lmin[5];             /* min qscale by frame type */    double lmax[5];    double lstep;               /* max change (multiply) in qscale per frame */    double i_cplx_sum[5];       /* estimated total texture bits in intra MBs at qscale=1 */    double p_cplx_sum[5];    double mv_bits_sum[5];    int frame_count[5];         /* number of frames of each type */};static int init_pass2(x264_t *);static float rate_estimate_qscale( x264_t *h, int pict_type );static void update_vbv( x264_t *h, int bits );int  x264_rc_analyse_slice( x264_t *h );/* Terminology: * qp = h.264's quantizer * qscale = linearized quantizer = Lagrange multiplier */static inline double qp2qscale(double qp){    return 0.85 * pow(2.0, ( qp - 12.0 ) / 6.0);}static inline double qscale2qp(double qscale){    return 12.0 + 6.0 * log(qscale/0.85) / log(2.0);}/* Texture bitrate is not quite inversely proportional to qscale, * probably due the the changing number of SKIP blocks. * MV bits level off at about qp<=12, because the lambda used * for motion estimation is constant there. */static inline double qscale2bits(ratecontrol_entry_t *rce, double qscale){    if(qscale<0.1)        qscale = 0.1;    return (rce->i_tex_bits + rce->p_tex_bits + .1) * pow( rce->qscale / qscale, 1.1 )           + rce->mv_bits * pow( X264_MAX(rce->qscale, 12) / X264_MAX(qscale, 12), 0.5 );}/* There is no analytical inverse to the above formula. */#if 0static inline double bits2qscale(ratecontrol_entry_t *rce, double bits){    if(bits<1.0)        bits = 1.0;    return (rce->i_tex_bits + rce->p_tex_bits + rce->mv_bits + .1) * rce->qscale / bits;}#endifint x264_ratecontrol_new( x264_t *h ){    x264_ratecontrol_t *rc;    int i;    x264_cpu_restore( h->param.cpu );    h->rc = rc = x264_malloc( sizeof( x264_ratecontrol_t ) );    memset(rc, 0, sizeof(*rc));    rc->b_abr = h->param.rc.b_cbr && !h->param.rc.b_stat_read;    rc->b_2pass = h->param.rc.b_cbr && h->param.rc.b_stat_read;    h->mb.b_variable_qp = 0;        /* FIXME: use integers */    if(h->param.i_fps_num > 0 && h->param.i_fps_den > 0)        rc->fps = (float) h->param.i_fps_num / h->param.i_fps_den;    else        rc->fps = 25.0;    rc->bitrate = h->param.rc.i_bitrate * 1000;    rc->rate_tolerance = h->param.rc.f_rate_tolerance;    rc->nmb = h->mb.i_mb_count;    rc->last_non_b_pict_type = -1;    rc->cbr_decay = 1.0;    if( h->param.rc.i_vbv_max_bitrate < h->param.rc.i_bitrate &&        h->param.rc.i_vbv_max_bitrate > 0)        x264_log(h, X264_LOG_ERROR, "max bitrate less than average bitrate, ignored.\n");    else if( h->param.rc.i_vbv_max_bitrate > 0 &&             h->param.rc.i_vbv_buffer_size > 0 )    {        if( h->param.rc.i_vbv_buffer_size < 10 * h->param.rc.i_vbv_max_bitrate / rc->fps ) {            h->param.rc.i_vbv_buffer_size = 10 * h->param.rc.i_vbv_max_bitrate / rc->fps;            x264_log( h, X264_LOG_ERROR, "VBV buffer size too small, using %d kbit\n",                      h->param.rc.i_vbv_buffer_size );        }        rc->buffer_rate = h->param.rc.i_vbv_max_bitrate * 1000 / rc->fps;        rc->buffer_size = h->param.rc.i_vbv_buffer_size * 1000;        rc->buffer_fill = rc->buffer_size * h->param.rc.f_vbv_buffer_init;        rc->cbr_decay = 1.0 - rc->buffer_rate / rc->buffer_size                      * 0.5 * X264_MAX(0, 1.5 - rc->buffer_rate * rc->fps / rc->bitrate);    }    else if( h->param.rc.i_vbv_max_bitrate || h->param.rc.i_vbv_buffer_size )        x264_log(h, X264_LOG_ERROR, "VBV maxrate or buffer size specified, but not both.\n");    if( rc->b_abr )    {        /* FIXME shouldn't need to arbitrarily specify a QP,         * but this is more robust than BPP measures */#define ABR_INIT_QP 24        rc->accum_p_norm = .01;        rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm;        rc->cplxr_sum = .01;        rc->wanted_bits_window = .01;    }    rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant;    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 );    rc->lstep = exp2f(h->param.rc.i_qp_step / 6.0);    rc->last_qscale = qp2qscale(26);    for( i = 0; i < 5; i++ )    {        rc->last_qscale_for[i] = qp2qscale(26);        rc->lmin[i] = qp2qscale( h->param.rc.i_qp_min );        rc->lmax[i] = qp2qscale( h->param.rc.i_qp_max );        rc->pred[i].coeff= 2.0;        rc->pred[i].count= 1.0;        rc->pred[i].decay= 0.5;    }#if 0 // FIXME: do we want to assign lmin/lmax based on ip_factor, or leave them all the same?    rc->lmin[SLICE_TYPE_I] /= fabs(h->param.f_ip_factor);    rc->lmax[SLICE_TYPE_I] /= fabs(h->param.f_ip_factor);    rc->lmin[SLICE_TYPE_B] *= fabs(h->param.f_pb_factor);    rc->lmax[SLICE_TYPE_B] *= fabs(h->param.f_pb_factor);#endif    /* Load stat file and init 2pass algo */    if( h->param.rc.b_stat_read )    {        int stats_size;        char *p, *stats_in;        FILE *stats_file;        /* read 1st pass stats */        assert( h->param.rc.psz_stat_in );        stats_file = fopen( h->param.rc.psz_stat_in, "rb");        if(!stats_file)        {            x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");            return -1;        }        // FIXME: error checking        fseek(stats_file, 0, SEEK_END);        stats_size = ftell(stats_file);        fseek(stats_file, 0, SEEK_SET);        stats_in = x264_malloc(stats_size+10);        fread(stats_in, 1, stats_size, stats_file);        fclose(stats_file);        /* find number of pics */        p = stats_in;        for(i=-1; p; i++)            p = strchr(p+1, ';');        if(i==0)        {            x264_log(h, X264_LOG_ERROR, "empty stats file\n");            return -1;        }        i += h->param.i_bframe;        rc->entry = (ratecontrol_entry_t*) x264_malloc(i*sizeof(ratecontrol_entry_t));        memset(rc->entry, 0, i*sizeof(ratecontrol_entry_t));        /* FIXME: num_entries is sometimes treated as number of frames in the video */        rc->num_entries= i;        /* init all to skipped p frames */        for(i=0; i<rc->num_entries; i++){            ratecontrol_entry_t *rce = &rc->entry[i];            rce->pict_type = SLICE_TYPE_P;            rce->qscale = rce->new_qscale = qp2qscale(20);            rce->misc_bits = rc->nmb + 10;            rce->new_qp = 0;        }        /* read stats */        p = stats_in;        for(i=0; i < rc->num_entries - h->param.i_bframe; i++){            ratecontrol_entry_t *rce;            int frame_number;            char pict_type;            int e;            char *next;            float qp;            next= strchr(p, ';');            if(next){                (*next)=0; //sscanf is unbelievably slow on looong strings                next++;            }            e = sscanf(p, " in:%d ", &frame_number);            if(frame_number < 0 || frame_number >= rc->num_entries)            {                x264_log(h, X264_LOG_ERROR, "bad frame number (%d) at stats line %d\n", frame_number, i);                return -1;            }            rce = &rc->entry[frame_number];            e += sscanf(p, " in:%*d out:%*d type:%c q:%f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d",                   &pict_type, &qp, &rce->i_tex_bits, &rce->p_tex_bits,                   &rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count, &rce->s_count);            switch(pict_type){                case 'I': rce->kept_as_ref = 1;                case 'i': rce->pict_type = SLICE_TYPE_I; break;                case 'P': rce->pict_type = SLICE_TYPE_P; break;                case 'B': rce->kept_as_ref = 1;                case 'b': rce->pict_type = SLICE_TYPE_B; break;                default:  e = -1; break;            }            if(e != 10){                x264_log(h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);                return -1;            }            rce->qscale = qp2qscale(qp);            p = next;        }        x264_free(stats_in);        if(h->param.rc.b_cbr)        {            if(init_pass2(h) < 0) return -1;        } /* else we're using constant quant, so no need to run the bitrate allocation */    }    /* Open output file */    /* If input and output files are the same, output to a temp file     * and move it to the real name only when it's complete */    if( h->param.rc.b_stat_write )

⌨️ 快捷键说明

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