[x265] [PATCH] port emergency mode feature from x264

sagar at multicorewareinc.com sagar at multicorewareinc.com
Mon Jul 27 14:15:49 CEST 2015


# HG changeset patch
# User Sagar Kotecha <sagar at multicorewareinc.com>
# Date 1437997463 -19800
#      Mon Jul 27 17:14:23 2015 +0530
# Node ID b554b7cba38d66ade3feda62a40878f143737366
# Parent  b015514a93868e2dcf431d2e94b147861076a376
port emergency mode feature from x264

The emergency mode activates in vbv mode if frame qp > QP_MAX_SPEC

diff -r b015514a9386 -r b554b7cba38d source/common/quant.cpp
--- a/source/common/quant.cpp	Sun Jul 26 16:12:32 2015 +0530
+++ b/source/common/quant.cpp	Mon Jul 27 17:14:23 2015 +0530
@@ -447,13 +447,13 @@
             primitives.cu[sizeIdx].dct(m_fencShortBuf, m_fencDctCoeff, trSize);
         }
 
-        if (m_nr)
+        if (m_nr && m_nr->nrOffset)
         {
             /* denoise is not applied to intra residual, so DST can be ignored */
             int cat = sizeIdx + 4 * !isLuma + 8 * !isIntra;
             int numCoeff = 1 << (log2TrSize * 2);
-            primitives.denoiseDct(m_resiDctCoeff, m_nr->residualSum[cat], m_nr->offsetDenoise[cat], numCoeff);
-            m_nr->count[cat]++;
+            primitives.denoiseDct(m_resiDctCoeff, m_nr->nrResidualSum[cat], m_nr->nrOffset[cat], numCoeff);
+            m_nr->nrCount[cat]++;
         }
     }
 
diff -r b015514a9386 -r b554b7cba38d source/common/quant.h
--- a/source/common/quant.h	Sun Jul 26 16:12:32 2015 +0530
+++ b/source/common/quant.h	Mon Jul 27 17:14:23 2015 +0530
@@ -71,6 +71,14 @@
     uint16_t offsetDenoise[MAX_NUM_TR_CATEGORIES][MAX_NUM_TR_COEFFS];
     uint32_t residualSum[MAX_NUM_TR_CATEGORIES][MAX_NUM_TR_COEFFS];
     uint32_t count[MAX_NUM_TR_CATEGORIES];
+
+    uint16_t offsetEmergency[QP_MAX_MAX - QP_MAX_SPEC][MAX_NUM_TR_CATEGORIES][MAX_NUM_TR_COEFFS];
+    uint32_t residualSumEmergency[MAX_NUM_TR_CATEGORIES][MAX_NUM_TR_COEFFS];
+    uint32_t countEmergency[MAX_NUM_TR_CATEGORIES];
+
+    ALIGN_VAR_16(uint16_t, (*nrOffset)[MAX_NUM_TR_COEFFS]);
+    uint32_t (*nrResidualSum)[MAX_NUM_TR_COEFFS];
+    uint32_t *nrCount;
 };
 
 class Quant
diff -r b015514a9386 -r b554b7cba38d source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Sun Jul 26 16:12:32 2015 +0530
+++ b/source/encoder/encoder.cpp	Mon Jul 27 17:14:23 2015 +0530
@@ -198,7 +198,6 @@
         m_scalingList.setDefaultScalingList();
     else if (m_scalingList.parseScalingList(m_param->scalingLists))
         m_aborted = true;
-    m_scalingList.setupQuantMatrices();
 
     m_lookahead = new Lookahead(m_param, m_threadPool);
     if (m_numPools)
@@ -214,6 +213,77 @@
     initSPS(&m_sps);
     initPPS(&m_pps);
 
+    uint16_t offsetEmergency[QP_MAX_MAX - QP_MAX_SPEC][MAX_NUM_TR_CATEGORIES][MAX_NUM_TR_COEFFS];
+
+    if (m_param->rc.vbvBufferSize)
+    {
+        bool scalingEnabled = m_scalingList.m_bEnabled;
+        if (!scalingEnabled)
+        {
+            m_scalingList.setDefaultScalingList();
+            m_scalingList.setupQuantMatrices();
+        }
+        else
+            m_scalingList.setupQuantMatrices();
+
+        for (int q = 0; q < QP_MAX_MAX - QP_MAX_SPEC; q++)
+        {
+            for (int cat = 0; cat < MAX_NUM_TR_CATEGORIES; cat++)
+            {
+                uint16_t *nrOffset = offsetEmergency[q][cat];
+
+                int trSize = cat & 3;
+
+                int coefCount = 1 << ((trSize + 2) * 2);
+
+                /* Denoise chroma first then luma, then DC. */
+                int dcThreshold = (QP_MAX_MAX - QP_MAX_SPEC) * 2 / 3;
+                int lumaThreshold = (QP_MAX_MAX - QP_MAX_SPEC) * 2 / 3;
+                int chromaThreshold = 0;
+
+                int thresh = (cat < 4 || (cat >= 8 && cat < 12)) ? lumaThreshold : chromaThreshold;
+
+                double quantF = (double)(1ULL << (q / 6 + 16 + 8));
+
+                for (int i = 0; i < coefCount; i++)
+                {
+                    uint16_t max = (1 << (7 + X265_DEPTH)) - 1;
+                    /* True "emergency mode": remove all DCT coefficients */
+                    if (q == QP_MAX_MAX - QP_MAX_SPEC - 1)
+                    {
+                        nrOffset[i] = max;
+                        continue;
+                    }
+
+                    int iThresh = i == 0 ? dcThreshold : thresh;
+                    if (q < iThresh)
+                    {
+                        nrOffset[i] = 0;
+                        continue;
+                    }
+
+                    int numList = (cat >= 8) * 3 + ((int)!iThresh);
+
+                    double pos = (double)(q - iThresh + 1) / (QP_MAX_MAX - QP_MAX_SPEC - iThresh);
+                    double start = quantF / (m_scalingList.m_quantCoef[trSize][numList][QP_MAX_SPEC % 6][i]);
+
+                    // Formula chosen as an exponential scale to vaguely mimic the effects of a higher quantizer.
+                    double bias = (pow(2, pos * (QP_MAX_MAX - QP_MAX_SPEC)) * 0.003 - 0.003) * start;
+                    nrOffset[i] = (uint16_t)X265_MIN(bias + 0.5, max);
+                }
+            }
+        }
+
+        if (!scalingEnabled)
+        {
+            m_scalingList.m_bEnabled = false;
+            m_scalingList.m_bDataPresent = false;
+            m_scalingList.setupQuantMatrices();
+        }
+    }
+    else
+        m_scalingList.setupQuantMatrices();
+
     int numRows = (m_param->sourceHeight + g_maxCUSize - 1) / g_maxCUSize;
     int numCols = (m_param->sourceWidth  + g_maxCUSize - 1) / g_maxCUSize;
     for (int i = 0; i < m_param->frameNumThreads; i++)
@@ -223,6 +293,8 @@
             x265_log(m_param, X265_LOG_ERROR, "Unable to initialize frame encoder, aborting\n");
             m_aborted = true;
         }
+        if (m_frameEncoder[i]->m_nr && m_param->rc.vbvBufferSize)
+            memcpy(m_frameEncoder[i]->m_nr->offsetEmergency, offsetEmergency, sizeof(offsetEmergency));
     }
 
     for (int i = 0; i < m_param->frameNumThreads; i++)
diff -r b015514a9386 -r b554b7cba38d source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Sun Jul 26 16:12:32 2015 +0530
+++ b/source/encoder/frameencoder.cpp	Mon Jul 27 17:14:23 2015 +0530
@@ -135,7 +135,7 @@
         ok &= m_rce.picTimingSEI && m_rce.hrdTiming;
     }
 
-    if (m_param->noiseReductionIntra || m_param->noiseReductionInter)
+    if (m_param->noiseReductionIntra || m_param->noiseReductionInter || m_param->rc.vbvBufferSize)
         m_nr = X265_MALLOC(NoiseReduction, 1);
     if (m_nr)
         memset(m_nr, 0, sizeof(NoiseReduction));
@@ -250,6 +250,9 @@
             {
                 m_tld[i].analysis.initSearch(*m_param, m_top->m_scalingList);
                 m_tld[i].analysis.create(m_tld);
+                if (m_tld[i].analysis.m_quant.m_frameNr && m_param->rc.vbvBufferSize)
+                for (int tid = 0; tid < m_param->frameNumThreads; tid++)
+                    memcpy(m_tld[i].analysis.m_quant.m_frameNr[tid].offsetEmergency, m_nr->offsetEmergency, sizeof(m_nr->offsetEmergency));
             }
 
             for (int i = 0; i < m_pool->m_numProviders; i++)
@@ -361,11 +364,45 @@
         }
     }
 
+    int numTLD;
+    if (m_pool)
+        numTLD = m_param->bEnableWavefront ? m_pool->m_numWorkers : m_pool->m_numWorkers + m_pool->m_numProviders;
+    else
+        numTLD = 1;
+
     /* Get the QP for this frame from rate control. This call may block until
      * frames ahead of it in encode order have called rateControlEnd() */
     int qp = m_top->m_rateControl->rateControlStart(m_frame, &m_rce, m_top);
     m_rce.newQp = qp;
 
+    if (m_nr)
+    {
+        if (qp > QP_MAX_SPEC && m_frame->m_param->rc.vbvBufferSize)
+        {
+            for (int i = 0; i < numTLD; i++)
+            {
+                m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrOffset = m_tld[i].analysis.m_quant.m_frameNr[m_jpId].offsetEmergency[qp - QP_MAX_SPEC - 1];
+                m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrResidualSum = m_tld[i].analysis.m_quant.m_frameNr[m_jpId].residualSumEmergency;
+                m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrCount = m_tld[i].analysis.m_quant.m_frameNr[m_jpId].countEmergency;
+            }
+        }
+        else
+        {
+            if (m_param->noiseReductionIntra || m_param->noiseReductionInter)
+            {
+                for (int i = 0; i < numTLD; i++)
+                {
+                    m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrOffset = m_tld[i].analysis.m_quant.m_frameNr[m_jpId].offsetDenoise;
+                    m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrResidualSum = m_tld[i].analysis.m_quant.m_frameNr[m_jpId].residualSum;
+                    m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrCount = m_tld[i].analysis.m_quant.m_frameNr[m_jpId].count;
+                }
+            }
+            else
+            for (int i = 0; i < numTLD; i++)
+                m_tld[i].analysis.m_quant.m_frameNr[m_jpId].nrOffset = NULL;
+        }
+    }
+
     /* Clip slice QP to 0-51 spec range before encoding */
     slice->m_sliceQp = x265_clip3(-QP_BD_OFFSET, QP_MAX_SPEC, qp);
 
@@ -697,36 +734,35 @@
         }
     }
 
-    int numTLD;
-    if (m_pool)
-        numTLD = m_param->bEnableWavefront ? m_pool->m_numWorkers : m_pool->m_numWorkers + m_pool->m_numProviders;
-    else
-        numTLD = 1;
-
     if (m_nr)
     {
-        /* Accumulate NR statistics from all worker threads */
-        for (int i = 0; i < numTLD; i++)
+        bool nrEnabled = (m_rce.newQp < QP_MAX_SPEC) && (m_param->noiseReductionIntra || m_param->noiseReductionInter);
+
+        if (nrEnabled)
         {
-            NoiseReduction* nr = &m_tld[i].analysis.m_quant.m_frameNr[m_jpId];
-            for (int cat = 0; cat < MAX_NUM_TR_CATEGORIES; cat++)
+            /* Accumulate NR statistics from all worker threads */
+            for (int i = 0; i < numTLD; i++)
             {
-                for (int coeff = 0; coeff < MAX_NUM_TR_COEFFS; coeff++)
-                    m_nr->residualSum[cat][coeff] += nr->residualSum[cat][coeff];
-            
-                m_nr->count[cat] += nr->count[cat];
+                NoiseReduction* nr = &m_tld[i].analysis.m_quant.m_frameNr[m_jpId];
+                for (int cat = 0; cat < MAX_NUM_TR_CATEGORIES; cat++)
+                {
+                    for (int coeff = 0; coeff < MAX_NUM_TR_COEFFS; coeff++)
+                        m_nr->residualSum[cat][coeff] += nr->residualSum[cat][coeff];
+
+                    m_nr->count[cat] += nr->count[cat];
+                }
             }
-        }
 
-        noiseReductionUpdate();
+            noiseReductionUpdate();
 
-        /* Copy updated NR coefficients back to all worker threads */
-        for (int i = 0; i < numTLD; i++)
-        {
-            NoiseReduction* nr = &m_tld[i].analysis.m_quant.m_frameNr[m_jpId];
-            memcpy(nr->offsetDenoise, m_nr->offsetDenoise, sizeof(uint16_t) * MAX_NUM_TR_CATEGORIES * MAX_NUM_TR_COEFFS);
-            memset(nr->count, 0, sizeof(uint32_t) * MAX_NUM_TR_CATEGORIES);
-            memset(nr->residualSum, 0, sizeof(uint32_t) * MAX_NUM_TR_CATEGORIES * MAX_NUM_TR_COEFFS);
+            /* Copy updated NR coefficients back to all worker threads */
+            for (int i = 0; i < numTLD; i++)
+            {
+                NoiseReduction* nr = &m_tld[i].analysis.m_quant.m_frameNr[m_jpId];
+                memcpy(nr->offsetDenoise, m_nr->offsetDenoise, sizeof(uint16_t)* MAX_NUM_TR_CATEGORIES * MAX_NUM_TR_COEFFS);
+                memset(nr->count, 0, sizeof(uint32_t)* MAX_NUM_TR_CATEGORIES);
+                memset(nr->residualSum, 0, sizeof(uint32_t)* MAX_NUM_TR_CATEGORIES * MAX_NUM_TR_COEFFS);
+            }
         }
     }
 
diff -r b015514a9386 -r b554b7cba38d source/encoder/search.cpp
--- a/source/encoder/search.cpp	Sun Jul 26 16:12:32 2015 +0530
+++ b/source/encoder/search.cpp	Mon Jul 27 17:14:23 2015 +0530
@@ -80,7 +80,7 @@
     m_me.init(param.searchMethod, param.subpelRefine, param.internalCsp);
 
     bool ok = m_quant.init(param.rdoqLevel, param.psyRdoq, scalingList, m_entropyCoder);
-    if (m_param->noiseReductionIntra || m_param->noiseReductionInter)
+    if (m_param->noiseReductionIntra || m_param->noiseReductionInter || m_param->rc.vbvBufferSize)
         ok &= m_quant.allocNoiseReduction(param);
 
     ok &= Predict::allocBuffers(param.internalCsp); /* sets m_hChromaShift & m_vChromaShift */


More information about the x265-devel mailing list