[x265] [PATCH] commit : adding ratecontrol.cpp and ratecontrol.h
sumalatha at multicorewareinc.com
sumalatha at multicorewareinc.com
Thu Aug 8 12:53:41 CEST 2013
# HG changeset patch
# User sumalatha
# Date 1375959099 -19800
# Node ID 8f8e08edfc80dd0e336a86f8a5919f6fc65e9fba
# Parent 33aa6210de6d486b413f0a6ef82750a89d76c981
commit : adding ratecontrol.cpp and ratecontrol.h
diff -r 33aa6210de6d -r 8f8e08edfc80 source/encoder/rateControl.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/source/encoder/rateControl.cpp Thu Aug 08 16:21:39 2013 +0530
@@ -0,0 +1,266 @@
+/*****************************************************************************
+ * Copyright (C) 2013 x265 project
+ *
+ * Authors: Sumalatha <sumalatha at multicorewareinc.com>
+ * Aarthi <aarthi at multicorewareinc.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
+ *
+ * This program is also available under a commercial proprietary license.
+ * For more information, contact us at licensing at multicorewareinc.com.
+ *****************************************************************************/
+
+#include "rateControl.h"
+
+using namespace x265;
+
+
+void RateControl::rateControlInit(TComSlice * frame , float curFrameDuration, x265_param_t *param)
+{
+ curFrame = curFrame;
+ frameType = curFrame->getSliceType();
+ frameNum = param->frameRate;
+ keyFrameInterval = param->keyframeInterval;
+ fps = param->frameRate;
+ bframes = param->bframes;
+
+}
+
+
+void RateControl::rateControlStart(LookaheadFrame *lFrame )
+{
+
+ RateControlEntry *rce = new RateControlEntry();
+ float q;
+
+ //Always enabling ABR
+ if(1)// rc->b_abr )
+ {
+ q = qScale2qp( rateEstimateQscale( lFrame ) );
+ }
+ q = x265_clip3( q, MIN_QP, MAX_QP );
+
+ //rc.qpa_rc = rc.qpa_rc_prev =
+ //rc.qpa_aq = rc.qpa_aq_prev = 0;
+ qp = x265_clip3( q + 0.5f, 0, MAX_QP );
+
+ qpm = q;
+ if( rce )
+ rce->new_qp = qp;
+
+ accum_p_qp_update( );
+
+ if( frameType != B_SLICE )
+ last_non_b_pict_type = frameType;
+
+
+}
+
+void RateControl::accum_p_qp_update( )
+{
+ //x264_ratecontrol_t *rc = h->rc;
+ accum_p_qp *= .95;
+ accum_p_norm *= .95;
+ accum_p_norm += 1;
+ if( frameType == I_SLICE )
+ accum_p_qp += qpm + ip_offset;
+ else
+ accum_p_qp += qpm;
+}
+
+
+float RateControl::rateEstimateQscale (LookaheadFrame *lframe )
+{
+
+ float q;
+ // ratecontrol_entry_t rce = UNINIT(rce);
+ int pict_type = frameType;
+ int64_t total_bits = 0;//CHECK:for ABR
+
+
+
+ if( pict_type == B_SLICE )
+ {
+ /* B-frames don't have independent ratecontrol, but rather get the
+ * average QP of the two adjacent P-frames + an offset */
+
+ int i0 = curFrame->getRefPic(REF_PIC_LIST_0, 0)->getSlice()->getSliceType() == I_SLICE;
+ int i1 = curFrame->getRefPic(REF_PIC_LIST_1, 0)->getSlice()->getSliceType() == I_SLICE;
+ int dt0 = abs(curFrame->getPOC() - curFrame->getRefPic(REF_PIC_LIST_0, 0)->getPOC());
+ int dt1 = abs(curFrame->getPOC() - curFrame->getRefPic(REF_PIC_LIST_1, 0)->getPOC());
+
+
+ //TODO:need to figure out this
+ float q0 = h->fref_nearest[0]->f_qp_avg_rc;
+ float q1 = h->fref_nearest[1]->f_qp_avg_rc;
+
+
+
+ if( i0 && i1 )
+ q = (q0 + q1) / 2 + ip_offset;
+ else if( i0 )
+ q = q1;
+ else if( i1 )
+ q = q0;
+ else
+ q = (q0*dt1 + q1*dt0) / (dt0 + dt1);
+
+ if( h->fenc->b_kept_as_ref )
+ q += pb_offset/2;
+ else
+ q += pb_offset;
+
+
+ qp_novbv = q;
+ return qp2qScale( q );
+ }
+ else
+ {
+ double abr_buffer = 2 * rate_tolerance * bitrate;
+
+
+ /* 1pass ABR */
+ {
+ /* Calculate the quantizer which would have produced the desired
+ * average bitrate if it had been applied to all frames so far.
+ * Then modulate that quant based on the current frame's complexity
+ * relative to the average complexity so far (using the 2pass RCEQ).
+ * Then bias the quant up or down if total size so far was far from
+ * the target.
+ * Result: Depending on the value of rate_tolerance, there is a
+ * tradeoff between quality and bitrate precision. But at large
+ * tolerances, the bit distribution approaches that of 2pass. */
+
+ double wanted_bits, overflow = 1;
+
+ last_satd = 0; //need to get this from lookahead //x264_rc_analyse_slice( h );
+ short_term_cplxsum *= 0.5;
+ short_term_cplxcount *= 0.5;
+ //TODO:need to get the duration for each frame
+ //short_term_cplxsum += last_satd / (CLIP_DURATION(h->fenc->f_duration) / BASE_FRAME_DURATION);
+ short_term_cplxcount ++;
+
+ rce->p_count = ncu;
+
+ rce->pict_type = pict_type;
+
+ {
+ //TODO:wanted_bits_window, fps , h->fenc->i_reordered_pts, h->i_reordered_pts_delay, h->fref_nearest[0]->f_qp_avg_rc, h->param.rc.f_ip_factor, h->sh.i_type
+ //need to checked where it is initialized
+ q = getQScale( rce, wanted_bits_window / cplxr_sum, frameNum );
+
+ /* ABR code can potentially be counterproductive in CBR, so just don't bother.
+ * Don't run it if the frame complexity is zero either. */
+ if( /*!rcc->b_vbv_min_rate && */last_satd )
+ {
+ // TODO: need to check the thread_frames
+ int i_frame_done = frameNum + 1 - h->i_thread_frames;
+ double time_done = i_frame_done / fps;
+ if(i_frame_done > 0 )
+ {
+ //time_done = ((double)(h->fenc->i_reordered_pts - h->i_reordered_pts_delay)) * h->param.i_timebase_num / h->param.i_timebase_den;
+ time_done = ((double)(h->fenc->i_reordered_pts - h->i_reordered_pts_delay)) * (1/fps);
+ }
+ wanted_bits = time_done * bitrate;
+ if( wanted_bits > 0 )
+ {
+ abr_buffer *= X265_MAX( 1, sqrt( time_done ) );
+ overflow = x265_clip3f( 1.0 + (total_bits - wanted_bits) / abr_buffer, .5, 2 );
+ q *= overflow;
+ }
+ }
+ }
+
+ if( pict_type == I_SLICE && keyFrameInterval > 1
+ /* should test _next_ pict type, but that isn't decided yet */
+ && last_non_b_pict_type != I_SLICE )
+ {
+ q = qp2qScale( accum_p_qp / accum_p_norm );
+ q /= fabs( h->param.rc.f_ip_factor );
+ }
+ else if( frameNum > 0 )
+ {
+ if(1)//assume that for ABR this is always enabled h->param.rc.i_rc_method != X264_RC_CRF )
+ {
+ /* Asymmetric clipping, because symmetric would prevent
+ * overflow control in areas of rapidly oscillating complexity */
+ double lmin = last_qscale_for[pict_type] / lstep;
+ double lmax = last_qscale_for[pict_type] * lstep;
+ if( overflow > 1.1 && frameNum > 3 )
+ lmax *= lstep;
+ else if( overflow < 0.9 )
+ lmin /= lstep;
+
+ q = x265_clip3f(q, lmin, lmax);
+ }
+ }
+
+ qp_novbv = qScale2qp( q );
+
+ //FIXME use get_diff_limited_q() ?
+ //q = clip_qscale( h, pict_type, q );
+ double lmin_1 = lmin[pict_type];
+ double lmax_1 = lmax[pict_type];
+ x265_clip3f( q, lmin_1, lmax_1 );
+ }
+
+ last_qscale_for[pict_type] =
+ last_qscale = q;
+
+ if( !frameNum == 0 )
+ last_qscale_for[P_SLICE] = q * fabs( h->param.rc.f_ip_factor );
+
+ //this is for VBV stuff
+ //frame_size_planned = predict_size( &pred[h->sh.i_type], q, last_satd );
+
+
+
+ return q;
+ }
+}
+
+
+/**
+ * modify the bitrate curve from pass1 for one frame
+ */
+double RateControl::getQScale(RateControlEntry *rce, double rate_factor, int frame_num)
+{
+ double q;
+ //x264_zone_t *zone = get_zone( h, frame_num );
+
+ q = pow( rce->blurred_complexity, 1 - qcompress );
+
+ // avoid NaN's in the rc_eq
+ if(rce->tex_bits + rce->mv_bits == 0 )
+ q = last_qscale_for[rce->pict_type];
+ else
+ {
+ last_rceq = q;
+ q /= rate_factor;
+ last_qscale = q;
+ }
+
+ /*TODO: need to check zone is required */
+ //if( zone )
+ //{
+ // if( zone->b_force_qp )
+ // q = qp2qscale( zone->i_qp );
+ // else
+ // q /= zone->f_bitrate_factor;
+ //}
+
+ return q;
+}
+
diff -r 33aa6210de6d -r 8f8e08edfc80 source/encoder/rateControl.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/source/encoder/rateControl.h Thu Aug 08 16:21:39 2013 +0530
@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * Copyright (C) 2013 x265 project
+ *
+ * Authors: Sumalatha <sumalatha at multicorewareinc.com>
+ * Aarthi <aarthi at multicorewareinc.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
+ *
+ * This program is also available under a commercial proprietary license.
+ * For more information, contact us at licensing at multicorewareinc.com.
+ *****************************************************************************/
+
+#ifndef __RATECONTROL__
+#define __RATECONTROL__
+
+#include <stdint.h>
+#include "TLibEncoder/TEncTop.h"
+
+#include "math.h"
+
+namespace x265 {
+// private x265 namespace
+
+class RateControlEntry
+{
+ public:
+ int pict_type;
+ int p_count;
+ int new_qp;
+ float blurred_complexity;
+ int tex_bits;
+ int mv_bits;
+
+
+
+
+} ;
+
+typedef struct
+{
+ float coeff;
+ float count;
+ float decay;
+ float offset;
+} predictor_t;
+
+
+class RateControl
+{
+public:
+ int ncu; /* number of CUs in a frame */
+ TComSlice *curFrame; /* all info abt the current frame */
+ SliceType frameType; /*Current frame type */
+ float frameDuration ; /*current frame duration in seconds */
+ int frameNum; /*current frame number TODO: need to initaialize in init */
+ int keyFrameInterval; /*TODO: need to initialize in init */
+
+
+
+
+ /* current frame */
+ RateControlEntry *rce;
+ int qp; /* updated qp for current frame */
+ float qpm; /* qp for current macroblock: precise float for AQ */
+
+ double bitrate;
+ double rate_tolerance;
+ double qcompress;
+
+
+ /* ABR stuff */
+ int last_satd;
+ double last_rceq;
+ double cplxr_sum; /* sum of bits*qscale/rceq */
+ double expected_bits_sum; /* sum of qscale2bits after rceq, ratefactor, and overflow, only includes finished frames */
+ int64_t filler_bits_sum; /* sum in bits of finished frames' filler data */
+ double wanted_bits_window; /* target bitrate * window */
+ double cbr_decay;
+ double short_term_cplxsum;
+ double short_term_cplxcount;
+ double rate_factor_constant;
+ double ip_offset;
+ double pb_offset;
+
+ int last_non_b_pict_type;
+ double accum_p_qp; /* for determining I-frame quant */
+ double accum_p_norm;
+ double last_qscale;
+ double last_qscale_for[3]; /* last qscale for a specific pict type, used for max_diff & ipb factor stuff */
+
+ double fps;
+ double lstep;
+ float qp_novbv; /* QP for the current frame if 1-pass VBV was disabled. */
+ double lmin[3]; /* min qscale by frame type */
+ double lmax[3];
+ double frame_size_planned;
+
+
+
+
+void rateControlInit(TComSlice * frame , float curFrameDuration, x265_param_t *param); // to be called for each frame to set the reqired parameters for rateControl.
+void rateControlStart(LookaheadFrame *lframe); // to be called for each frame to process RateCOntrol and set QP
+
+float rateEstimateQscale(LookaheadFrame *lframe); // main logic for calculating QP based on ABR
+void accum_p_qp_update();
+double getQScale(RateControlEntry *rce, double rate_factor, int frame_num);
+
+float qScale2qp( float qscale )
+{
+ return 12.0f + 6.0f * logf( qscale/0.85f );
+}
+
+float qp2qScale( float qp )
+{
+ return 0.85f * powf( 2.0f, ( qp - 12.0f ) / 6.0f );
+}
+int x265_clip3( int v, int i_min, int i_max )
+{
+ return ( (v < i_min) ? i_min : (v > i_max) ? i_max : v );
+}
+
+double x265_clip3f( double v, double i_min, double i_max )
+{
+ return ( (v < i_min) ? i_min : (v > i_max) ? i_max : v );
+}
+
+float predict_size( predictor_t *p, float q, float var )
+{
+ return (p->coeff*var + p->offset) / (q*p->count);
+}
+
+
+
+
+};
+ }
+
+#endif // ifndef __RATECONTROL__
\ No newline at end of file
More information about the x265-devel
mailing list