📄 plugin_2pass2.c
字号:
/****************************************************************************** * * 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 ****************************************************************************/intxvid_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 0static void stats_print(rc_2pass2_t * rc);#endif/*---------------------------------------------------------------------------- *--------------------------------------------------------------------------*/static intrc_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -