changeset 4970:66659d4a7b31

no-rdo: refactor enodeResandCalcRDInterCU function Divide estimateBits and modeDecision inside the function. EstimateBits uses a pseudo encode. Bitstream changes with this patch for --rd 1.
author Deepthi Devaki <deepthidevaki@multicorewareinc.com>
date Fri, 08 Nov 2013 12:33:47 +0530
parents 74bed0a288f5
children 8487f675effa
files source/Lib/TLibEncoder/TEncSearch.cpp source/Lib/TLibEncoder/TEncSearch.h source/encoder/compress.cpp
diffstat 3 files changed, 153 insertions(+-), 3 deletions(-) [+]
line wrap: on
line diff
--- a/source/Lib/TLibEncoder/TEncSearch.cpp	Fri Nov 08 14:30:32 2013 -0600
+++ b/source/Lib/TLibEncoder/TEncSearch.cpp	Fri Nov 08 12:33:47 2013 +0530
@@ -2915,6 +2915,144 @@ void TEncSearch::encodeResAndCalcRdInter
     cu->setQPSubParts(qpBest, 0, cu->getDepth(0));
 }
 
+void TEncSearch::estimateRDInterCU(TComDataCU* cu, TComYuv* fencYuv, TComYuv* predYuv, TShortYUV* outResiYuv,
+                                   TShortYUV* outBestResiYuv, TComYuv* outReconYuv, bool /*bSkipRes*/, bool curUseRDOQ)
+{
+    uint32_t width  = cu->getWidth(0);
+    uint32_t height = cu->getHeight(0);
+
+    outResiYuv->subtract(fencYuv, predYuv, 0, width);
+
+    uint32_t zerobits = estimateZerobits(cu);
+    uint32_t zerodistortion = estimateZeroDist(cu, fencYuv, predYuv);
+    uint64_t zerocost = m_rdCost->calcRdCost(zerodistortion, zerobits);
+
+    uint32_t distortion = 0;
+    uint32_t bits = 0;
+    estimateBitsDist(cu, outResiYuv, bits, distortion, curUseRDOQ);
+    uint64_t cost = m_rdCost->calcRdCost(distortion, bits);
+
+    if (cu->isLosslessCoded(0))
+    {
+        zerocost = cost + 1;
+    }
+
+    if (zerocost < cost)
+    {
+        const uint32_t qpartnum = cu->getPic()->getNumPartInCU() >> (cu->getDepth(0) << 1);
+        ::memset(cu->getTransformIdx(), 0, qpartnum * sizeof(UChar));
+        ::memset(cu->getCbf(TEXT_LUMA), 0, qpartnum * sizeof(UChar));
+        ::memset(cu->getCbf(TEXT_CHROMA_U), 0, qpartnum * sizeof(UChar));
+        ::memset(cu->getCbf(TEXT_CHROMA_V), 0, qpartnum * sizeof(UChar));
+        ::memset(cu->getCoeffY(), 0, width * height * sizeof(TCoeff));
+        ::memset(cu->getCoeffCb(), 0, width * height * sizeof(TCoeff) >> 2);
+        ::memset(cu->getCoeffCr(), 0, width * height * sizeof(TCoeff) >> 2);
+        cu->setTransformSkipSubParts(0, 0, 0, 0, cu->getDepth(0));
+        if (cu->getMergeFlag(0) && cu->getPartitionSize(0) == SIZE_2Nx2N)
+        {
+            cu->setSkipFlagSubParts(true, 0, cu->getDepth(0));
+        }
+        bits = zerobits;
+        outBestResiYuv->clear();
+        generateRecon(cu, predYuv, outBestResiYuv, outReconYuv, true);
+    }
+    else
+    {
+        xSetResidualQTData(cu, 0, 0, outBestResiYuv, cu->getDepth(0), true);
+        generateRecon(cu, predYuv, outBestResiYuv, outReconYuv, false);
+    }
+
+    int part = partitionFromSizes(width, height);
+    distortion = primitives.sse_pp[part](fencYuv->getLumaAddr(), fencYuv->getStride(), outReconYuv->getLumaAddr(), outReconYuv->getStride());
+    part = partitionFromSizes(width >> 1, height >> 1);
+    distortion += m_rdCost->scaleChromaDistCb(primitives.sse_pp[part](fencYuv->getCbAddr(), fencYuv->getCStride(), outReconYuv->getCbAddr(), outReconYuv->getCStride()));
+    distortion += m_rdCost->scaleChromaDistCr(primitives.sse_pp[part](fencYuv->getCrAddr(), fencYuv->getCStride(), outReconYuv->getCrAddr(), outReconYuv->getCStride()));
+
+    cu->m_totalBits       = bits;
+    cu->m_totalDistortion = distortion;
+    cu->m_totalCost       = m_rdCost->calcRdCost(distortion, bits);
+}
+
+uint32_t TEncSearch::estimateZerobits(TComDataCU* cu)
+{
+    if (cu->isIntra(0))
+    {
+        return 0;
+    }
+
+    uint32_t zeroResiBits = 0;
+
+    uint32_t width  = cu->getWidth(0);
+    uint32_t height = cu->getHeight(0);
+
+    const uint32_t qpartnum = cu->getPic()->getNumPartInCU() >> (cu->getDepth(0) << 1);
+    ::memset(cu->getTransformIdx(), 0, qpartnum * sizeof(UChar));
+    ::memset(cu->getCbf(TEXT_LUMA), 0, qpartnum * sizeof(UChar));
+    ::memset(cu->getCbf(TEXT_CHROMA_U), 0, qpartnum * sizeof(UChar));
+    ::memset(cu->getCbf(TEXT_CHROMA_V), 0, qpartnum * sizeof(UChar));
+    ::memset(cu->getCoeffY(), 0, width * height * sizeof(TCoeff));
+    ::memset(cu->getCoeffCb(), 0, width * height * sizeof(TCoeff) >> 2);
+    ::memset(cu->getCoeffCr(), 0, width * height * sizeof(TCoeff) >> 2);
+    cu->setTransformSkipSubParts(0, 0, 0, 0, cu->getDepth(0));
+
+    m_rdGoOnSbacCoder->load(m_rdSbacCoders[cu->getDepth(0)][CI_CURR_BEST]);
+    zeroResiBits = xSymbolBitsInter(cu);
+    // Reset skipflags to false which would have set to true by xSymbolBitsInter if merge-skip
+    cu->setSkipFlagSubParts(false, 0, cu->getDepth(0));
+    return zeroResiBits;
+}
+
+uint32_t TEncSearch::estimateZeroDist(TComDataCU* cu, TComYuv* fencYuv, TComYuv* predYuv)
+{
+    uint32_t distortion = 0;
+
+    uint32_t width  = cu->getWidth(0);
+    uint32_t height = cu->getHeight(0);
+
+    int part = partitionFromSizes(width, height);
+
+    distortion = primitives.sse_pp[part](fencYuv->getLumaAddr(), fencYuv->getStride(), predYuv->getLumaAddr(), predYuv->getStride());
+    part = partitionFromSizes(width >> 1, height >> 1);
+    distortion += m_rdCost->scaleChromaDistCb(primitives.sse_pp[part](fencYuv->getCbAddr(), fencYuv->getCStride(), predYuv->getCbAddr(), predYuv->getCStride()));
+    distortion += m_rdCost->scaleChromaDistCr(primitives.sse_pp[part](fencYuv->getCrAddr(), fencYuv->getCStride(), predYuv->getCrAddr(), predYuv->getCStride()));
+    return distortion;
+}
+
+void TEncSearch::generateRecon(TComDataCU* cu, TComYuv* predYuv, TShortYUV* resiYuv, TComYuv* reconYuv, bool skipRes)
+{
+    if (skipRes)
+    {
+        predYuv->copyToPartYuv(reconYuv, 0);
+        return;
+    }
+    else
+    {
+        uint32_t width  = cu->getWidth(0);
+        xSetResidualQTData(cu, 0, 0, resiYuv, cu->getDepth(0), true);
+        reconYuv->addClip(predYuv, resiYuv, 0, width);
+    }
+}
+
+void TEncSearch::estimateBitsDist(TComDataCU* cu, TShortYUV* resiYuv, uint32_t& bits, uint32_t& distortion, bool curUseRDOQ)
+{
+    if (cu->isIntra(0))
+    {
+        return;
+    }
+
+    bits = 0;
+    distortion = 0;
+    uint64_t cost = 0;
+    uint32_t zeroDistortion = 0;
+    m_rdGoOnSbacCoder->load(m_rdSbacCoders[cu->getDepth(0)][CI_CURR_BEST]);
+    xEstimateResidualQT(cu, 0, 0, resiYuv, cu->getDepth(0), cost, bits, distortion, &zeroDistortion, curUseRDOQ);
+
+    xSetResidualQTData(cu, 0, 0, NULL, cu->getDepth(0), false);
+    m_rdGoOnSbacCoder->load(m_rdSbacCoders[cu->getDepth(0)][CI_CURR_BEST]);
+    bits = xSymbolBitsInter(cu);
+    m_rdGoOnSbacCoder->store(m_rdSbacCoders[cu->getDepth(0)][CI_TEMP_BEST]);
+}
+
 #if _MSC_VER
 #pragma warning(disable: 4701) // potentially uninitialized local variable
 #endif
--- a/source/Lib/TLibEncoder/TEncSearch.h	Fri Nov 08 14:30:32 2013 -0600
+++ b/source/Lib/TLibEncoder/TEncSearch.h	Fri Nov 08 12:33:47 2013 +0530
@@ -153,6 +153,17 @@ public:
     void encodeResAndCalcRdInterCU(TComDataCU* cu, TComYuv* fencYuv, TComYuv* predYuv, TShortYUV* resiYuv, TShortYUV* bestResiYuv,
                                    TComYuv* reconYuv, bool bSkipRes, bool curUseRDOQ = true);
 
+    void estimateRDInterCU(TComDataCU* cu, TComYuv* fencYuv, TComYuv* predYuv, TShortYUV* resiYuv, TShortYUV* bestResiYuv,
+                           TComYuv* reconYuv, bool bSkipRes, bool curUseRDOQ = true);
+
+    uint32_t estimateZerobits(TComDataCU* cu);
+
+    uint32_t estimateZeroDist(TComDataCU* cu, TComYuv* fencYuv, TComYuv* predYuv);
+
+    void generateRecon(TComDataCU* cu, TComYuv* predYuv, TShortYUV* resiYuv, TComYuv* reconYuv, bool skipRes);
+
+    void estimateBitsDist(TComDataCU* cu, TShortYUV* resiYuv, uint32_t& bits, uint32_t& distortion, bool curUseRDOQ);
+
     /// set ME search range
     void setAdaptiveSearchRange(int dir, int refIdx, int merange) { m_adaptiveRange[dir][refIdx] = merange; }
 
--- a/source/encoder/compress.cpp	Fri Nov 08 14:30:32 2013 -0600
+++ b/source/encoder/compress.cpp	Fri Nov 08 12:33:47 2013 +0530
@@ -319,7 +319,7 @@ void TEncCu::xComputeCostMerge2Nx2N(TCom
     m_tmpRecoYuv[depth] = yuv;
 
     //Encode with residue
-    m_search->encodeResAndCalcRdInterCU(outTempCU, m_origYuv[depth], bestPredYuv, m_tmpResiYuv[depth], m_bestResiYuv[depth], m_tmpRecoYuv[depth], false);
+    m_search->estimateRDInterCU(outTempCU, m_origYuv[depth], bestPredYuv, m_tmpResiYuv[depth], m_bestResiYuv[depth], m_tmpRecoYuv[depth], false);
 
     if (outTempCU->m_totalCost < outBestCU->m_totalCost)    //Choose best from no-residue mode and residue mode
     {
@@ -476,8 +476,9 @@ void TEncCu::xCompressInterCU(TComDataCU
                 m_search->motionCompensation(outBestCU, m_bestPredYuv[depth], REF_PIC_LIST_X, partIdx, false, true);
             }
 
-            m_search->encodeResAndCalcRdInterCU(outBestCU, m_origYuv[depth], m_bestPredYuv[depth], m_tmpResiYuv[depth],
-                                                m_bestResiYuv[depth], m_bestRecoYuv[depth], false);
+            m_search->estimateRDInterCU(outBestCU, m_origYuv[depth], m_bestPredYuv[depth], m_tmpResiYuv[depth],
+                                        m_bestResiYuv[depth], m_bestRecoYuv[depth], false);
+
 #if CU_STAT_LOGFILE
             fprintf(fp1, "\n N : %d ,  Best Inter : %d , ", outBestCU->getWidth(0) / 2, outBestCU->m_totalCost);
 #endif