plugin_2pass2.c
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C语言 代码 · 共 1,857 行 · 第 1/4 页
C
1,857 行
/******************************************************************************
*
* XviD Bit Rate Controller Library
* - VBR 2 pass bitrate controller implementation -
*
* Copyright (C) 2002 Foxer <email?>
* 2002 Dirk Knop <dknop@gwdg.de>
* 2002-2003 Edouard Gomez <ed.gomez@free.fr>
* 2003 Pete Ross <pross@xvid.org>
*
* This curve treatment algorithm is the one originally implemented by Foxer
* and tuned by Dirk Knop for the XviD vfw frontend.
*
* 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-1307 USA
*
* $Id: plugin_2pass2.c,v 1.7 2005/03/27 03:59:42 suxen_drol Exp $
*
*****************************************************************************/
#define BQUANT_PRESCALE
#undef COMPENSATE_FORMULA
/* forces second pass not to be bigger than first */
#undef PASS_SMALLER
/* automatically alters overflow controls (strength and improvement/degradation)
to fight most common problems without user's knowladge */
#define SMART_OVERFLOW_SETTING
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include "../xvid.h"
#include "../image/image.h"
/*****************************************************************************
* Some default settings
****************************************************************************/
#define DEFAULT_KEYFRAME_BOOST 0
#define DEFAULT_OVERFLOW_CONTROL_STRENGTH 10
#define DEFAULT_CURVE_COMPRESSION_HIGH 0
#define DEFAULT_CURVE_COMPRESSION_LOW 0
#define DEFAULT_MAX_OVERFLOW_IMPROVEMENT 10
#define DEFAULT_MAX_OVERFLOW_DEGRADATION 10
/* Keyframe settings */
#define DEFAULT_KFREDUCTION 20
#define DEFAULT_KFTHRESHOLD 1
/*****************************************************************************
* Some default constants (can be tuned)
****************************************************************************/
/* Specify the invariant part of the headers bits (header+MV)
* as hlength/cst */
#define INVARIANT_HEADER_PART_IVOP 1 /* factor 1.0f */
#define INVARIANT_HEADER_PART_PVOP 2 /* factor 0.5f */
#define INVARIANT_HEADER_PART_BVOP 8 /* factor 0.125f */
/*****************************************************************************
* Structures
****************************************************************************/
/* Statistics */
typedef struct {
int type; /* first pass type */
int quant; /* first pass quant */
int blks[3]; /* k,m,y blks */
int length; /* first pass length */
int invariant; /* what we assume as being invariant between the two passes, it's a sub part of header + MV bits */
int scaled_length; /* scaled length */
int desired_length; /* desired length; calculated during encoding */
int error;
int zone_mode; /* XVID_ZONE_xxx */
double weight;
} twopass_stat_t;
/* Context struct */
typedef struct
{
xvid_plugin_2pass2_t param;
/*----------------------------------
* constant statistical data
*--------------------------------*/
/* Number of frames of the sequence */
int num_frames;
/* Number of Intra frames of the sequence */
int num_keyframes;
/* Target filesize to reach */
uint64_t target;
/* Count of each frame types */
int count[3];
/* Total length of each frame types (1st pass) */
uint64_t tot_length[3];
uint64_t tot_invariant[3];
/* Average length of each frame types (used first for 1st pass data and
* then for scaled averages */
double avg_length[3];
/* Minimum frame length allowed for each frame type */
int min_length[3];
/* Total bytes per frame type once the curve has been scaled
* NB: advanced parameters do not change this value. This field
* represents the total scaled w/o any advanced settings */
uint64_t tot_scaled_length[3];
/* Maximum observed frame size observed during the first pass, the RC
* will try tp force all frame sizes in the second pass to be under that
* limit */
int max_length;
/*----------------------------------
* Zones statistical data
*--------------------------------*/
/* Total length used by XVID_ZONE_QUANT zones */
uint64_t tot_quant;
uint64_t tot_quant_invariant;
/* Holds the total amount of frame bytes, zone weighted (only scalable
* part of frame bytes) */
uint64_t tot_weighted;
/*----------------------------------
* Advanced settings helper ratios
*--------------------------------*/
/* This the ratio that has to be applied to all p/b frames in order
* to reserve/retrieve bits for/from keyframe boosting and consecutive
* keyframe penalty */
double pb_iboost_tax_ratio;
/* This the ratio to apply to all b/p frames in order to respect the
* assymetric curve compression while respecting a target filesize
* NB: The assymetric delta gain has to be computed before this ratio
* is applied, and then the delta is added to the scaled size */
double assymetric_tax_ratio;
/*----------------------------------
* Data from the stats file kept
* into RAM for easy access
*--------------------------------*/
/* Array of keyframe locations
* eg: rc->keyframe_locations[100] returns the frame number of the 100th
* keyframe */
int *keyframe_locations;
/* Index of the last keyframe used in the keyframe_location */
int KF_idx;
/* Array of all 1st pass data file -- see the twopass_stat_t structure
* definition for more details */
twopass_stat_t * stats;
/*----------------------------------
* Hysteresis helpers
*--------------------------------*/
/* This field holds the int2float conversion errors of each quant per
* frame type, this allow the RC to keep track of rouding error and thus
* increase or decrease the chosen quant according to this residue */
double quant_error[3][32];
/* This fields stores the count of each quant usage per frame type
* No real role but for debugging */
int quant_count[3][32];
/* Last valid quantizer used per frame type, it allows quantizer
* increament/decreament limitation in order to avoid big image quality
* "jumps" */
int last_quant[3];
/*----------------------------------
* Overflow control
*--------------------------------*/
/* Current overflow that has to be distributed to p/b frames */
double overflow;
/* Total overflow for keyframes -- not distributed directly */
double KFoverflow;
/* Amount of keyframe overflow to introduce to the global p/b frame
* overflow counter at each encoded frame */
double KFoverflow_partial;
/* Unknown ???
* ToDo: description */
double fq_error;
int min_quant; /* internal minimal quant, prevents wrong quants from being used */
/*----------------------------------
* Debug
*--------------------------------*/
double desired_total;
double real_total;
} rc_2pass2_t;
/*****************************************************************************
* Sub plugin functions prototypes
****************************************************************************/
static int rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t ** handle);
static int rc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data);
static int rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data);
static int rc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy);
/*****************************************************************************
* Plugin definition
****************************************************************************/
int
xvid_plugin_2pass2(void * handle, int opt, void * param1, void * param2)
{
switch(opt) {
case XVID_PLG_INFO :
case XVID_PLG_FRAME :
return 0;
case XVID_PLG_CREATE :
return rc_2pass2_create((xvid_plg_create_t*)param1, param2);
case XVID_PLG_DESTROY :
return rc_2pass2_destroy((rc_2pass2_t*)handle, (xvid_plg_destroy_t*)param1);
case XVID_PLG_BEFORE :
return rc_2pass2_before((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1);
case XVID_PLG_AFTER :
return rc_2pass2_after((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1);
}
return XVID_ERR_FAIL;
}
/*****************************************************************************
* Sub plugin functions definitions
****************************************************************************/
/* First a few local helping function prototypes */
static int statsfile_count_frames(rc_2pass2_t * rc, char * filename);
static int statsfile_load(rc_2pass2_t *rc, char * filename);
static void zone_process(rc_2pass2_t *rc, const xvid_plg_create_t * create);
static void first_pass_stats_prepare_data(rc_2pass2_t * rc);
static void first_pass_scale_curve_internal(rc_2pass2_t *rc);
static void scaled_curve_apply_advanced_parameters(rc_2pass2_t * rc);
static int check_curve_for_vbv_compliancy(rc_2pass2_t * rc, const float fps);
static int scale_curve_for_vbv_compliancy(rc_2pass2_t * rc, const float fps);
#if 0
static void stats_print(rc_2pass2_t * rc);
#endif
/*----------------------------------------------------------------------------
*--------------------------------------------------------------------------*/
static int
rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t **handle)
{
xvid_plugin_2pass2_t * param = (xvid_plugin_2pass2_t *)create->param;
rc_2pass2_t * rc;
int i;
rc = malloc(sizeof(rc_2pass2_t));
if (rc == NULL)
return XVID_ERR_MEMORY;
/* v1.0.x */
rc->param.version = param->version;
rc->param.bitrate = param->bitrate;
rc->param.filename = param->filename;
rc->param.keyframe_boost = param->keyframe_boost;
rc->param.curve_compression_high = param->curve_compression_high;
rc->param.curve_compression_low = param->curve_compression_low;
rc->param.overflow_control_strength = param->overflow_control_strength;
rc->param.max_overflow_improvement = param->max_overflow_improvement;
rc->param.max_overflow_degradation = param->max_overflow_degradation;
rc->param.kfreduction = param->kfreduction;
rc->param.kfthreshold = param->kfthreshold;
rc->param.container_frame_overhead = param->container_frame_overhead;
if (XVID_VERSION_MINOR(param->version) >= 1) {
rc->param.vbv_size = param->vbv_size;
rc->param.vbv_initial = param->vbv_initial;
rc->param.vbv_maxrate = param->vbv_maxrate;
rc->param.vbv_peakrate = param->vbv_peakrate;
}else{
rc->param.vbv_size =
rc->param.vbv_initial =
rc->param.vbv_maxrate =
rc->param.vbv_peakrate = 0;
}
/* Initialize all defaults */
#define _INIT(a, b) if((a) <= 0) (a) = (b)
/* Let's set our defaults if needed */
_INIT(rc->param.keyframe_boost, DEFAULT_KEYFRAME_BOOST);
_INIT(rc->param.overflow_control_strength, DEFAULT_OVERFLOW_CONTROL_STRENGTH);
_INIT(rc->param.curve_compression_high, DEFAULT_CURVE_COMPRESSION_HIGH);
_INIT(rc->param.curve_compression_low, DEFAULT_CURVE_COMPRESSION_LOW);
_INIT(rc->param.max_overflow_improvement, DEFAULT_MAX_OVERFLOW_IMPROVEMENT);
_INIT(rc->param.max_overflow_degradation, DEFAULT_MAX_OVERFLOW_DEGRADATION);
/* Keyframe settings */
_INIT(rc->param.kfreduction, DEFAULT_KFREDUCTION);
_INIT(rc->param.kfthreshold, DEFAULT_KFTHRESHOLD);
#undef _INIT
/* Initialize some stuff to zero */
for(i=0; i<3; i++) {
int j;
for (j=0; j<32; j++) {
rc->quant_error[i][j] = 0;
rc->quant_count[i][j] = 0;
}
}
for (i=0; i<3; i++) rc->last_quant[i] = 0;
rc->fq_error = 0;
rc->min_quant = 1;
/* Count frames (and intra frames) in the stats file, store the result into
* the rc structure */
if (statsfile_count_frames(rc, param->filename) == -1) {
DPRINTF(XVID_DEBUG_RC,"[xvid rc] -- ERROR: fopen %s failed\n", param->filename);
free(rc);
return(XVID_ERR_FAIL);
}
/* Allocate the stats' memory */
if ((rc->stats = malloc(rc->num_frames * sizeof(twopass_stat_t))) == NULL) {
free(rc);
return(XVID_ERR_MEMORY);
}
/* Allocate keyframes location's memory
* PS: see comment in pre_process0 for the +1 location requirement */
rc->keyframe_locations = malloc((rc->num_keyframes + 1) * sizeof(int));
if (rc->keyframe_locations == NULL) {
free(rc->stats);
free(rc);
return(XVID_ERR_MEMORY);
}
/* Load the first pass stats */
if (statsfile_load(rc, param->filename) == -1) {
DPRINTF(XVID_DEBUG_RC,"[xvid rc] -- ERROR: fopen %s failed\n", param->filename);
free(rc->keyframe_locations);
free(rc->stats);
free(rc);
return XVID_ERR_FAIL;
}
/* Compute the target filesize */
if (rc->param.bitrate<0) {
/* if negative, bitrate equals the target (in kbytes) */
rc->target = ((uint64_t)(-rc->param.bitrate)) * 1024;
} else if (rc->num_frames < create->fbase/create->fincr) {
/* Source sequence is less than 1s long, we do as if it was 1s long */
rc->target = rc->param.bitrate / 8;
} else {
/* Target filesize = bitrate/8 * numframes / framerate */
rc->target =
((uint64_t)rc->param.bitrate * (uint64_t)rc->num_frames * \
(uint64_t)create->fincr) / \
((uint64_t)create->fbase * 8);
}
DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Frame rate: %d/%d (%ffps)\n",
create->fbase, create->fincr,
(double)create->fbase/(double)create->fincr);
DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Number of frames: %d\n", rc->num_frames);
if(rc->param.bitrate>=0)
DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Target bitrate: %ld\n", rc->param.bitrate);
DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Target filesize: %lld\n", rc->target);
/* Compensate the average frame overhead caused by the container */
rc->target -= rc->num_frames*rc->param.container_frame_overhead;
DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Container Frame overhead: %d\n", rc->param.container_frame_overhead);
if(rc->param.container_frame_overhead)
DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- New target filesize after container compensation: %lld\n", rc->target);
/* When bitrate is not given it means it has been scaled by an external
* application */
if (rc->param.bitrate) {
/* Apply zone settings
* - set rc->tot_quant which represents the total num of bytes spent in
* fixed quant zones
* - set rc->tot_weighted which represents the total amount of bytes
* spent in normal or weighted zones in first pass (normal zones can
* be considered weight=1)
* - set rc->tot_quant_invariant which represents the total num of bytes
* spent in fixed quant zones for headers */
zone_process(rc, create);
} else {
/* External scaling -- zones are ignored */
for (i=0;i<rc->num_frames;i++) {
rc->stats[i].zone_mode = XVID_ZONE_WEIGHT;
rc->stats[i].weight = 1.0;
}
rc->tot_quant = 0;
}
/* Gathers some information about first pass stats:
* - finds the minimum frame length for each frame type during 1st pass.
* rc->min_size[]
* - determines the maximum frame length observed (no frame type distinction).
* rc->max_size
* - count how many times each frame type has been used.
* rc->count[]
* - total bytes used per frame type
* rc->tot_length[]
* - total bytes considered invariant between the 2 passes
* - store keyframe location
* rc->keyframe_locations[]
*/
first_pass_stats_prepare_data(rc);
/* If we have a user bitrate, it means it's an internal curve scaling */
if (rc->param.bitrate) {
/* Perform internal curve scaling */
first_pass_scale_curve_internal(rc);
}
/* Apply advanced curve options, and compute some parameters in order to
* shape the curve in the BEFORE/AFTER pair of functions */
scaled_curve_apply_advanced_parameters(rc);
/* Check curve for VBV compliancy and rescale if necessary */
#ifdef VBV_FORCE
if (rc->param.vbv_size==0) {
rc->param.vbv_size = 3145728;
rc->param.vbv_initial = 2359296;
rc->param.vbv_maxrate = 4854000;
rc->param.vbv_peakrate = 8000000;
}
#endif
/* vbv_size==0 switches VBV check off */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?