[x265] [PATCH] Enable PropagateCost assembly primitive

gopi.satykrishna at multicorewareinc.com gopi.satykrishna at multicorewareinc.com
Wed Aug 31 11:03:46 CEST 2016


# HG changeset patch
# User Gopi Satykrishna Akisetty <gopi.satykrishna at multicorewareinc.com>
# Date 1472623041 -19800
#      Wed Aug 31 11:27:21 2016 +0530
# Node ID 3c0561db9c3c0e7dd80e8df18813e2c88407378b
# Parent  9e624761d74e996f885efb7f6ba51b6a6c691482
Enable PropagateCost assembly primitive

diff -r 9e624761d74e -r 3c0561db9c3c source/common/lowres.cpp
--- a/source/common/lowres.cpp	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/common/lowres.cpp	Wed Aug 31 11:27:21 2016 +0530
@@ -60,6 +60,8 @@
         CHECKED_MALLOC(invQscaleFactor, int, cuCountFullRes);
         CHECKED_MALLOC(qpCuTreeOffset, double, cuCountFullRes);
         CHECKED_MALLOC(blockVariance, uint32_t, cuCountFullRes);
+        if (qgSize == 8)
+            CHECKED_MALLOC(invQscaleFactor8x8, int, cuCountFullRes);
     }
     CHECKED_MALLOC(propagateCost, uint16_t, cuCount);
 
@@ -129,6 +131,7 @@
     X265_FREE(qpCuTreeOffset);
     X265_FREE(propagateCost);
     X265_FREE(blockVariance);
+    X265_FREE(invQscaleFactor8x8);
 }
 
 // (re) initialize lowres state
diff -r 9e624761d74e -r 3c0561db9c3c source/common/lowres.h
--- a/source/common/lowres.h	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/common/lowres.h	Wed Aug 31 11:27:21 2016 +0530
@@ -145,6 +145,7 @@
     double*   qpAqOffset;      // AQ QP offset values for each 16x16 CU
     double*   qpCuTreeOffset;  // cuTree QP offset values for each 16x16 CU
     int*      invQscaleFactor; // qScale values for qp Aq Offsets
+    int*      invQscaleFactor8x8; // temporary buffer for qg-size 8
     uint32_t* blockVariance;
     uint64_t  wp_ssd[3];       // This is different than SSDY, this is sum(pixel^2) - sum(pixel)^2 for entire frame
     uint64_t  wp_sum[3];
diff -r 9e624761d74e -r 3c0561db9c3c source/common/pixel.cpp
--- a/source/common/pixel.cpp	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/common/pixel.cpp	Wed Aug 31 11:27:21 2016 +0530
@@ -845,58 +845,31 @@
 /* Estimate the total amount of influence on future quality that could be had if we
  * were to improve the reference samples used to inter predict any given CU. */
 static void estimateCUPropagateCost(int* dst, const uint16_t* propagateIn, const int32_t* intraCosts, const uint16_t* interCosts,
-                                    const int32_t* invQscales, const double* fpsFactor, int len, uint32_t qgSize)
+                                    const int32_t* invQscales, const double* fpsFactor, int len)
 {
     double fps = *fpsFactor / 256;  // range[0.01, 1.00]
-    if (qgSize == 8)
+    for (int i = 0; i < len; i++)
     {
-        for (int i = 0; i < len; i++)
-        {
-            int intraCost = intraCosts[i];
-            int interCost = X265_MIN(intraCosts[i], interCosts[i] & LOWRES_COST_MASK);
-            int invQscaleFactor = (invQscales[i * 2] + invQscales[i * 2 + 1] + invQscales[i * 2 + len * 2] + invQscales[i * 2 + len * 2 + 1]) / 4;
-            double propagateIntra = intraCost * invQscaleFactor; // Q16 x Q8.8 = Q24.8
-            double propagateAmount = (double)propagateIn[i] + propagateIntra * fps; // Q16.0 + Q24.8 x Q0.x = Q25.0
-            double propagateNum = (double)(intraCost - interCost); // Q32 - Q32 = Q33.0
+        int intraCost = intraCosts[i];
+        int interCost = X265_MIN(intraCosts[i], interCosts[i] & LOWRES_COST_MASK);
+        double propagateIntra = intraCost * invQscales[i]; // Q16 x Q8.8 = Q24.8
+        double propagateAmount = (double)propagateIn[i] + propagateIntra * fps; // Q16.0 + Q24.8 x Q0.x = Q25.0
+        double propagateNum = (double)(intraCost - interCost); // Q32 - Q32 = Q33.0
 
 #if 0
-            // algorithm that output match to asm
-            float intraRcp = (float)1.0f / intraCost;   // VC can't mapping this into RCPPS
-            float intraRcpError1 = (float)intraCost * (float)intraRcp;
-            intraRcpError1 *= (float)intraRcp;
-            float intraRcpError2 = intraRcp + intraRcp;
-            float propagateDenom = intraRcpError2 - intraRcpError1;
-            dst[i] = (int)(propagateAmount * propagateNum * (double)propagateDenom + 0.5);
+        // algorithm that output match to asm
+        float intraRcp = (float)1.0f / intraCost;   // VC can't mapping this into RCPPS
+        float intraRcpError1 = (float)intraCost * (float)intraRcp;
+        intraRcpError1 *= (float)intraRcp;
+        float intraRcpError2 = intraRcp + intraRcp;
+        float propagateDenom = intraRcpError2 - intraRcpError1;
+        dst[i] = (int)(propagateAmount * propagateNum * (double)propagateDenom + 0.5);
 #else
-            double propagateDenom = (double)intraCost;             // Q32
-            dst[i] = (int)(propagateAmount * propagateNum / propagateDenom + 0.5);
+        double propagateDenom = (double)intraCost;             // Q32
+        dst[i] = (int)(propagateAmount * propagateNum / propagateDenom + 0.5);
 #endif
         }
-    }
-    else
-    {
-        for (int i = 0; i < len; i++)
-        {
-            int intraCost = intraCosts[i];
-            int interCost = X265_MIN(intraCosts[i], interCosts[i] & LOWRES_COST_MASK);
-            double propagateIntra = intraCost * invQscales[i]; // Q16 x Q8.8 = Q24.8
-            double propagateAmount = (double)propagateIn[i] + propagateIntra * fps; // Q16.0 + Q24.8 x Q0.x = Q25.0
-            double propagateNum = (double)(intraCost - interCost); // Q32 - Q32 = Q33.0
-
-#if 0
-            // algorithm that output match to asm
-            float intraRcp = (float)1.0f / intraCost;   // VC can't mapping this into RCPPS
-            float intraRcpError1 = (float)intraCost * (float)intraRcp;
-            intraRcpError1 *= (float)intraRcp;
-            float intraRcpError2 = intraRcp + intraRcp;
-            float propagateDenom = intraRcpError2 - intraRcpError1;
-            dst[i] = (int)(propagateAmount * propagateNum * (double)propagateDenom + 0.5);
-#else
-            double propagateDenom = (double)intraCost;             // Q32
-            dst[i] = (int)(propagateAmount * propagateNum / propagateDenom + 0.5);
-#endif
-        }
-    }
+    //}
 }
 
 /* Conversion between double and Q8.8 fixed point (big-endian) for storage */
diff -r 9e624761d74e -r 3c0561db9c3c source/common/primitives.h
--- a/source/common/primitives.h	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/common/primitives.h	Wed Aug 31 11:27:21 2016 +0530
@@ -187,7 +187,7 @@
 typedef void (*planecopy_sp_t) (const uint16_t* src, intptr_t srcStride, pixel* dst, intptr_t dstStride, int width, int height, int shift, uint16_t mask);
 typedef pixel (*planeClipAndMax_t)(pixel *src, intptr_t stride, int width, int height, uint64_t *outsum, const pixel minPix, const pixel maxPix);
 
-typedef void (*cutree_propagate_cost) (int* dst, const uint16_t* propagateIn, const int32_t* intraCosts, const uint16_t* interCosts, const int32_t* invQscales, const double* fpsFactor, int len, uint32_t qgSize);
+typedef void (*cutree_propagate_cost) (int* dst, const uint16_t* propagateIn, const int32_t* intraCosts, const uint16_t* interCosts, const int32_t* invQscales, const double* fpsFactor, int len);
 
 typedef void (*cutree_fix8_unpack)(double *dst, uint16_t *src, int count);
 typedef void (*cutree_fix8_pack)(uint16_t *dst, double *src, int count);
diff -r 9e624761d74e -r 3c0561db9c3c source/common/x86/asm-primitives.cpp
--- a/source/common/x86/asm-primitives.cpp	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/common/x86/asm-primitives.cpp	Wed Aug 31 11:27:21 2016 +0530
@@ -1027,7 +1027,7 @@
         ALL_CHROMA_444_PU(p2s, filterPixelToShort, sse2);
         ALL_LUMA_PU(convert_p2s, filterPixelToShort, sse2);
         ALL_LUMA_TU(count_nonzero, count_nonzero, sse2);
-        //p.propagateCost = PFX(mbtree_propagate_cost_sse2);
+        p.propagateCost = PFX(mbtree_propagate_cost_sse2);
     }
     if (cpuMask & X265_CPU_SSE3)
     {
@@ -1312,7 +1312,7 @@
         p.pu[LUMA_64x32].copy_pp = (copy_pp_t)PFX(blockcopy_ss_64x32_avx);
         p.pu[LUMA_64x48].copy_pp = (copy_pp_t)PFX(blockcopy_ss_64x48_avx);
         p.pu[LUMA_64x64].copy_pp = (copy_pp_t)PFX(blockcopy_ss_64x64_avx);
-        //p.propagateCost = PFX(mbtree_propagate_cost_avx);
+        p.propagateCost = PFX(mbtree_propagate_cost_avx);
     }
     if (cpuMask & X265_CPU_XOP)
     {
@@ -2153,7 +2153,7 @@
         p.chroma[X265_CSP_I444].pu[LUMA_64x64].filter_vsp = PFX(interp_4tap_vert_sp_64x64_avx2);
 
         p.frameInitLowres = PFX(frame_init_lowres_core_avx2);
-        //p.propagateCost = PFX(mbtree_propagate_cost_avx2);
+        p.propagateCost = PFX(mbtree_propagate_cost_avx2);
         p.fix8Unpack = PFX(cutree_fix8_unpack_avx2);
         p.fix8Pack = PFX(cutree_fix8_pack_avx2);
 
@@ -2356,7 +2356,7 @@
         ALL_CHROMA_444_PU(p2s, filterPixelToShort, sse2);
         ALL_LUMA_PU(convert_p2s, filterPixelToShort, sse2);
         ALL_LUMA_TU(count_nonzero, count_nonzero, sse2);
-        //p.propagateCost = PFX(mbtree_propagate_cost_sse2);
+        p.propagateCost = PFX(mbtree_propagate_cost_sse2);
     }
     if (cpuMask & X265_CPU_SSE3)
     {
@@ -2670,7 +2670,7 @@
         p.pu[LUMA_48x64].copy_pp = PFX(blockcopy_pp_48x64_avx);
 
         p.frameInitLowres = PFX(frame_init_lowres_core_avx);
-        //p.propagateCost = PFX(mbtree_propagate_cost_avx);
+        p.propagateCost = PFX(mbtree_propagate_cost_avx);
     }
     if (cpuMask & X265_CPU_XOP)
     {
@@ -3666,7 +3666,7 @@
         p.chroma[X265_CSP_I444].pu[LUMA_64x16].filter_vpp = PFX(interp_4tap_vert_pp_64x16_avx2);
 
         p.frameInitLowres = PFX(frame_init_lowres_core_avx2);
-        //p.propagateCost = PFX(mbtree_propagate_cost_avx2);
+        p.propagateCost = PFX(mbtree_propagate_cost_avx2);
         p.saoCuStatsE0 = PFX(saoCuStatsE0_avx2);
         p.saoCuStatsE1 = PFX(saoCuStatsE1_avx2);
         p.saoCuStatsE2 = PFX(saoCuStatsE2_avx2);
diff -r 9e624761d74e -r 3c0561db9c3c source/common/x86/mc-a2.asm
--- a/source/common/x86/mc-a2.asm	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/common/x86/mc-a2.asm	Wed Aug 31 11:27:21 2016 +0530
@@ -994,7 +994,7 @@
 
 ;-----------------------------------------------------------------------------
 ; void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, int32_t *intra_costs,
-;                             uint16_t *inter_costs, int32_t *inv_qscales, double *fps_factor, int len, uint32_t qgSize)
+;                             uint16_t *inter_costs, int32_t *inv_qscales, double *fps_factor, int len )
 ;-----------------------------------------------------------------------------
 INIT_XMM sse2
 cglobal mbtree_propagate_cost, 7,7,7
diff -r 9e624761d74e -r 3c0561db9c3c source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/encoder/slicetype.cpp	Wed Aug 31 11:27:21 2016 +0530
@@ -237,6 +237,21 @@
         }
     }
 
+    if (param->rc.qgSize == 8)
+    {
+        for (int cuY = 0; cuY < heightInCU; cuY++)
+        {
+            for (int cuX = 0; cuX < widthInCU; cuX++)
+            {
+                const int cuXY = cuX + cuY * widthInCU;
+                curFrame->m_lowres.invQscaleFactor8x8[cuXY] = (curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4] +
+                                                               curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + 1] +
+                                                               curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + curFrame->m_lowres.maxBlocksInRowFullRes] +
+                                                               curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + curFrame->m_lowres.maxBlocksInRowFullRes + 1]) / 4;
+            }
+        }
+    }
+
     if (param->bEnableWeightedPred || param->bEnableWeightedBiPred)
     {
         int hShift = CHROMA_H_SHIFT(param->internalCsp);
@@ -347,15 +362,9 @@
             frame cost estimates, they are not very accurate */
             const bool bFrameScoreCU = (cuX > 0 && cuX < widthInCU - 1 &&
                                         cuY > 0 && cuY < heightInCU - 1) || widthInCU <= 2 || heightInCU <= 2;
-            int invQscaleFactor, icostAq;
+            int icostAq;
             if (qgSize == 8)
-            {
-                invQscaleFactor = (fenc.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4] +
-                                   fenc.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + 1] +
-                                   fenc.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + fenc.maxBlocksInRowFullRes] +
-                                   fenc.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + fenc.maxBlocksInRowFullRes + 1]) / 4;
-                icostAq = (bFrameScoreCU && fenc.invQscaleFactor) ? ((icost * invQscaleFactor + 128) >> 8) : icost;
-            }
+                icostAq = (bFrameScoreCU && fenc.invQscaleFactor) ? ((icost * fenc.invQscaleFactor8x8[cuXY] + 128) >> 8) : icost;
             else
                 icostAq = (bFrameScoreCU && fenc.invQscaleFactor) ? ((icost * fenc.invQscaleFactor[cuXY] +128) >> 8) : icost;
 
@@ -1816,11 +1825,11 @@
         if (m_param->rc.qgSize == 8)
             primitives.propagateCost(m_scratch, propagateCost,
                        frames[b]->intraCost + cuIndex, frames[b]->lowresCosts[b - p0][p1 - b] + cuIndex,
-                       frames[b]->invQscaleFactor + (cuIndex * 4), &fpsFactor, m_8x8Width, m_param->rc.qgSize);
+                       frames[b]->invQscaleFactor8x8 + cuIndex, &fpsFactor, m_8x8Width);
         else
             primitives.propagateCost(m_scratch, propagateCost,
                        frames[b]->intraCost + cuIndex, frames[b]->lowresCosts[b - p0][p1 - b] + cuIndex,
-                       frames[b]->invQscaleFactor + cuIndex, &fpsFactor, m_8x8Width, m_param->rc.qgSize);
+                       frames[b]->invQscaleFactor + cuIndex, &fpsFactor, m_8x8Width);
 
         if (referenced)
             propagateCost += m_8x8Width;
@@ -1913,12 +1922,7 @@
             for (int cuX = 0; cuX < m_8x8Width; cuX++)
             {
                 const int cuXY = cuX + cuY * m_8x8Width;
-                int invQscaleFactor = (frame->invQscaleFactor[cuX * 2 + cuY * m_8x8Width * 4] +
-                                       frame->invQscaleFactor[cuX * 2 + cuY * m_8x8Width * 4 + 1] +
-                                       frame->invQscaleFactor[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] +
-                                       frame->invQscaleFactor[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1]) / 4;
-
-                int intracost = ((frame->intraCost[cuXY]) / 4 * invQscaleFactor + 128) >> 8;
+                int intracost = ((frame->intraCost[cuXY]) / 4 * frame->invQscaleFactor8x8[cuXY] + 128) >> 8;
                 if (intracost)
                 {
                     int propagateCost = ((frame->propagateCost[cuXY]) / 4 * fpsFactor + 128) >> 8;
@@ -1928,7 +1932,6 @@
                     frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes] - m_cuTreeStrength * (log2_ratio);
                     frame->qpCuTreeOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] = frame->qpAqOffset[cuX * 2 + cuY * m_8x8Width * 4 + frame->maxBlocksInRowFullRes + 1] - m_cuTreeStrength * (log2_ratio);
                 }
-
             }
         }
     }
@@ -2292,15 +2295,9 @@
     /* do not include edge blocks in the frame cost estimates, they are not very accurate */
     const bool bFrameScoreCU = (cuX > 0 && cuX < widthInCU - 1 &&
                                 cuY > 0 && cuY < heightInCU - 1) || widthInCU <= 2 || heightInCU <= 2;
-    int invQscaleFactor, bcostAq;
+    int bcostAq;
     if (m_lookahead.m_param->rc.qgSize == 8)
-    {
-        invQscaleFactor = (fenc->invQscaleFactor[cuX * 2 + cuY * widthInCU * 4] +
-                           fenc->invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + 1] +
-                           fenc->invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + fenc->maxBlocksInRowFullRes] +
-                           fenc->invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + fenc->maxBlocksInRowFullRes + 1]) / 4;
-        bcostAq = (bFrameScoreCU && fenc->invQscaleFactor) ? ((bcost * invQscaleFactor + 128) >> 8) : bcost;
-    }
+        bcostAq = (bFrameScoreCU && fenc->invQscaleFactor) ? ((bcost * fenc->invQscaleFactor8x8[cuXY] + 128) >> 8) : bcost;
     else
         bcostAq = (bFrameScoreCU && fenc->invQscaleFactor) ? ((bcost * fenc->invQscaleFactor[cuXY] +128) >> 8) : bcost;
 
diff -r 9e624761d74e -r 3c0561db9c3c source/test/pixelharness.cpp
--- a/source/test/pixelharness.cpp	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/test/pixelharness.cpp	Wed Aug 31 11:27:21 2016 +0530
@@ -1387,8 +1387,8 @@
     {
         int width = 16 + rand() % 64;
         int index = i % TEST_CASES;
-        checked(opt, opt_dest, ushort_test_buff[index] + j, int_test_buff[index] + j, ushort_test_buff[index] + j, int_test_buff[index] + j, &fps, width, 32);
-        ref(ref_dest, ushort_test_buff[index] + j, int_test_buff[index] + j, ushort_test_buff[index] + j, int_test_buff[index] + j, &fps, width, 32);
+        checked(opt, opt_dest, ushort_test_buff[index] + j, int_test_buff[index] + j, ushort_test_buff[index] + j, int_test_buff[index] + j, &fps, width);
+        ref(ref_dest, ushort_test_buff[index] + j, int_test_buff[index] + j, ushort_test_buff[index] + j, int_test_buff[index] + j, &fps, width);
 
         if (memcmp(ref_dest, opt_dest, 64 * 64 * sizeof(pixel)))
             return false;
@@ -3102,7 +3102,7 @@
     if (opt.propagateCost)
     {
         HEADER0("propagateCost");
-        REPORT_SPEEDUP(opt.propagateCost, ref.propagateCost, ibuf1, ushort_test_buff[0], int_test_buff[0], ushort_test_buff[0], int_test_buff[0], double_test_buff[0], 80, 32);
+        REPORT_SPEEDUP(opt.propagateCost, ref.propagateCost, ibuf1, ushort_test_buff[0], int_test_buff[0], ushort_test_buff[0], int_test_buff[0], double_test_buff[0], 80);
     }
 
     if (opt.fix8Pack)
diff -r 9e624761d74e -r 3c0561db9c3c source/x265.h
--- a/source/x265.h	Mon Aug 29 13:49:09 2016 +0530
+++ b/source/x265.h	Wed Aug 31 11:27:21 2016 +0530
@@ -263,8 +263,8 @@
     /* An array of quantizer offsets to be applied to this image during encoding.
      * These are added on top of the decisions made by rateControl.
      * Adaptive quantization must be enabled to use this feature. These quantizer
-     * offsets should be given for each 16x16 block. Behavior if quant
-     * offsets differ between encoding passes is undefined. */
+     * offsets should be given for each 16x16 block (8x8 block, when qg-size is 8).
+     * Behavior if quant offsets differ between encoding passes is undefined. */
     float            *quantOffsets;
 
     /* Frame level statistics */


More information about the x265-devel mailing list