[x265] [PATCH] rc: implement qp with Aq for each Cu before encoding them

Aarthi Thirumalai aarthi at multicorewareinc.com
Mon Oct 28 11:06:27 CET 2013


# HG changeset patch
# User Aarthi Thirumalai
# Date 1382954771 -19800
#      Mon Oct 28 15:36:11 2013 +0530
# Node ID 3a3745d7052909c7b725cf7c97d91e089df30a33
# Parent  ef2428fd32feddd60168f3430c50f4d7e6f02741
rc: implement qp with Aq for each Cu before encoding them.

diff -r ef2428fd32fe -r 3a3745d70529 source/common/lowres.cpp
--- a/source/common/lowres.cpp	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/common/lowres.cpp	Mon Oct 28 15:36:11 2013 +0530
@@ -48,7 +48,8 @@
     if (*aqMode)
     {
         m_qpAqOffset = (double*)x265_malloc(sizeof(double) * cuCount);
-        if (!m_qpAqOffset)
+        m_invQscaleFactor = (int*)x265_malloc(sizeof(int) * cuCount);
+        if (!m_qpAqOffset || !m_invQscaleFactor)
             *aqMode = 0;
     }
 
@@ -110,6 +111,7 @@
         X265_FREE(lowresMvCosts[1][i]);
     }
     X265_FREE(m_qpAqOffset);
+    X265_FREE(m_invQscaleFactor);
 }
 
 // (re) initialize lowres state
@@ -125,7 +127,7 @@
     satdCost = -1;
     memset(costEst, -1, sizeof(costEst));
 
-    if (m_qpAqOffset)
+    if (m_qpAqOffset && m_invQscaleFactor)
         memset(costEstAq, -1, sizeof(costEstAq));
 
     for (int y = 0; y < bframes + 2; y++)
diff -r ef2428fd32fe -r 3a3745d70529 source/common/lowres.h
--- a/source/common/lowres.h	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/common/lowres.h	Mon Oct 28 15:36:11 2013 +0530
@@ -36,6 +36,7 @@
     /* lowres buffers, sizes and strides */
     pixel *buffer[4];
     double *m_qpAqOffset; // qp Aq offset values for each Cu
+    int *m_invQscaleFactor; // qScale values for qp Aq Offsets 
     int    width;     // width of lowres frame in pixels
     int    lines;     // height of lowres frame in pixel lines
     int    frameNum;  // Presentation frame number
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/frameencoder.cpp	Mon Oct 28 15:36:11 2013 +0530
@@ -1007,6 +1007,8 @@
         codeRow.m_entropyCoder.resetEntropy();
 
         TEncSbac *bufSbac = (m_cfg->param.bEnableWavefront && col == 0 && row > 0) ? &m_rows[row - 1].m_bufferSbacCoder : NULL;
+        int qp = calcQpForCu(m_pic, cuAddr);
+        cu->setQP(0,(char)qp);
         codeRow.processCU(cu, m_pic->getSlice(), bufSbac, m_cfg->param.bEnableWavefront && col == 1);
 
         // TODO: Keep atomic running totals for rate control?
@@ -1058,6 +1060,34 @@
     m_totalTime = m_totalTime + (x265_mdate() - startTime);
 }
 
+int FrameEncoder::calcQpForCu(TComPic *pic, UInt cuAddr)
+{
+    x265_emms();
+    double qp = pic->getSlice()->getSliceQp();
+    if (m_cfg->param.rc.aqMode)
+    {
+        /* Derive qpOffet for each CU by averaging offsets for all 16x16 blocks in the cu. */
+        double qp_offset = 0;
+        int blockSize = g_maxCUWidth >> 2;
+        int maxBlockCols = (pic->getPicYuvOrg()->getWidth() + (blockSize - 1)) / blockSize;
+        int maxBlockRows = (pic->getPicYuvOrg()->getHeight() + (blockSize - 1)) / blockSize;
+        int block_y = (cuAddr / pic->getPicSym()->getFrameWidthInCU()) * 4;
+        int block_x = (cuAddr * 4) - block_y * pic->getPicSym()->getFrameWidthInCU();
+        int cnt = 0;
+        for (int h = 0; h < 4 && block_y < maxBlockRows ; h++, block_y++)
+        {
+            for (int w = 0; w < 4 && (block_x + w) < maxBlockCols; w++)
+            {
+                qp_offset += pic->m_lowres.m_qpAqOffset[block_x + w + (block_y * maxBlockCols)];
+                cnt++;
+            }
+        }
+        qp_offset /= cnt;
+        qp += qp_offset;
+    }
+    return Clip3(MIN_QP, MAX_QP, (int)(qp + 0.5));
+}
+
 TComPic *FrameEncoder::getEncodedPicture(NALUnitEBSP **nalunits)
 {
     if (m_pic)
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/frameencoder.h	Mon Oct 28 15:36:11 2013 +0530
@@ -165,7 +165,7 @@
 protected:
 
     void determineSliceBounds();
-
+    int calcQpForCu(TComPic *pic, UInt cuAddr);
     Encoder*                 m_top;
     TEncCfg*                 m_cfg;
 
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/ratecontrol.cpp	Mon Oct 28 15:36:11 2013 +0530
@@ -74,34 +74,22 @@
         return acEnergyVar(primitives.var[LUMA_16x16](src, srcStride), 8);
 }
 
-/* Find the total AC energy of each CU in all planes */
-double RateControl::acEnergyCu(TComPic* pic, uint32_t cuAddr)
+/* Find the total AC energy of each block in all planes */
+double RateControl::acEnergyCu(TComPic* pic, UInt block_x, UInt block_y)
 {
     uint32_t var = 0;
     double avgQp = 0, strength = cfg->param.rc.aqStrength * 1.0397f;
-    pixel* srcLuma = pic->getPicYuvOrg()->getLumaAddr(cuAddr);
-    pixel* srcCb = pic->getPicYuvOrg()->getCbAddr(cuAddr);
-    pixel* srcCr = pic->getPicYuvOrg()->getCrAddr(cuAddr);
-    UInt blockWidth = g_maxCUWidth >> 2;
-    UInt blockHeight = g_maxCUHeight >> 2;
-    UInt frameStride = pic->getPicYuvOrg()->getStride();
-    UInt cStride = pic->getPicYuvOrg()->getCStride();
-
-    /* Calculate Qp offset for each 16x16 block in the CU and average them over entire CU */
-    for (UInt h = 0, cnt = 0; h < g_maxCUHeight; h += blockHeight)
-    {
-        for (UInt w = 0; w < g_maxCUWidth; w += blockWidth, cnt++)
-        {
-            UInt blockOffsetLuma = w + (h * frameStride);
-            UInt blockOffsetChroma = (w >> 1) + ((h >> 1) * cStride);
-            var = acEnergyPlane(srcLuma + blockOffsetLuma, frameStride, 0);
-            var += acEnergyPlane(srcCb + blockOffsetChroma, cStride, 1);
-            var += acEnergyPlane(srcCr + blockOffsetChroma, cStride, 1);
-            avgQp += strength * (X265_LOG2(X265_MAX(var, 1)) - (14.427f));
-        }
-    }
-
-    avgQp /= 16;
+    pixel* srcLuma = pic->getPicYuvOrg()->getLumaAddr() ;
+    pixel* srcCb = pic->getPicYuvOrg()->getCbAddr() ;
+    pixel* srcCr = pic->getPicYuvOrg()->getCrAddr();
+    int frameStride = pic->getPicYuvOrg()->getStride();
+    int cStride = pic->getPicYuvOrg()->getCStride();
+    UInt blockOffsetLuma = block_x + (block_y * frameStride);
+    UInt blockOffsetChroma = (block_x >> 1) + ((block_y >> 1) * cStride);
+    var = acEnergyPlane(srcLuma + blockOffsetLuma, frameStride, 0);
+    var += acEnergyPlane(srcCb + blockOffsetChroma, cStride, 1);
+    var += acEnergyPlane(srcCr + blockOffsetChroma, cStride, 1);
+    avgQp = strength * (X265_LOG2( X265_MAX(var, 1) ) - 14.427f);
     x265_emms();
     return avgQp;
 }
@@ -111,16 +99,21 @@
     /* Actual adaptive quantization */
     if (cfg->param.rc.aqMode)
     {
-        int maxRows = pic->getPicSym()->getFrameHeightInCU();
-        int maxCols = pic->getPicSym()->getFrameWidthInCU();
-        for (int cu_y = 0; cu_y < maxRows; cu_y++)
+        UInt blockWidth = g_maxCUWidth >> 2;
+        UInt blockHeight = g_maxCUHeight >> 2;
+        double qp_adj = 0;
+        int block_xy = 0;
+        int maxCol = pic->getPicYuvOrg()->getWidth();
+        int maxRow = pic->getPicYuvOrg()->getHeight();
+        /* Calculate Qp offset for each 16x16 block in the frame */
+         for (int block_y = 0; block_y < maxRow; block_y += blockHeight)
         {
-            for (int cu_x = 0; cu_x < maxCols; cu_x++)
+            for (int block_x = 0; block_x < maxCol; block_x += blockWidth)
             {
-                double qp_adj;
-                int cu_xy = maxCols * cu_y + cu_x;
-                qp_adj = acEnergyCu(pic, cu_xy);
-                pic->m_lowres.m_qpAqOffset[cu_xy] = qp_adj;
+                qp_adj = acEnergyCu(pic, block_x, block_y);
+                pic->m_lowres.m_qpAqOffset[block_xy] = qp_adj;
+                pic->m_lowres.m_invQscaleFactor[block_xy] = x265_exp2fix8(qp_adj);
+                block_xy++;
             }
         }
     }
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/ratecontrol.h	Mon Oct 28 15:36:11 2013 +0530
@@ -85,7 +85,7 @@
     double getQScale(RateControlEntry *rce, double rateFactor);
     double rateEstimateQscale(RateControlEntry *rce); // main logic for calculating QP based on ABR
     void accumPQpUpdate();
-    double acEnergyCu(TComPic* pic, uint32_t cuAddr);
+    double acEnergyCu(TComPic* pic, UInt block_x, UInt block_y);
 };
 }
 
diff -r ef2428fd32fe -r 3a3745d70529 source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp	Mon Oct 28 00:08:06 2013 -0500
+++ b/source/encoder/slicetype.cpp	Mon Oct 28 15:36:11 2013 +0530
@@ -483,8 +483,8 @@
         if (bFrameScoreCU)
         {
             costIntra += icost;
-            if (fenc->m_qpAqOffset)
-                costIntraAq += (icost * x265_exp2fix8(fenc->m_qpAqOffset[cuXY]) + 128) >> 8;
+            if (fenc->m_invQscaleFactor)
+                costIntraAq += (icost * fenc->m_invQscaleFactor[cuXY] + 128) >> 8;
         }
     }
     if (!bBidir)
@@ -505,7 +505,7 @@
         {
             costEst += bcost;
             if (fenc->m_qpAqOffset)
-                costEstAq += (bcost * x265_exp2fix8(fenc->m_qpAqOffset[cuXY]) + 128) >> 8;
+                costEstAq += (bcost * fenc->m_invQscaleFactor[cuXY] + 128) >> 8;
         }
     }
     fenc->lowresCosts[b - p0][p1 - b][cuXY] = (uint16_t)(X265_MIN(bcost, LOWRES_COST_MASK) | (listused << LOWRES_COST_SHIFT));


More information about the x265-devel mailing list