/* ***** BEGIN LICENSE BLOCK ***** * * $Id: rate_control.cpp,v 1.5 2007/03/28 11:05:50 tjdwave Exp $ $Name: Dirac_0_7_0 $ * * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is BBC Research and Development code. * * The Initial Developer of the Original Code is the British Broadcasting * Corporation. * Portions created by the Initial Developer are Copyright (C) 2004. * All Rights Reserved. * * Contributor(s): Myo Tun (Original Author, myo.tun@brunel.ac.uk) * Jonathan Loo (Jonathan.Loo@brunel.ac.uk) * School of Engineering and Design, Brunel University, UK * Thomas Davies (bugfixes to improve stability and a major refactor to introduce a buffer model) * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser * Public License Version 2.1 (the "LGPL"), in which case the provisions of * the GPL or the LGPL are applicable instead of those above. If you wish to * allow use of your version of this file only under the terms of the either * the GPL or LGPL and not to allow others to use your version of this file * under the MPL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by the GPL * or LGPL. If you do not delete the provisions above, a recipient may use * your version of this file under the terms of any one of the MPL, the GPL * or the LGPL. * ***** END LICENSE BLOCK ***** */ //////////////Rate Control Algorithm////////////////// /* The algorithm controls the bitrate by adaptively changing the Quality Factor, QF of each frame before encoding by the m_fcoder.Compress( , , , ) function in CompressNextFrame() (seq_compress.cpp). The first sub-group which is I, L1, L2, L2 frames are encoded by using the initial QF which is set to 7. The corresponding bitrate R is then calculated. Adaption for the next subgroup is carried out by determining a model parameter K, whose relationship to QF and bit rate is: QF = 10-5/2log(K/R^(-2)) K is determined from the first subgroup data (QF and rate), and used to calculate a new QF from the target rates for the next subgroup. The same procedure applies for the calculation of the QF for the remaining sub-groups until it reaches to the end of a GOP. For the next GOP, the initial QF of the first sub-group is the average value of the QF of the first sub-group and last sub-group from the previous GOP. The calculation of the QF of each and every sub-group is carried out in the CalcNextQualFactor( , ) function at the rate_control.cpp. The target bitrate is varied according to a decoder buffer model, consisting of the average bitrate over a GOP plus an adjustment to steer the buffer towards a target occupancy. A target bit rate corresponding to the different sub-groups still neeeds to be calculated from this overall target. In order to do this, the modified version of test model version 5, TM5 bit allocation procedure is employed and target bit rates for each sub-group are calculated by using the allocated bits to each frame types. The modified version of TM5 bit allocation procedure is implemented in Allocate ( , ) function at the rate_control.cpp. */ #include #include using namespace dirac; //Default constructor FrameComplexity::FrameComplexity(): m_XI(169784), m_XL1(36016), m_XL2(4824) {} //Default constructor RateController::RateController(int trate, SourceParams& srcp, EncoderParams& encp): m_qf (7.0), m_I_qf (7.0), m_target_rate(trate), m_buffer_size(4000*trate),// for the moment, set buffer size to 4*bitrate m_buffer_bits((m_buffer_size*3)/4),// initial occupancy of 75% m_encparams(encp), m_fcount(encp.L1Sep() ), m_intra_only(false), m_L2_complexity_sum(0) { SetFrameDistribution(); CalcTotalBits(srcp); } void RateController::SetFrameDistribution() { m_num_L1frame = m_encparams.NumL1(); if (m_num_L1frame > 0) m_num_Iframe = 1; else if (m_num_L1frame == 0) { m_num_Iframe = 10; m_intra_only = true; } else m_num_Iframe = 0; m_num_L2frame = m_encparams.GOPLength() - m_num_Iframe - m_num_L1frame; } void RateController::CalcTotalBits(const SourceParams& sourceparams) { const Rational& frame_rate = sourceparams.FrameRate(); double f_rate = frame_rate.m_num/frame_rate.m_denom; int GOP_length = m_encparams.GOPLength(); m_GOP_duration = GOP_length/f_rate; m_total_GOP_bits = int(m_GOP_duration*1000.0)*m_target_rate; //Unit in bits m_current_GOP_bits = m_total_GOP_bits; m_picture_bits = m_total_GOP_bits/GOP_length; if (m_encparams.Verbose()) { std::cout<<"\nRate Control Encoding with target bit rate = "; std::cout<1 ) { m_frame_complexity.SetL2Complexity(m_L2_complexity_sum/ (m_encparams.L1Sep()-1)); } Allocate(); /* We work out what this means for the quality factor and set it*/ // Get the target number of bits for the coming subgroup // calculated from allocations double trate = TargetSubgroupRate(); // Get the projected rate for the coming subgroup, calculated // from measured values (complexities) double prate = ProjectedSubgroupRate(); // Determine K value double K = std::pow(prate, 2)*std::pow(10.0, ((double)2/5*(10-m_qf)))/16; // Determine a new QF m_qf = 10 - (double)5/2*log10(16*K/std::pow(trate, 2)); m_qf = ReviewQualityFactor( m_qf , num_bits ); m_encparams.SetQf(m_qf); /* Resetting */ // Reset the frame counter m_fcount = m_encparams.L1Sep(); // Reset the count of L2 bits m_L2_complexity_sum = 0; } } else { // We're doing intra-only coding // TBD } } void RateController::UpdateBuffer( const int num_bits ) { m_buffer_bits -= num_bits; m_buffer_bits += m_picture_bits; /* if (m_encparams.Verbose()) { std::cout<m_buffer_size) { if (m_encparams.Verbose()) { std::cout<m_total_GOP_bits/2) { // The frame is too big, so reset to a smaller quality factor return ClipQualityFactor(qfac-2); } else { // Keep the quality factor in a sensible range return ClipQualityFactor( qfac ); } } float RateController::ClipQualityFactor( const float qfac ) { // Keep the quality factor in a sensible range return std::min( std::max( qfac, 2.0f), 15.0f); } void RateController::CalcNextIntraQualFactor() { m_I_qf = (m_I_qf + m_qf)/2.0; m_I_qf = ClipQualityFactor( m_I_qf ); m_encparams.SetQf(m_I_qf); }