[x265] [PATCH 2 of 4] Reuse analysis info of low resolution for full resolution encoding

Tom Vaughan tom.vaughan at multicorewareinc.com
Fri Jun 9 04:42:05 CEST 2017


Yes.  This is an experimental feature, still in development.



*From:* x265-devel [mailto:x265-devel-bounces at videolan.org] *On Behalf
Of *Deepthi
Nandakumar
*Sent:* Thursday, June 8, 2017 9:21 AM
*To:* Development for x265
*Subject:* Re: [x265] [PATCH 2 of 4] Reuse analysis info of low resolution
for full resolution encoding



So, the general idea here is to reuse analysis data from lower resolution
encodes (save mode) for higher resolution encodes (load mode). The
compression efficiency loss here will always be higher, than, if you used
high-res analysis data for low-res encodes.



On Fri, Jun 2, 2017 at 10:58 PM, <kavitha at multicorewareinc.com> wrote:

# HG changeset patch
# User Kavitha Sampath <kavitha at multicorewareinc.com>
# Date 1495615463 -19800
#      Wed May 24 14:14:23 2017 +0530
# Node ID 802bb7ead1e0151a604bc293451c735990656162
# Parent  404253434d33e99955aac29480ee16b8e939a64c
Reuse analysis info of low resolution for full resolution encoding.

New CLI option --scale-factor is added. This option should be coupled
with analysis-mode, --refine-level 10. It specifies the factor
by which input video of save mode should be scaled down.
Currently only scale-factor 2 is supported.

diff -r 404253434d33 -r 802bb7ead1e0 source/common/cudata.cpp
--- a/source/common/cudata.cpp  Wed May 24 08:39:45 2017 +0530
+++ b/source/common/cudata.cpp  Wed May 24 14:14:23 2017 +0530
@@ -28,6 +28,7 @@
 #include "picyuv.h"
 #include "mv.h"
 #include "cudata.h"
+#define MAX_MV 1 << 14

 using namespace X265_NS;

@@ -1623,6 +1624,11 @@
                 dir |= (1 << list);
                 candMvField[count][list].mv = colmv;
                 candMvField[count][list].refIdx = refIdx;
+                if (m_encData->m_param->scaleFactor &&
m_encData->m_param->analysisMode == X265_ANALYSIS_SAVE && m_log2CUSize[0] <
4)
+                {
+                    MV dist(MAX_MV, MAX_MV);
+                    candMvField[count][list].mv = dist;
+                }
             }
         }

@@ -1783,7 +1789,13 @@
             int curRefPOC = m_slice->m_refPOCList[picList][refIdx];
             int curPOC = m_slice->m_poc;

-            pmv[numMvc++] = amvpCand[num++] =
scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC,
colPOC, colRefPOC);
+            if (m_encData->m_param->scaleFactor &&
m_encData->m_param->analysisMode == X265_ANALYSIS_SAVE && (m_log2CUSize[0]
< 4))
+            {
+                MV dist(MAX_MV, MAX_MV);
+                pmv[numMvc++] = amvpCand[num++] = dist;
+            }
+            else
+                pmv[numMvc++] = amvpCand[num++] =
scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC,
colPOC, colRefPOC);
         }
     }

diff -r 404253434d33 -r 802bb7ead1e0 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp       Wed May 24 08:39:45 2017 +0530
+++ b/source/encoder/analysis.cpp       Wed May 24 14:14:23 2017 +0530
@@ -2263,6 +2263,19 @@
                             mode.cu.m_mvd[list][pu.puAbsPartIdx] =
mode.cu.m_mv[list][pu.puAbsPartIdx] - mvp;
                         }
                     }
+                    else if(m_param->scaleFactor)
+                    {
+                        MVField candMvField[MRG_MAX_NUM_CANDS][2]; //
double length for mv of both lists
+                        uint8_t candDir[MRG_MAX_NUM_CANDS];
+                        mode.cu.getInterMergeCandidates(pu.puAbsPartIdx,
part, candMvField, candDir);
+                        mode.cu.m_mvpIdx[0][pu.puAbsPartIdx] =
interDataCTU->mvpIdx[0][cuIdx + part];
+                        uint8_t mvpIdx =
mode.cu.m_mvpIdx[0][pu.puAbsPartIdx];
+                        mode.cu.setPUInterDir(candDir[mvpIdx],
pu.puAbsPartIdx, part);
+                        mode.cu.setPUMv(0, candMvField[mvpIdx][0].mv,
pu.puAbsPartIdx, part);
+                        mode.cu.setPUMv(1, candMvField[mvpIdx][1].mv,
pu.puAbsPartIdx, part);
+                        mode.cu.setPURefIdx(0,
(int8_t)candMvField[mvpIdx][0].refIdx, pu.puAbsPartIdx, part);
+                        mode.cu.setPURefIdx(1,
(int8_t)candMvField[mvpIdx][1].refIdx, pu.puAbsPartIdx, part);
+                    }
                 }
                 motionCompensation(mode.cu, pu, mode.predYuv, true, (m_csp
!= X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400));
             }
diff -r 404253434d33 -r 802bb7ead1e0 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp        Wed May 24 08:39:45 2017 +0530
+++ b/source/encoder/encoder.cpp        Wed May 24 14:14:23 2017 +0530
@@ -2839,6 +2839,11 @@
     X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFile);
     X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFile);
     X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFile);
+    int scaledNumPartition = analysis->numPartitions;
+    int factor = 1 << m_param->scaleFactor;
+
+    if (m_param->scaleFactor)
+        analysis->numPartitions *= factor;

     /* Memory is allocated for inter and intra analysis data based on the
slicetype */
     allocAnalysis(analysis);
@@ -2862,12 +2867,31 @@
         for (uint32_t d = 0; d < depthBytes; d++)
         {
             int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
+            if (m_param->scaleFactor)
+            {
+                if (depthBuf[d] == 0)
+                    depthBuf[d] = 1;
+                if (partSizes[d] == SIZE_NxN)
+                    partSizes[d] = SIZE_2Nx2N;
+            }
             memset(&((analysis_intra_data
*)analysis->intraData)->depth[count], depthBuf[d], bytes);
             memset(&((analysis_intra_data
*)analysis->intraData)->chromaModes[count], modeBuf[d], bytes);
             memset(&((analysis_intra_data
*)analysis->intraData)->partSizes[count], partSizes[d], bytes);
             count += bytes;
         }
-        X265_FREAD(((analysis_intra_data *)analysis->intraData)->modes,
sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions,
m_analysisFile);
+
+        if (!m_param->scaleFactor)
+        {
+            X265_FREAD(((analysis_intra_data
*)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame *
analysis->numPartitions, m_analysisFile);
+        }
+        else
+        {
+            uint8_t *tempLumaBuf = X265_MALLOC(uint8_t,
analysis->numCUsInFrame * scaledNumPartition);
+            X265_FREAD(tempLumaBuf, sizeof(uint8_t),
analysis->numCUsInFrame * scaledNumPartition, m_analysisFile);
+            for (uint32_t ctu32Idx = 0, cnt = 0; ctu32Idx <
analysis->numCUsInFrame * scaledNumPartition; ctu32Idx++, cnt += factor)
+                memset(&((analysis_intra_data
*)analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);
+            X265_FREE(tempLumaBuf);
+        }
         X265_FREE(tempBuf);
         consumedBytes += frameRecordSize;
     }
@@ -2923,12 +2947,16 @@
         for (uint32_t d = 0; d < depthBytes; d++)
         {
             int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
+            if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA &&
depthBuf[d] == 0)
+                 depthBuf[d] = 1;
             memset(&((analysis_inter_data
*)analysis->interData)->depth[count], depthBuf[d], bytes);
             memset(&((analysis_inter_data
*)analysis->interData)->modes[count], modeBuf[d], bytes);
             if (m_param->analysisRefineLevel > 4)
             {
+                if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA &&
partSize[d] == SIZE_NxN)
+                     partSize[d] = SIZE_2Nx2N;
                 memset(&((analysis_inter_data
*)analysis->interData)->partSize[count], partSize[d], bytes);
-                int numPU = nbPartsTable[(int)partSize[d]];
+                int numPU = (modeBuf[d] == MODE_INTRA) ? 1 :
nbPartsTable[(int)partSize[d]];
                 for (int pu = 0; pu < numPU; pu++)
                 {
                     if (pu) d++;
@@ -2940,6 +2968,11 @@
                         {
                             ((analysis_inter_data
*)analysis->interData)->mvpIdx[i][count + pu] = mvpIdx[i][d];
                             ((analysis_inter_data
*)analysis->interData)->refIdx[i][count + pu] = refIdx[i][d];
+                            if (m_param->scaleFactor)
+                            {
+                                mv[i][d].x *=
(int16_t)m_param->scaleFactor;
+                                mv[i][d].y *=
(int16_t)m_param->scaleFactor;
+                            }
                             memcpy(&((analysis_inter_data
*)analysis->interData)->mv[i][count + pu], &mv[i][d], sizeof(MV));
                         }
                     }
@@ -2961,7 +2994,20 @@
                 X265_FREE(mv[i]);
             }
             if (bIntraInInter)
-                X265_FREAD(((analysis_intra_data
*)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame *
analysis->numPartitions, m_analysisFile);
+            {
+                if (!m_param->scaleFactor)
+                {
+                    X265_FREAD(((analysis_intra_data
*)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame *
analysis->numPartitions, m_analysisFile);
+                }
+                else
+                {
+                    uint8_t *tempLumaBuf = X265_MALLOC(uint8_t,
analysis->numCUsInFrame * scaledNumPartition);
+                    X265_FREAD(tempLumaBuf, sizeof(uint8_t),
analysis->numCUsInFrame * scaledNumPartition, m_analysisFile);
+                    for (uint32_t ctu32Idx = 0, cnt = 0; ctu32Idx <
analysis->numCUsInFrame * scaledNumPartition; ctu32Idx++, cnt += factor)
+                        memset(&((analysis_intra_data
*)analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);
+                    X265_FREE(tempLumaBuf);
+                }
+            }
         }
         else
             X265_FREAD(((analysis_inter_data *)analysis->interData)->ref,
sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU *
numDir, m_analysisFile);
@@ -3183,7 +3229,7 @@
                         interDataCTU->partSize[depthBytes] = partSize;

                         /* Store per PU data */
-                        uint32_t numPU = nbPartsTable[(int)partSize];
+                        uint32_t numPU = (predMode == MODE_INTRA) ? 1 :
nbPartsTable[(int)partSize];
                         for (uint32_t puIdx = 0; puIdx < numPU; puIdx++)
                         {
                             uint32_t puabsPartIdx =
ctu->getPUOffset(puIdx, absPartIdx) + absPartIdx;
diff -r 404253434d33 -r 802bb7ead1e0 source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp      Wed May 24 08:39:45 2017 +0530
+++ b/source/encoder/slicetype.cpp      Wed May 24 14:14:23 2017 +0530
@@ -893,7 +893,7 @@
     if (m_param->rc.cuTree && !m_param->rc.bStatRead)
         /* update row satds based on cutree offsets */
         curFrame->m_lowres.satdCost = frameCostRecalculate(frames, p0, p1,
b);
-    else if (m_param->analysisMode != X265_ANALYSIS_LOAD)
+    else if (m_param->analysisMode != X265_ANALYSIS_LOAD ||
m_param->scaleFactor)
     {
         if (m_param->rc.aqMode)
             curFrame->m_lowres.satdCost = curFrame->m_lowres.costEstAq[b -
p0][p1 - b];
_______________________________________________
x265-devel mailing list
x265-devel at videolan.org
https://mailman.videolan.org/listinfo/x265-devel





-- 

Deepthi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20170608/0e5da451/attachment-0001.html>


More information about the x265-devel mailing list