ratectl.cc
来自「Motion JPEG编解码器源代码」· CC 代码 · 共 1,089 行 · 第 1/3 页
CC
1,089 行
/* ratectl.c, bitrate control routines (linear quantization only currently) *//* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. *//* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * *//* Modifications and enhancements (C) 2000,2001,2002,2003 Andrew Stevens *//* These modifications are 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. * */#include "config.h"#include <math.h>#include <limits.h>#include "mjpeg_types.h"#include "mjpeg_logging.h"#include "mpeg2syntaxcodes.h"#include "tables.h"#include "simd.h"#include "fastintfns.h"#include "mpeg2encoder.hh"#include "picture.hh"#include "ratectl.hh"#include "quantize.hh"/* private prototypes */double RateCtl::ScaleQuantf( int q_scale_type, double quant ){ double quantf; if ( q_scale_type ) { int iquantl, iquanth; double wl, wh; /* BUG TODO: This should interpolate the table... */ wh = quant-floor(quant); wl = 1.0 - wh; iquantl = (int) floor(quant); iquanth = iquantl+1; /* clip to legal (linear) range */ if (iquantl<1) { iquantl = 1; iquanth = 1; } if (iquantl>111) { iquantl = 112; iquanth = 112; } quantf = (double) wl * (double)non_linear_mquant_table[map_non_linear_mquant[iquantl]] + wh * (double)non_linear_mquant_table[map_non_linear_mquant[iquanth]] ; } else { /* clip mquant to legal (linear) range */ quantf = quant; if (quantf<2.0) quantf = 2; if (quantf>62.0) quantf = 62.0; } return quantf;}int RateCtl::ScaleQuant( int q_scale_type , double quant ){ int iquant; if ( q_scale_type ) { iquant = (int) floor(quant+0.5); /* clip mquant to legal (linear) range */ if (iquant<1) iquant = 1; if (iquant>112) iquant = 112; iquant = non_linear_mquant_table[map_non_linear_mquant[iquant]]; } else { /* clip mquant to legal (linear) range */ iquant = (int)floor(quant+0.5); if (iquant<2) iquant = 2; if (iquant>62) iquant = 62; iquant = (iquant/2)*2; // Must be *even* } return iquant;}double RateCtl::InvScaleQuant( int q_scale_type, int raw_code ){ int i; if( q_scale_type ) { i = 112; while( 1 < i && map_non_linear_mquant[i] != raw_code ) --i; return ((double)i); } else return ((double)raw_code);}RateCtl::RateCtl( EncoderParams &_encparams ) : encparams( _encparams ){}/***************************** * * On-the-fly rate controller. The constructor sets up the initial * control and estimator parameter values to values that experience * suggest make sense. All the important ones are dynamically * tuned anyway so these values are not too critical. * ****************************/OnTheFlyRateCtl::OnTheFlyRateCtl(EncoderParams &encparams ) : RateCtl(encparams){ buffer_variation = 0; bits_transported = 0; bits_used = 0; frame_overshoot_margin = 0; sum_avg_act = 0.0; sum_avg_var = 0.0; /* TODO: These values should are really MPEG-1/2 and material type dependent. The encoder should probably run over the first 100 frames or so look-ahead to tune theses dynamically before doing real encoding... alternative a config file should be written! */ sum_avg_quant = 0.0;}/********************* * * Initialise rate control parameters * params: reinit - Rate control is being re-initialised during the middle * of a run. Don't reset adaptive parameters. * ********************/void OnTheFlyRateCtl::InitSeq(bool reinit){ double init_quant; /* If its stills with a size we have to hit then make the guesstimates of for initial quantisation pessimistic... */ bits_transported = bits_used = 0; field_rate = 2*encparams.decode_frame_rate; fields_per_pict = encparams.fieldpic ? 1 : 2; if( encparams.still_size > 0 ) { per_pict_bits = encparams.still_size * 8; } else { per_pict_bits = static_cast<int32_t>(encparams.fieldpic ? encparams.bit_rate / field_rate : encparams.bit_rate / encparams.decode_frame_rate ); } /* Everything else already set or adaptive */ if( reinit ) return; first_gop = true; K_AVG_WINDOW[I_TYPE] = 2.0; switch( encparams.M ) { case 1 : // P K_AVG_WINDOW[P_TYPE] = 8.0; K_AVG_WINDOW[B_TYPE] = 1.0; // dummy break; case 2 : // BP K_AVG_WINDOW[P_TYPE] = 4.0; K_AVG_WINDOW[B_TYPE] = 4.0; break; default: // BBP K_AVG_WINDOW[P_TYPE] = 3.0; K_AVG_WINDOW[B_TYPE] = 7.0; break; } /* Calculate reasonable margins for variation in the decoder buffer. We assume that having less than 5 frame intervals worth buffered is cutting it fine for avoiding under-runs. The gain values represent the fraction of the under/over shoot to be recovered during one second. Gain is decreased if the buffer margin is large, gain is higher for avoiding overshoot. Currently, for a 1-frame sized margin gain is set to recover an undershoot in half a second */ if( encparams.still_size > 0 ) { undershoot_carry = 0; overshoot_gain = 1.0; } else { int buffer_safe = 3 * per_pict_bits ; undershoot_carry = (encparams.video_buffer_size - buffer_safe)/6; if( undershoot_carry < 0 ) mjpeg_error_exit1("Rate control can't cope with a video buffer smaller 4 frame intervals"); overshoot_gain = encparams.bit_rate / (encparams.video_buffer_size-buffer_safe); } bits_per_mb = (double)encparams.bit_rate / (encparams.mb_per_pict); /* Reaction paramer - i.e. quantisation feedback gain relative to bit over/undershoot. For normal frames it is fairly modest as we can compensate over multiple frames and can average out variations in image complexity. For stills we set it a higher so corrections take place more rapidly *within* a single frame. */ if( encparams.still_size > 0 ) fb_gain = (int)floor(2.0*encparams.bit_rate/encparams.decode_frame_rate); else fb_gain = (int)floor(4.0*encparams.bit_rate/encparams.decode_frame_rate); /* Set the virtual buffers for per-frame rate control feedback to values corresponding to the quantisation floor (if specified) or a "reasonable" quantisation (6.0) if not. */ init_quant = (encparams.quant_floor > 0.0 ? encparams.quant_floor : 6.0); int i; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) ratectl_vbuf[i] = static_cast<int>(init_quant * fb_gain / 62.0); next_ip_delay = 0.0; decoding_time = 0.0;}void OnTheFlyRateCtl::InitGOP( int np, int nb){ N[P_TYPE] = encparams.fieldpic ? 2*np+1 : 2*np; N[B_TYPE] = encparams.fieldpic ? 2*nb : 2*nb; N[I_TYPE] = encparams.fieldpic ? 1 : 2; fields_in_gop = N[I_TYPE] + N[P_TYPE] + N[B_TYPE]; /* At the start of a GOP before any frames have gone the actual buffer state represents a long term average. Any undershoot due to the I_frame of the previous GOP should by now have been caught up. */ gop_buffer_correction = 0; /* Each still is encoded independently so we reset rate control for each one. They're all I-frames so each stills is a GOP too. */ int i; if( first_gop || encparams.still_size > 0) { mjpeg_debug( "FIRST GOP INIT"); fast_tune = true; first_gop = false; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) { first_encountered[i] = true; pict_base_bits[i] = per_pict_bits; } } else { mjpeg_debug( "REST GOP INIT" ); double recovery_fraction = field_rate/(overshoot_gain * fields_in_gop); double recovery_gain = recovery_fraction > 1.0 ? 1.0 : overshoot_gain * recovery_fraction; int available_bits = static_cast<int>( (encparams.bit_rate+buffer_variation*recovery_gain) * fields_in_gop/field_rate); double Xsum = 0.0; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) Xsum += N[i]*Xhi[i]; for( i = FIRST_PICT_TYPE; i <= LAST_PICT_TYPE; ++i ) pict_base_bits[i] = static_cast<int32_t>(fields_per_pict*available_bits*Xhi[i]/Xsum); fast_tune = false; }}/* Step 1a: compute target bits for current picture being coded, based * on predicting from past frames */void OnTheFlyRateCtl::InitNewPict(Picture &picture){ double target_Q;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?