diff options
Diffstat (limited to 'src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp')
-rw-r--r-- | src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp | 280 |
1 files changed, 138 insertions, 142 deletions
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp index da4b4bab8..bd5b62346 100644 --- a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp @@ -89,30 +89,30 @@ FrameComplexity::FrameComplexity(): //Default constructor RateController::RateController(int trate, SourceParams& srcp, EncoderParams& encp): - m_qf(encp.Qf()), - m_I_qf(encp.Qf()), + m_qf (encp.Qf()), + m_I_qf (encp.Qf()), m_I_qf_long_term(encp.Qf()), m_target_rate(trate), - m_buffer_size(5000 * trate), // for the moment, set buffer size to 5 seconds - m_buffer_bits((m_buffer_size * 9) / 10), // initial occupancy of 90% + m_buffer_size(5000*trate),// for the moment, set buffer size to 5 seconds + m_buffer_bits((m_buffer_size*9)/10),// initial occupancy of 90% m_encparams(encp), - m_fcount(encp.L1Sep()), + m_fcount(encp.L1Sep() ), m_intra_only(false), m_L2_complexity_sum(0) { SetFrameDistribution(); CalcTotalBits(srcp); - if(m_intra_only) + if (m_intra_only) m_Iframe_bits = m_total_GOP_bits; else { - m_Iframe_bits = m_total_GOP_bits / 10; - m_L1frame_bits = (m_Iframe_bits * 3) / m_num_L1frame; - if(m_encparams.L1Sep() > 1) - m_L2frame_bits = (m_total_GOP_bits - m_Iframe_bits - - m_L1frame_bits * m_num_L1frame) / - (m_encparams.GOPLength() - 1 - m_num_L1frame); + m_Iframe_bits = m_total_GOP_bits/10; + m_L1frame_bits = (m_Iframe_bits*3)/m_num_L1frame; + if (m_encparams.L1Sep()>1) + m_L2frame_bits = ( m_total_GOP_bits - m_Iframe_bits - + m_L1frame_bits*m_num_L1frame )/ + (m_encparams.GOPLength()-1-m_num_L1frame); else m_L2frame_bits = 0; @@ -124,7 +124,7 @@ void RateController::SetFrameDistribution() m_num_L1frame = m_encparams.NumL1(); m_num_Iframe = 1; - if(m_num_L1frame == 0) + if (m_num_L1frame == 0) { m_num_Iframe = m_encparams.GOPLength(); m_intra_only = true; @@ -136,60 +136,60 @@ void RateController::SetFrameDistribution() void RateController::CalcTotalBits(const SourceParams& sourceparams) { const Rational& frame_rate = sourceparams.FrameRate(); - double f_rate = double(frame_rate.m_num) / double(frame_rate.m_denom); + double f_rate = double(frame_rate.m_num)/double(frame_rate.m_denom); int GOP_length = m_encparams.GOPLength(); - m_GOP_duration = GOP_length / f_rate; - m_total_GOP_bits = (long int)(m_GOP_duration * 1000.0) * m_target_rate; //Unit in bits + m_GOP_duration = GOP_length/f_rate; + m_total_GOP_bits = (long int)(m_GOP_duration*1000.0)*m_target_rate; //Unit in bits m_GOP_target = m_total_GOP_bits; - m_picture_bits = m_total_GOP_bits / GOP_length; + m_picture_bits = m_total_GOP_bits/GOP_length; - if(m_encparams.Verbose()) + if (m_encparams.Verbose()) { - std::cout << "\nRate Control Encoding with target bit rate = "; - std::cout << m_target_rate << " kbps" << std::endl; + std::cout<<"\nRate Control Encoding with target bit rate = "; + std::cout<<m_target_rate<<" kbps"<< std::endl; - std::cout << "GOP Length = " << GOP_length << std::endl; + std::cout<<"GOP Length = "<<GOP_length<< std::endl; - std::cout << "Frame Rate = " << f_rate << std::endl; + std::cout<<"Frame Rate = "<<f_rate<< std::endl; - std::cout << "GOP Duration = " << m_GOP_duration << std::endl; + std::cout<<"GOP Duration = "<<m_GOP_duration<< std::endl; - std::cout << "Total Allocated Num. of bits for each GOP = "; - std::cout << m_total_GOP_bits << " (" << m_picture_bits << " per frame)"; - std::cout << std::endl; + std::cout<<"Total Allocated Num. of bits for each GOP = "; + std::cout<<m_total_GOP_bits<<" ("<<m_picture_bits<<" per frame)"; + std::cout<<std::endl; } } void RateController::Report() { - std::cout << std::endl; - std::cout << std::endl << "GOP target is " << m_GOP_target; - std::cout << std::endl << "Allocated frame bits by type: "; - std::cout << "I frames - " << m_Iframe_bits; - std::cout << "; L1/P frames - " << m_L1frame_bits; - std::cout << "; L2/B frames - " << m_L2frame_bits; - std::cout << std::endl; + std::cout<<std::endl; + std::cout<<std::endl<<"GOP target is "<<m_GOP_target; + std::cout<<std::endl<<"Allocated frame bits by type: "; + std::cout<<"I frames - "<<m_Iframe_bits; + std::cout<<"; L1/P frames - "<<m_L1frame_bits; + std::cout<<"; L2/B frames - "<<m_L2frame_bits; + std::cout<<std::endl; } double RateController::TargetSubgroupRate() { - long int bits = (m_encparams.L1Sep() - 1) * m_L2frame_bits + - m_L1frame_bits; - return (double)(bits) / (1000.0 * m_GOP_duration); + long int bits = (m_encparams.L1Sep()-1)*m_L2frame_bits+ + m_L1frame_bits; + return (double)(bits)/(1000.0*m_GOP_duration); } double RateController::ProjectedSubgroupRate() { - int bits = (m_encparams.L1Sep() - 1) * m_frame_complexity.L2Complexity() + + int bits = (m_encparams.L1Sep()-1)*m_frame_complexity.L2Complexity()+ m_frame_complexity.L1Complexity(); - return (double)(bits) / (1000.0 * m_GOP_duration); + return (double)(bits)/(1000.0*m_GOP_duration); } void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bits) { @@ -198,54 +198,53 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi // L2 frame before the next L1 frame i.e. before the start of an L1L2L2 // subgroup m_fcount--; - UpdateBuffer(num_bits); + UpdateBuffer( num_bits ); // filter tap for adjusting the QF double target_ratio = 0.9; int field_factor = m_encparams.FieldCoding() ? 2 : 1; - double top_size = (1.0 - target_ratio) - 0.5; - double bottom_size = target_ratio - 0.1; - double actual_ratio = double(m_buffer_bits) / double(m_buffer_size); + double top_size = (1.0 - target_ratio)-0.5; + double bottom_size = target_ratio-0.1; + double actual_ratio = double(m_buffer_bits)/double(m_buffer_size); double tap; - if((pparams.PictureNum() / field_factor) <= 3 * m_encparams.L1Sep()) + if ((pparams.PictureNum()/field_factor)<=3*m_encparams.L1Sep() ) tap = 1.0; - else - { - if(actual_ratio > target_ratio) - tap = (actual_ratio - target_ratio) / top_size; + else{ + if (actual_ratio>target_ratio) + tap = (actual_ratio-target_ratio)/top_size; else - tap = (target_ratio - actual_ratio) / bottom_size; + tap = (target_ratio-actual_ratio)/bottom_size; - tap = std::min(1.0, std::max(tap, 0.25)); + tap = std::min( 1.0, std::max(tap, 0.25 )); } - if(!m_intra_only) + if (!m_intra_only) { bool emergency_realloc = false; int target; // First, do normal coding - if(pparams.PicSort().IsIntra() == true) + if ( pparams.PicSort().IsIntra() == true ) { target = m_Iframe_bits; - if(num_bits < target / 2) + if (num_bits < target/2 ) emergency_realloc = true; // Update the statistics - m_frame_complexity.SetIComplexity(num_bits); + m_frame_complexity.SetIComplexity( num_bits ); // We've just coded an intra frame so we need to set qf for // the next group of L2(B) frames - m_qf = std::max(tap * m_qf + (1.0 - tap) * m_encparams.Qf(), m_encparams.Qf() - 1.0); - m_encparams.SetQf(m_qf); + m_qf = std::max(tap*m_qf+(1.0-tap)*m_encparams.Qf(), m_encparams.Qf()-1.0); + m_encparams.SetQf( m_qf ); - if(pparams.PictureNum() / field_factor == 0) + if (pparams.PictureNum()/field_factor==0) { // We've just coded the very first frame, which is a special // case as the two L2 frames which normally follow are missing @@ -255,47 +254,45 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi } //Update complexities - if((pparams.PictureNum() / field_factor) % m_encparams.L1Sep() != 0) + if ( (pparams.PictureNum()/field_factor) % m_encparams.L1Sep() !=0 ) { // Scheduled B/L2 picture target = m_L2frame_bits; - if(num_bits < target / 2) - { + if (num_bits < target/2 ){ emergency_realloc = true; } m_L2_complexity_sum += num_bits; } - else if(pparams.PicSort().IsIntra() == false) + else if ( pparams.PicSort().IsIntra() == false ) { // Scheduled P/L1 picture (if inserted I picture, don't change the complexity) target = m_L1frame_bits; - if(num_bits < target / 2 || num_bits > target * 3) - { + if (num_bits < target/2 || num_bits > target*3 ){ emergency_realloc = true; } m_frame_complexity.SetL1Complexity(num_bits); } - if(m_fcount == 0 || emergency_realloc == true) + if ( m_fcount==0 || emergency_realloc==true) { - if(emergency_realloc == true && m_encparams.Verbose() == true) - std::cout << std::endl << "Major mis-prediction of frame bit rate: re-allocating"; + if (emergency_realloc==true && m_encparams.Verbose()==true ) + std::cout<<std::endl<<"Major mis-prediction of frame bit rate: re-allocating"; /* We recompute allocations for the next subgroup */ - if(m_encparams.L1Sep() > 1 && m_fcount < m_encparams.L1Sep() - 1) + if ( m_encparams.L1Sep()>1 && m_fcount<m_encparams.L1Sep()-1) { - m_frame_complexity.SetL2Complexity(m_L2_complexity_sum / - (m_encparams.L1Sep() - 1 - m_fcount)); + m_frame_complexity.SetL2Complexity(m_L2_complexity_sum/ + (m_encparams.L1Sep()-1-m_fcount)); } - Allocate((pparams.PictureNum() / field_factor)); + Allocate( (pparams.PictureNum()/field_factor) ); /* We work out what this means for the quality factor and set it*/ @@ -307,29 +304,28 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi // from measured values (complexities) double prate = ProjectedSubgroupRate(); - if(m_encparams.Verbose() == true) + if (m_encparams.Verbose()==true ) { - std::cout << std::endl << "Target subgroup rate = " << trate; - std::cout << ", projected subgroup rate = " << prate; + std::cout<<std::endl<<"Target subgroup rate = "<<trate; + std::cout<<", projected subgroup rate = "<<prate; } // Determine K value - double K = std::pow(prate, 2) * std::pow(10.0, ((double)2 / 5 * (10 - m_qf))) / 16; + double K = std::pow(prate, 2)*std::pow(10.0, ((double)2/5*(10-m_qf)))/16; // Determine a new QF - double new_qf = 10 - (double)5 / 2 * log10(16 * K / std::pow(trate, 2)); - if((std::abs(m_qf - new_qf) < 0.25 && new_qf > 4.0) || new_qf > 8.0) + double new_qf = 10 - (double)5/2*log10(16*K/std::pow(trate, 2)); + if ( ( std::abs(m_qf-new_qf)<0.25 && new_qf > 4.0 ) || new_qf>8.0) m_qf = new_qf; else - m_qf = tap * new_qf + (1.0 - tap) * m_qf; + m_qf = tap*new_qf+(1.0-tap)*m_qf; - m_qf = ReviewQualityFactor(m_qf , num_bits); + m_qf = ReviewQualityFactor( m_qf , num_bits ); - if(m_qf < 8.0) - { - if(prate < 2 * trate) - m_qf = std::max(m_qf, m_encparams.Qf() - 1.0); + if ( m_qf<8.0 ){ + if (prate<2*trate) + m_qf = std::max(m_qf,m_encparams.Qf()-1.0); else - m_qf = std::max(m_qf, m_encparams.Qf() - 2.0); + m_qf = std::max(m_qf,m_encparams.Qf()-2.0); } m_encparams.SetQf(m_qf); @@ -338,7 +334,7 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi /* Resetting */ // Reset the frame counter - if(m_fcount == 0) + if (m_fcount==0) m_fcount = m_encparams.L1Sep(); // Reset the count of L2 bits @@ -352,22 +348,22 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi // Target rate - double trate = double(m_total_GOP_bits) / (1000.0 * m_num_Iframe); + double trate = double(m_total_GOP_bits)/(1000.0*m_num_Iframe); // Projected rate with current QF - double prate = double(num_bits) / 1000.0; + double prate = double(num_bits)/1000.0; // Determine K value - double K = std::pow(prate, 2) * std::pow(10.0, ((double)2 / 5 * (10 - m_qf))) / 16; + double K = std::pow(prate, 2)*std::pow(10.0, ((double)2/5*(10-m_qf)))/16; // Determine a new QF - double new_qf = 10 - (double)5 / 2 * log10(16 * K / std::pow(trate, 2)); + double new_qf = 10 - (double)5/2*log10(16*K/std::pow(trate, 2)); // Adjust the QF to meet the target - double abs_delta = std::abs(new_qf - m_qf); - if(abs_delta > 0.01) + double abs_delta = std::abs( new_qf - m_qf ); + if ( abs_delta>0.01) { // Rate of convergence to new QF double r; @@ -386,16 +382,16 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi Actual parameters may be adjusted later. Some applications may require instant lock. */ - double lg_diff = std::log(abs_delta / 2.0); - if(lg_diff < 0.0) - r = 0.5 * std::exp(-lg_diff * lg_diff / 2.0); + double lg_diff = std::log( abs_delta/2.0 ); + if ( lg_diff< 0.0 ) + r = 0.5*std::exp(-lg_diff*lg_diff/2.0); else - r = 1.0 - 0.5 * std::exp(-lg_diff * lg_diff / 2.0); + r = 1.0-0.5*std::exp(-lg_diff*lg_diff/2.0); r *= 0.75; - m_qf = r * m_qf + (1.0 - r) * new_qf; - m_qf = ReviewQualityFactor(m_qf , num_bits); + m_qf = r*m_qf + (1.0-r)*new_qf; + m_qf = ReviewQualityFactor( m_qf , num_bits ); m_encparams.SetQf(m_qf); } @@ -406,31 +402,31 @@ void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bi } -void RateController::UpdateBuffer(const long int num_bits) +void RateController::UpdateBuffer( const long int num_bits ) { m_buffer_bits -= num_bits; m_buffer_bits += m_picture_bits; - if(m_encparams.Verbose()) + if (m_encparams.Verbose()) { - std::cout << std::endl << "Buffer occupancy = " << ((double)m_buffer_bits * 100.0) - / ((double)m_buffer_size) << "%"; + std::cout<<std::endl<<"Buffer occupancy = "<<((double)m_buffer_bits*100.0) + /((double)m_buffer_size)<<"%"; } - if(m_buffer_bits < 0) + if (m_buffer_bits<0) { - if(m_encparams.Verbose()) + if (m_encparams.Verbose()) { - std::cout << std::endl << "WARNING: decoder buffer is out of bits - bit rate is too high"; + std::cout<<std::endl<<"WARNING: decoder buffer is out of bits - bit rate is too high"; } // m_buffer_bits = 0; } - if(m_buffer_bits > m_buffer_size) + if (m_buffer_bits>m_buffer_size) { - if(m_encparams.Verbose()) + if (m_encparams.Verbose()) { - std::cout << std::endl << "WARNING: decoder buffer has overflowed - bit rate is too low. Assuming bit-stuffing."; + std::cout<<std::endl<<"WARNING: decoder buffer has overflowed - bit rate is too low. Assuming bit-stuffing."; } m_buffer_bits = m_buffer_size; } @@ -438,97 +434,97 @@ void RateController::UpdateBuffer(const long int num_bits) } -void RateController::Allocate(const int fnum) +void RateController::Allocate (const int fnum) { const int XI = m_frame_complexity.IComplexity(); const int XL1 = m_frame_complexity.L1Complexity(); const int XL2 = m_frame_complexity.L2Complexity(); - double buffer_occ = ((double)m_buffer_bits) / ((double)m_buffer_size); + double buffer_occ = ( (double)m_buffer_bits)/((double)m_buffer_size); - if(!m_intra_only) + if ( !m_intra_only) { double correction; - if(buffer_occ < 0.9 && ((fnum + 1) % 4 * m_encparams.L1Sep()) == 0) + if (buffer_occ<0.9 && ( (fnum+1) % 4*m_encparams.L1Sep())==0 ) { // If we're undershooting buffer target, correct slowly - correction = std::min(0.25, 0.25 * (0.9 - buffer_occ) / 0.9); - m_GOP_target = (long int)(double(m_total_GOP_bits) * (1.0 - correction)); + correction = std::min( 0.25, 0.25*(0.9 - buffer_occ )/0.9 ); + m_GOP_target = ( long int)(double(m_total_GOP_bits)*( 1.0-correction) ); } - else if(buffer_occ > 0.9 && ((fnum + 1) % m_encparams.L1Sep()) == 0) + else if (buffer_occ>0.9 && ((fnum+1) % m_encparams.L1Sep())==0) { // If we're overshooting buffer target, correct quickly - correction = std::min(0.5, 0.5 * (buffer_occ - 0.9) / 0.9); - m_GOP_target = (long int)(double(m_total_GOP_bits) * (1.0 + correction)); + correction = std::min( 0.5, 0.5*( buffer_occ - 0.9 )/0.9 ); + m_GOP_target = ( long int)(double(m_total_GOP_bits)*( 1.0+correction) ); } } - const long int min_bits = m_total_GOP_bits / (100 * m_encparams.GOPLength()); + const long int min_bits = m_total_GOP_bits/(100*m_encparams.GOPLength()); // Allocate intra bits - m_Iframe_bits = (long int)(m_GOP_target - / (m_num_Iframe - + (double)(m_num_L1frame * XL1) / XI - + (double)(m_num_L2frame * XL2) / XI)); + m_Iframe_bits = (long int) (m_GOP_target + / (m_num_Iframe + +(double)(m_num_L1frame*XL1)/XI + +(double)(m_num_L2frame*XL2)/XI)); - m_Iframe_bits = std::max(min_bits, m_Iframe_bits); + m_Iframe_bits = std::max( min_bits, m_Iframe_bits ); // Allocate L1 bits - m_L1frame_bits = (long int)(m_GOP_target - / (m_num_L1frame - + (double)(m_num_Iframe * XI) / XL1 - + (double)(m_num_L2frame * XL2) / XL1)); + m_L1frame_bits = (long int) (m_GOP_target + / (m_num_L1frame + +(double)(m_num_Iframe*XI)/XL1 + +(double)(m_num_L2frame*XL2)/XL1)); - m_L1frame_bits = std::max(min_bits, m_L1frame_bits); + m_L1frame_bits = std::max( min_bits, m_L1frame_bits ); // Allocate L2 bits - m_L2frame_bits = (long int)(m_GOP_target - / (m_num_L2frame - + (double)(m_num_Iframe * XI) / XL2 - + (double)(m_num_L1frame * XL1) / XL2)); + m_L2frame_bits = (long int) (m_GOP_target + / (m_num_L2frame + +(double)(m_num_Iframe*XI)/XL2 + +(double)(m_num_L1frame*XL1)/XL2)); - m_L2frame_bits = std::max(min_bits, m_L2frame_bits); + m_L2frame_bits = std::max( min_bits, m_L2frame_bits ); } -float RateController::ReviewQualityFactor(const float qfac, const long int num_bits) +float RateController::ReviewQualityFactor( const float qfac, const long int num_bits ) { - if(num_bits > m_total_GOP_bits / 2) + if (num_bits>m_total_GOP_bits/2) { // The frame is too big, so reset to a smaller quality factor - return ClipQualityFactor(qfac - 2); + return ClipQualityFactor(qfac-2); } else { // Keep the quality factor in a sensible range - return ClipQualityFactor(qfac); + return ClipQualityFactor( qfac ); } } -float RateController::ClipQualityFactor(const float qfac) +float RateController::ClipQualityFactor( const float qfac ) { // Keep the quality factor in a sensible range - if(!m_intra_only) - return std::min(std::max(qfac, 0.0f), 16.0f); + if ( !m_intra_only ) + return std::min( std::max(qfac, 0.0f), 16.0f); else return std::max(qfac, 0.0f); } void RateController::CalcNextIntraQualFactor() { - m_I_qf = (m_I_qf + m_qf) / 2.0; - m_I_qf = ClipQualityFactor(m_I_qf); + m_I_qf = (m_I_qf + m_qf)/2.0; + m_I_qf = ClipQualityFactor( m_I_qf ); m_encparams.SetQf(m_I_qf); const double ff = 0.95; m_I_qf_long_term *= ff; - m_I_qf_long_term += (1.0 - ff) * m_I_qf; + m_I_qf_long_term += ( 1.0 - ff )*m_I_qf; } void RateController::SetCutPictureQualFactor() { - m_qf = std::min(m_qf , m_I_qf_long_term); - m_encparams.SetQf(m_qf); + m_qf = std::min( m_qf , m_I_qf_long_term ); + m_encparams.SetQf( m_qf ); } |