[x265] [PATCH] SEI: Insert buffering period and picture timing SEI messages

kavitha at multicorewareinc.com kavitha at multicorewareinc.com
Sun Jun 1 18:40:32 CEST 2014


# HG changeset patch
# User Kavitha Sampath <kavitha at multicorewareinc.com>
# Date 1401640530 -19800
#      Sun Jun 01 22:05:30 2014 +0530
# Node ID 322bcc4d26dd358d946b9e8da369f52690344af4
# Parent  592ef184549ef631c0fe725cb9fe3cbab8de1db4
SEI: Insert buffering period and picture timing SEI messages

The buffering period SEI message is inserted for every key frame and the
picture timing SEI is inserted for every frame. The commit also computes the
HRD parameters carried in these SEI messages. HRD parameters are signalled by
enabling --hrd.

diff -r 592ef184549e -r 322bcc4d26dd doc/reST/cli.rst
--- a/doc/reST/cli.rst	Thu May 29 23:42:16 2014 +0300
+++ b/doc/reST/cli.rst	Sun Jun 01 22:05:30 2014 +0530
@@ -846,6 +846,13 @@
 	to keep the stream headers for you and you want keyframes to be
 	random access points. Default disabled
 
+.. option:: --hrd, --no-hrd
+
+	Enable the signalling of HRD parameters to the decoder. The HRD
+	parameters are carried by the Buffering Period SEI messages and
+	Picture Timing SEI messages providing timing information to the
+	decoder. Default disabled
+
 .. option:: --aud, --no-aud
 
 	Emit an access unit delimiter NAL at the start of each slice access
diff -r 592ef184549e -r 322bcc4d26dd source/CMakeLists.txt
--- a/source/CMakeLists.txt	Thu May 29 23:42:16 2014 +0300
+++ b/source/CMakeLists.txt	Sun Jun 01 22:05:30 2014 +0530
@@ -19,7 +19,7 @@
 include(CheckCXXCompilerFlag)
 
 # X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 20)
+set(X265_BUILD 21)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 592ef184549e -r 322bcc4d26dd source/Lib/TLibCommon/SEI.h
--- a/source/Lib/TLibCommon/SEI.h	Thu May 29 23:42:16 2014 +0300
+++ b/source/Lib/TLibCommon/SEI.h	Sun Jun 01 22:05:30 2014 +0530
@@ -185,14 +185,7 @@
 
     PayloadType payloadType() const { return PICTURE_TIMING; }
 
-    SEIPictureTiming()
-        : m_picStruct(0)
-        , m_sourceScanType(0)
-        , m_duplicateFlag(false)
-        , m_picDpbOutputDuDelay(0)
-        , m_numNalusInDuMinus1(NULL)
-        , m_duCpbRemovalDelayMinus1(NULL)
-    {}
+    SEIPictureTiming() {}
 
     virtual ~SEIPictureTiming()
     {
diff -r 592ef184549e -r 322bcc4d26dd source/common/param.cpp
--- a/source/common/param.cpp	Thu May 29 23:42:16 2014 +0300
+++ b/source/common/param.cpp	Sun Jun 01 22:05:30 2014 +0530
@@ -613,6 +613,7 @@
     OPT("hash") p->decodedPictureHashSEI = atoi(value);
     OPT("aud") p->bEnableAccessUnitDelimiters = atobool(value);
     OPT("b-pyramid") p->bBPyramid = atobool(value);
+    OPT("hrd") p->bEmitHRDSEI = atobool(value);
     OPT("aq-mode") p->rc.aqMode = atoi(value);
     OPT("aq-strength") p->rc.aqStrength = atof(value);
     OPT("vbv-maxrate") p->rc.vbvMaxBitrate = atoi(value);
diff -r 592ef184549e -r 322bcc4d26dd source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Thu May 29 23:42:16 2014 +0300
+++ b/source/encoder/encoder.cpp	Sun Jun 01 22:05:30 2014 +0530
@@ -184,6 +184,7 @@
             }
         }
     }
+    m_rateControl->init(&m_frameEncoder[0].m_sps);
     m_lookahead->init();
     m_encodeStartTime = x265_mdate();
     m_totalFrameThreads = param->frameNumThreads;
@@ -1121,8 +1122,8 @@
     vui->setFrameFieldInfoPresentFlag(!!param->interlaceMode);
     vui->setFieldSeqFlag(!!param->interlaceMode);
 
-    vui->setHrdParametersPresentFlag(false);
-    vui->getHrdParameters()->setNalHrdParametersPresentFlag(false);
+    vui->setHrdParametersPresentFlag(param->bEmitHRDSEI);
+    vui->getHrdParameters()->setNalHrdParametersPresentFlag(param->bEmitHRDSEI);
     vui->getHrdParameters()->setSubPicHrdParamsPresentFlag(false);
 
     vui->getTimingInfo()->setTimingInfoPresentFlag(true);
@@ -1424,12 +1425,10 @@
 
     m_nonPackedConstraintFlag = false;
     m_frameOnlyConstraintFlag = false;
-    m_bufferingPeriodSEIEnabled = 0;
     m_displayOrientationSEIAngle = 0;
     m_gradualDecodingRefreshInfoEnabled = 0;
     m_decodingUnitInfoSEIEnabled = 0;
     m_useScalingListId = 0;
-    m_activeParameterSetsSEIEnabled = 0;
     m_minSpatialSegmentationIdc = 0;
     m_neutralChromaIndicationFlag = false;
     m_pocProportionalToTimingFlag = false;
diff -r 592ef184549e -r 322bcc4d26dd source/encoder/encoder.h
--- a/source/encoder/encoder.h	Thu May 29 23:42:16 2014 +0300
+++ b/source/encoder/encoder.h	Sun Jun 01 22:05:30 2014 +0530
@@ -82,7 +82,6 @@
     int64_t            m_firstPts;
     int64_t            m_bframeDelayTime;
     int64_t            m_prevReorderedPts[2];
-    int64_t            m_encodedFrameNum;
 
     ThreadPool*        m_threadPool;
     Lookahead*         m_lookahead;
@@ -157,7 +156,8 @@
     bool               m_bPCMFilterDisableFlag;
     bool               m_loopFilterAcrossTilesEnabledFlag;
 
-    int                m_bufferingPeriodSEIEnabled;
+    int64_t            m_encodedFrameNum;
+    int                m_lastBPSEI;
     int                m_displayOrientationSEIAngle;
     int                m_gradualDecodingRefreshInfoEnabled;
     int                m_decodingUnitInfoSEIEnabled;
@@ -168,7 +168,6 @@
 
     bool               m_TransquantBypassEnableFlag;   ///< transquant_bypass_enable_flag setting in PPS.
     bool               m_CUTransquantBypassFlagValue;  ///< if transquant_bypass_enable_flag, the fixed value to use for the per-CU cu_transquant_bypass_flag.
-    int                m_activeParameterSetsSEIEnabled; ///< enable active parameter set SEI message
 
     bool               m_neutralChromaIndicationFlag;
     bool               m_pocProportionalToTimingFlag;
diff -r 592ef184549e -r 322bcc4d26dd source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Thu May 29 23:42:16 2014 +0300
+++ b/source/encoder/frameencoder.cpp	Sun Jun 01 22:05:30 2014 +0530
@@ -143,11 +143,17 @@
     {
         m_sps.setHrdParameters(m_cfg->param->fpsNum, m_cfg->param->fpsDenom, 0, m_cfg->param->rc.bitrate, m_cfg->param->bframes > 0);
     }
-    if (m_cfg->m_bufferingPeriodSEIEnabled || m_cfg->m_decodingUnitInfoSEIEnabled)
+    if (m_cfg->param->bEmitHRDSEI || m_cfg->m_decodingUnitInfoSEIEnabled)
     {
         m_sps.getVuiParameters()->setHrdParametersPresentFlag(true);
     }
 
+    // initialize HRD parameters of SPS
+    if (m_cfg->param->bEmitHRDSEI)
+    {
+        top->m_rateControl->initHRD(&m_sps);
+    }
+
     m_sps.setTMVPFlagsPresent(true);
 
     // set default slice level flag to the same as SPS level flag
@@ -266,7 +272,7 @@
     nalunits[count]->init(nalu);
     count++;
 
-    if (m_cfg->m_activeParameterSetsSEIEnabled)
+    if (m_cfg->param->bEmitHRDSEI)
     {
         SEIActiveParameterSets sei;
         sei.activeVPSId = m_top->m_vps.getVPSId();
@@ -275,6 +281,7 @@
         sei.numSpsIdsMinus1 = 0;
         sei.activeSeqParamSetId = m_sps.getSPSId();
 
+        nalu.resetToType(NAL_UNIT_PREFIX_SEI);
         entropyCoder->setBitstream(&nalu.m_bitstream);
         m_seiWriter.writeSEImessage(nalu.m_bitstream, sei, &m_sps);
         writeRBSPTrailingBits(nalu.m_bitstream);
@@ -404,6 +411,7 @@
     TEncEntropy* entropyCoder      = getEntropyCoder(0);
     TComSlice*   slice             = m_pic->getSlice();
     int          chFmt             = slice->getSPS()->getChromaFormatIdc();
+    int          totalCoded        = (int)m_top->m_encodedFrameNum - 1;
 
     m_nalCount = 0;
     entropyCoder->setEntropyCoder(&m_sbacCoder, NULL);
@@ -526,6 +534,34 @@
 
     if (slice->getPic()->m_lowres.bKeyframe)
     {
+        if (m_cfg->param->bEmitHRDSEI)
+        {
+            OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI);
+            SEIBufferingPeriod sei_buffering_period;
+            sei_buffering_period.m_bpSeqParameterSetId = m_sps.getSPSId();
+            sei_buffering_period.m_rapCpbParamsPresentFlag = 0;
+
+            // for the concatenation, it can be set to one during splicing.
+            sei_buffering_period.m_concatenationFlag = 0;
+
+            // since the temporal layer HRD is not ready, we assumed it is fixed
+            sei_buffering_period.m_auCpbRemovalDelayDelta = 1;
+            sei_buffering_period.m_cpbDelayOffset = 0;
+            sei_buffering_period.m_dpbDelayOffset = 0;
+
+            // hrdFullness() calculates the initial CPB removal delay and offset
+            m_top->m_rateControl->hrdFullness(&sei_buffering_period);
+            m_seiWriter.writeSEImessage(nalu.m_bitstream, sei_buffering_period, &m_sps);
+            writeRBSPTrailingBits(nalu.m_bitstream);
+            m_nalList[m_nalCount] = X265_MALLOC(NALUnitEBSP, 1);
+            if (m_nalList[m_nalCount])
+            {
+                m_nalList[m_nalCount]->init(nalu);
+                m_nalCount++;
+            }
+
+            m_top->m_lastBPSEI = totalCoded;
+        }
         if (m_cfg->m_gradualDecodingRefreshInfoEnabled && !slice->getRapPicFlag())
         {
             // Gradual decoding refresh SEI
@@ -568,21 +604,36 @@
         }
     }
 
-    if (!!m_cfg->param->interlaceMode)
+    if (m_cfg->param->bEmitHRDSEI || !!m_cfg->param->interlaceMode)
     {
+        // Picture Timing SEI
         OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI);
+        SEIPictureTiming sei;
 
-        SEIPictureTiming sei;
+        int poc = slice->getPOC();
+        int cpbDelayLength = slice->getSPS()->getVuiParameters()->getHrdParameters()->getCpbRemovalDelayLengthMinus1() + 1;
         if (m_cfg->param->interlaceMode == 2)
         {
-            sei.m_picStruct = (slice->getPOC() & 1) ? 1 /* top */ : 2 /* bottom */;
+            sei.m_picStruct = (poc & 1) ? 1 /* top */ : 2 /* bottom */;
+        }
+        else if (m_cfg->param->interlaceMode == 1)
+        {
+            sei.m_picStruct = (poc & 1) ? 2 /* bottom */ : 1 /* top */;
         }
         else
         {
-            sei.m_picStruct = (slice->getPOC() & 1) ? 2 /* bottom */ : 1 /* top */;
+            sei.m_picStruct = 0;
         }
         sei.m_sourceScanType = 0;
-        sei.m_duplicateFlag = 0;
+        sei.m_duplicateFlag = false;
+        sei.m_picDpbOutputDuDelay = 0;
+        sei.m_numNalusInDuMinus1 = NULL;
+        sei.m_duCpbRemovalDelayMinus1 = NULL;
+
+        // The m_aucpbremoval delay specifies how many clock ticks the access unit associated with the picture timing
+        // SEI message has to wait after removal of the access unit with the most recent buffering period SEI message
+        sei.m_auCpbRemovalDelay = X265_MIN(X265_MAX(1, totalCoded - m_top->m_lastBPSEI), (1 << cpbDelayLength));
+        sei.m_picDpbOutputDelay = slice->getSPS()->getNumReorderPics(0) + poc - totalCoded;
 
         entropyCoder->setBitstream(&nalu.m_bitstream);
         m_seiWriter.writeSEImessage(nalu.m_bitstream, sei, &m_sps);
diff -r 592ef184549e -r 322bcc4d26dd source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Thu May 29 23:42:16 2014 +0300
+++ b/source/encoder/ratecontrol.cpp	Sun Jun 01 22:05:30 2014 +0530
@@ -27,12 +27,60 @@
 #include "encoder.h"
 #include "slicetype.h"
 #include "ratecontrol.h"
+#include "TLibCommon/SEI.h"
+
+#define BR_SHIFT  6
+#define CPB_SHIFT 4
 
 using namespace x265;
 
 /* Amortize the partial cost of I frames over the next N frames */
 const double RateControl::amortizeFraction = 0.85;
 const int RateControl::amortizeFrames = 75;
+namespace {
+
+inline int calcScale(uint32_t x)
+{
+    static uint8_t lut[16] = {4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+    int y, z = (((x & 0xffff) - 1) >> 27) & 16;
+    x >>= z;
+    z += y = (((x & 0xff) - 1) >> 28) & 8;
+    x >>= y;
+    z += y = (((x & 0xf) - 1) >> 29) & 4;
+    x >>= y;
+    return z + lut[x&0xf];
+}
+
+inline int calcLength(uint32_t x)
+{
+    static uint8_t lut[16] = {4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
+    int y, z = (((x >> 16) - 1) >> 27) & 16;
+    x >>= z ^ 16;
+    z += y = ((x - 0x100) >> 28) & 8;
+    x >>= y ^ 8;
+    z += y = ((x - 0x10) >> 29) & 4;
+    x >>= y ^ 4;
+    return z + lut[x];
+}
+
+inline void reduceFraction(int* n, int* d)
+{
+    int a = *n;
+    int b = *d;
+    int c;
+    if (!a || !b)
+        return;
+    c = a % b;
+    while (c)
+    {
+        a = b;
+        b = c;
+        c = a % b;
+    }
+    *n /= b;
+    *d /= b;
+}
+}  // end anonymous namespace
 
 /* Compute variance to derive AC energy of each block */
 static inline uint32_t acEnergyVar(TComPic *pic, uint64_t sum_ssd, int shift, int i)
@@ -287,40 +335,11 @@
         param->rc.vbvMaxBitrate = 0;
     }
 
-    isVbv = param->rc.vbvMaxBitrate > 0 && param->rc.vbvBufferSize > 0;
-    double fps = (double)param->fpsNum / param->fpsDenom;
-    if (isVbv)
-    {
-        /* We don't support changing the ABR bitrate right now,
-           so if the stream starts as CBR, keep it CBR. */
-        if (param->rc.vbvBufferSize < (int)(param->rc.vbvMaxBitrate / fps))
-        {
-            param->rc.vbvBufferSize = (int)(param->rc.vbvMaxBitrate / fps);
-            x265_log(param, X265_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",
-                     param->rc.vbvBufferSize);
-        }
-        int vbvBufferSize = param->rc.vbvBufferSize * 1000;
-        int vbvMaxBitrate = param->rc.vbvMaxBitrate * 1000;
-
-        bufferRate = vbvMaxBitrate / fps;
-        vbvMaxRate = vbvMaxBitrate;
-        bufferSize = vbvBufferSize;
-        singleFrameVbv = bufferRate * 1.1 > bufferSize;
-
-        if (param->rc.vbvBufferInit > 1.)
-            param->rc.vbvBufferInit = Clip3(0.0, 1.0, param->rc.vbvBufferInit / param->rc.vbvBufferSize);
-        param->rc.vbvBufferInit = Clip3(0.0, 1.0, X265_MAX(param->rc.vbvBufferInit, bufferRate / bufferSize));
-        bufferFillFinal = bufferSize * param->rc.vbvBufferInit;
-        isCbr = param->rc.rateControlMode == X265_RC_ABR
-            && param->rc.vbvMaxBitrate <= param->rc.bitrate;
-    }
-
     bframes = param->bframes;
     bframeBits = 0;
     leadingNoBSatd = 0;
     ipOffset = 6.0 * X265_LOG2(param->rc.ipFactor);
     pbOffset = 6.0 * X265_LOG2(param->rc.pbFactor);
-    init();
 
     /* Adjust the first frame in order to stabilize the quality level compared to the rest */
 #define ABR_INIT_QP_MIN (24 + QP_BD_OFFSET)
@@ -347,8 +366,41 @@
     lstep = pow(2, param->rc.qpStep / 6.0);
 }
 
-void RateControl::init()
+void RateControl::init(TComSPS *sps)
 {
+    isVbv = param->rc.vbvMaxBitrate > 0 && param->rc.vbvBufferSize > 0;
+    double fps = (double)param->fpsNum / param->fpsDenom;
+    if (isVbv)
+    {
+        /* We don't support changing the ABR bitrate right now,
+           so if the stream starts as CBR, keep it CBR. */
+        if (param->rc.vbvBufferSize < (int)(param->rc.vbvMaxBitrate / fps))
+        {
+            param->rc.vbvBufferSize = (int)(param->rc.vbvMaxBitrate / fps);
+            x265_log(param, X265_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",
+                     param->rc.vbvBufferSize);
+        }
+        int vbvBufferSize = param->rc.vbvBufferSize * 1000;
+        int vbvMaxBitrate = param->rc.vbvMaxBitrate * 1000;
+
+        TComHRD* hrd = sps->getVuiParameters()->getHrdParameters();
+        if (hrd->getNalHrdParametersPresentFlag())
+        {
+            vbvBufferSize = (hrd->getCpbSizeValueMinus1(0, 0, 0) + 1) << (hrd->getCpbSizeScale() + CPB_SHIFT);
+            vbvMaxBitrate = (hrd->getBitRateValueMinus1(0, 0, 0) + 1) << (hrd->getBitRateScale() + BR_SHIFT);
+        }
+        bufferRate = vbvMaxBitrate / fps;
+        vbvMaxRate = vbvMaxBitrate;
+        bufferSize = vbvBufferSize;
+        singleFrameVbv = bufferRate * 1.1 > bufferSize;
+
+        if (param->rc.vbvBufferInit > 1.)
+            param->rc.vbvBufferInit = Clip3(0.0, 1.0, param->rc.vbvBufferInit / param->rc.vbvBufferSize);
+        param->rc.vbvBufferInit = Clip3(0.0, 1.0, X265_MAX(param->rc.vbvBufferInit, bufferRate / bufferSize));
+        bufferFillFinal = bufferSize * param->rc.vbvBufferInit;
+        isCbr = param->rc.rateControlMode == X265_RC_ABR
+            && param->rc.vbvMaxBitrate <= param->rc.bitrate;
+    }
     totalBits = 0;
     framesDone = 0;
     double tuneCplxFactor = 1;
@@ -373,6 +425,45 @@
     predBfromP = pred[0];
 }
 
+void RateControl::initHRD(TComSPS *sps)
+{
+    int vbvBufferSize = param->rc.vbvBufferSize * 1000;
+    int vbvMaxBitrate = param->rc.vbvMaxBitrate * 1000;
+
+    // Init HRD
+    TComHRD* hrd = sps->getVuiParameters()->getHrdParameters();
+    hrd->setCpbCntMinus1(0, 0);
+    hrd->setLowDelayHrdFlag(0, false);
+    hrd->setFixedPicRateFlag(0, 1);
+    hrd->setPicDurationInTcMinus1(0, 0);
+
+    // normalize HRD size and rate to the value / scale notation
+    hrd->setBitRateScale(Clip3(0, 15, calcScale(vbvMaxBitrate) - BR_SHIFT));
+    hrd->setBitRateValueMinus1(0, 0, 0, (vbvMaxBitrate >> (hrd->getBitRateScale() + BR_SHIFT)) - 1);
+
+    hrd->setCpbSizeScale(Clip3(0, 15, calcScale(vbvBufferSize) - CPB_SHIFT));
+    hrd->setCpbSizeValueMinus1(0, 0, 0, (vbvBufferSize >> (hrd->getCpbSizeScale() + CPB_SHIFT)) - 1);
+    int bitRateUnscale = (hrd->getBitRateValueMinus1(0, 0, 0) + 1) << (hrd->getBitRateScale() + BR_SHIFT);
+    int cpbSizeUnscale = (hrd->getCpbSizeValueMinus1(0, 0, 0) + 1) << (hrd->getCpbSizeScale() + CPB_SHIFT);
+
+    // arbitrary
+    #define MAX_DURATION 0.5
+
+    TimingInfo *time = sps->getVuiParameters()->getTimingInfo();
+    int maxCpbOutputDelay = (int)(X265_MIN(param->keyframeMax * MAX_DURATION * time->getTimeScale() / time->getNumUnitsInTick(), INT_MAX));
+    int maxDpbOutputDelay = (int)(sps->getMaxDecPicBuffering(0) * MAX_DURATION * time->getTimeScale() / time->getNumUnitsInTick());
+    int maxDelay = (int)(90000.0 * cpbSizeUnscale / bitRateUnscale + 0.5);
+
+    hrd->setInitialCpbRemovalDelayLengthMinus1(2 + Clip3(4, 22, 32 - calcLength(maxDelay)) - 1);
+    hrd->setCpbRemovalDelayLengthMinus1(Clip3(4, 31, 32 - calcLength(maxCpbOutputDelay)) - 1);
+    hrd->setDpbOutputDelayLengthMinus1(Clip3(4, 31, 32 - calcLength(maxDpbOutputDelay)) - 1);
+
+    #undef MAX_DURATION
+
+    vbvBufferSize = cpbSizeUnscale;
+    vbvMaxBitrate = bitRateUnscale;
+}
+
 void RateControl::rateControlStart(TComPic* pic, Lookahead *l, RateControlEntry* rce, Encoder* enc)
 {
     curSlice = pic->getSlice();
@@ -627,7 +718,7 @@
             double underflow = 1.0 + (totalBits - wantedBitsWindow) / abrBuffer;
             if (underflow < 0.9 && !isFrameDone)
             {
-                init();
+                init(NULL);
                 shortTermCplxSum = rce->lastSatd / (CLIP_DURATION(frameDuration) / BASE_FRAME_DURATION);
                 shortTermCplxCount = 1;
                 isAbrReset = true;
@@ -642,6 +733,26 @@
     }
 }
 
+void RateControl::hrdFullness(SEIBufferingPeriod *seiBP)
+{
+    TComVUI* vui = curSlice->getSPS()->getVuiParameters();
+    TComHRD* hrd = vui->getHrdParameters();
+    int num = 90000;
+    int denom = (hrd->getBitRateValueMinus1(0, 0, 0) + 1) << (hrd->getBitRateScale() + BR_SHIFT);
+    reduceFraction(&num, &denom);
+    uint64_t cpbState = (uint64_t)bufferFillFinal;
+    uint64_t cpbSize = (uint64_t)((hrd->getCpbSizeValueMinus1(0, 0, 0) + 1) << (hrd->getCpbSizeScale() + CPB_SHIFT));
+
+    if(cpbState < 0 || cpbState > cpbSize)
+    {
+         x265_log(param, X265_LOG_WARNING, "CPB %s: %.0lf bits in a %.0lf-bit buffer\n",
+                   cpbState < 0 ? "underflow" : "overflow", (float)cpbState/denom, (float)cpbSize/denom);
+    }
+
+    seiBP->m_initialCpbRemovalDelay[0][0] = (uint32_t)(num * cpbState + denom) / denom;
+    seiBP->m_initialCpbRemovalDelayOffset[0][0] = (uint32_t)(num * cpbSize + denom) / denom - seiBP->m_initialCpbRemovalDelay[0][0];
+}
+
 void RateControl::updateVbvPlan(Encoder* enc)
 {
     bufferFill = bufferFillFinal;
diff -r 592ef184549e -r 322bcc4d26dd source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Thu May 29 23:42:16 2014 +0300
+++ b/source/encoder/ratecontrol.h	Sun Jun 01 22:05:30 2014 +0530
@@ -26,14 +26,14 @@
 #ifndef X265_RATECONTROL_H
 #define X265_RATECONTROL_H
 
-#include "TLibCommon/CommonDef.h"
-
 namespace x265 {
 // encoder namespace
 
 struct Lookahead;
 class Encoder;
 class TComPic;
+class TComSPS;
+class SEIBufferingPeriod;
 
 #define BASE_FRAME_DURATION 0.04
 
@@ -129,6 +129,9 @@
     void calcAdaptiveQuantFrame(TComPic *pic);
     int rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce);
     int rowDiagonalVbvRateControl(TComPic* pic, uint32_t row, RateControlEntry* rce, double& qpVbv);
+    void hrdFullness(SEIBufferingPeriod* sei);
+    void init(TComSPS* sps);
+    void initHRD(TComSPS* sps);
 
 protected:
 
@@ -138,7 +141,6 @@
     int residualFrames;
     int residualCost;
 
-    void init();
     double getQScale(RateControlEntry *rce, double rateFactor);
     double rateEstimateQscale(TComPic* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR
     void accumPQpUpdate();
diff -r 592ef184549e -r 322bcc4d26dd source/x265.cpp
--- a/source/x265.cpp	Thu May 29 23:42:16 2014 +0300
+++ b/source/x265.cpp	Sun Jun 01 22:05:30 2014 +0530
@@ -159,6 +159,8 @@
     { "strong-intra-smoothing",    no_argument, NULL, 0 },
     { "no-cutree",                 no_argument, NULL, 0 },
     { "cutree",                    no_argument, NULL, 0 },
+    { "no-hrd",               no_argument, NULL, 0 },
+    { "hrd",                  no_argument, NULL, 0 },
     { "sar",            required_argument, NULL, 0 },
     { "overscan",       required_argument, NULL, 0 },
     { "videoformat",    required_argument, NULL, 0 },
@@ -386,6 +388,7 @@
     H0("   --[no-]cutree                 Enable cutree for Adaptive Quantization. Default %s\n", OPT(param->rc.cuTree));
     H0("   --cbqpoffs <integer>          Chroma Cb QP Offset. Default %d\n", param->cbQpOffset);
     H0("   --crqpoffs <integer>          Chroma Cr QP Offset. Default %d\n", param->crQpOffset);
+    H0("   --[no-]hrd                    Enable HRD parameters signalling. Default %s\n", OPT(param->bEmitHRDSEI));
     H0("   --rd <0..6>                   Level of RD in mode decision 0:least....6:full RDO. Default %d\n", param->rdLevel);
     H0("   --psy-rd <0..2.0>             Strength of psycho-visual optimization. Requires slow preset or below. Default %f\n", param->psyRd);
     H0("   --[no-]signhide               Hide sign bit of one coeff per TU (rdo). Default %s\n", OPT(param->bEnableSignHiding));
diff -r 592ef184549e -r 322bcc4d26dd source/x265.h
--- a/source/x265.h	Thu May 29 23:42:16 2014 +0300
+++ b/source/x265.h	Sun Jun 01 22:05:30 2014 +0530
@@ -410,6 +410,10 @@
      * NAL at the start of every access unit. Default false */
     int       bEnableAccessUnitDelimiters;
 
+    /* Enables the buffering period SEI and picture timing SEI to signal the HRD
+     * parameteres. Default is disabled */
+    int       bEmitHRDSEI;
+
     /*== Coding Unit (CU) definitions ==*/
 
     /* Maxiumum CU width and height in pixels.  The size must be 64, 32, or 16.


More information about the x265-devel mailing list