[x265] [X265][PATCH] Fix: Hang when vbv is used with slices

Niranjan Bala niranjan at multicorewareinc.com
Fri Jan 22 11:21:48 UTC 2021


>From 64a985847ecca1a6937fe1dae00d3db79cf0bcb2 Mon Sep 17 00:00:00 2001
From: Niranjan <niranjan at multicorewareinc.com>
Date: Fri, 22 Jan 2021 08:26:58 +0530
Subject: [PATCH] Fix: Hang when vbv is used with slices

---
 source/encoder/frameencoder.cpp | 30 ++++++++++++++++--------------
 source/encoder/frameencoder.h   |  4 ++--
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index 2086a15a5..efe85282f 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -47,8 +47,6 @@ FrameEncoder::FrameEncoder()
     m_slicetypeWaitTime = 0;
     m_activeWorkerCount = 0;
     m_completionCount = 0;
-    m_bAllRowsStop = false;
-    m_vbvResetTriggerRow = -1;
     m_outStreams = NULL;
     m_backupStreams = NULL;
     m_substreamSizes = NULL;
@@ -88,6 +86,8 @@ void FrameEncoder::destroy()
     delete[] m_outStreams;
     delete[] m_backupStreams;
     X265_FREE(m_sliceBaseRow);
+    X265_FREE((void*)m_bAllRowsStop);
+    X265_FREE((void*)m_vbvResetTriggerRow);
     X265_FREE(m_sliceMaxBlockRow);
     X265_FREE(m_cuGeoms);
     X265_FREE(m_ctuGeomMap);
@@ -118,6 +118,8 @@ bool FrameEncoder::init(Encoder *top, int numRows, int
numCols)
     bool ok = !!m_numRows;

     m_sliceBaseRow = X265_MALLOC(uint32_t, m_param->maxSlices + 1);
+    m_bAllRowsStop = X265_MALLOC(bool, m_param->maxSlices);
+    m_vbvResetTriggerRow = X265_MALLOC(int, m_param->maxSlices);
     ok &= !!m_sliceBaseRow;
     m_sliceGroupSize = (uint16_t)(m_numRows + m_param->maxSlices - 1) /
m_param->maxSlices;
     uint32_t sliceGroupSizeAccu = (m_numRows << 8) / m_param->maxSlices;

@@ -438,8 +440,8 @@ void FrameEncoder::compressFrame()
     m_stallStartTime = 0;

     m_completionCount = 0;
-    m_bAllRowsStop = false;
-    m_vbvResetTriggerRow = -1;
+    memset((void*)m_bAllRowsStop, 0, sizeof(bool) * m_param->maxSlices);
+    memset((void*)m_vbvResetTriggerRow, -1, sizeof(int) *
m_param->maxSlices);
     m_rowSliceTotalBits[0] = 0;
     m_rowSliceTotalBits[1] = 0;

@@ -1469,16 +1471,16 @@ void FrameEncoder::processRowEncoder(int intRow,
ThreadLocalData& tld)
                 curRow.bufferedEntropy.copyState(rowCoder);
                 curRow.bufferedEntropy.loadContexts(rowCoder);
             }
-            if (bFirstRowInSlice && m_vbvResetTriggerRow != intRow)

+            if (bFirstRowInSlice && m_vbvResetTriggerRow[curRow.sliceId]
!= intRow)
             {
                 curEncData.m_rowStat[row].rowQp = curEncData.m_avgQpRc;
                 curEncData.m_rowStat[row].rowQpScale =
x265_qp2qScale(curEncData.m_avgQpRc);
             }

             FrameData::RCStatCU& cuStat = curEncData.m_cuStat[cuAddr];
-            if (m_param->bEnableWavefront && rowInSlice >= col &&
!bFirstRowInSlice && m_vbvResetTriggerRow != intRow)
+            if (m_param->bEnableWavefront && rowInSlice >= col &&
!bFirstRowInSlice && m_vbvResetTriggerRow[curRow.sliceId] != intRow)
                 cuStat.baseQp = curEncData.m_cuStat[cuAddr - numCols +
1].baseQp;
-            else if (!m_param->bEnableWavefront && !bFirstRowInSlice &&
m_vbvResetTriggerRow != intRow)
+            else if (!m_param->bEnableWavefront && !bFirstRowInSlice &&
m_vbvResetTriggerRow[curRow.sliceId] != intRow)
                 cuStat.baseQp = curEncData.m_rowStat[row - 1].rowQp;
             else
                 cuStat.baseQp = curEncData.m_rowStat[row].rowQp;
@@ -1655,7 +1657,7 @@ void FrameEncoder::processRowEncoder(int intRow,
ThreadLocalData& tld)
                     x265_log(m_param, X265_LOG_DEBUG, "POC %d row %d -
encode restart required for VBV, to %.2f from %.2f\n",
                         m_frame->m_poc, row, qpBase,
curEncData.m_cuStat[cuAddr].baseQp);

-                    m_vbvResetTriggerRow = row;
+                    m_vbvResetTriggerRow[curRow.sliceId] = row;
                     m_outStreams[0].copyBits(&m_backupStreams[0]);

                     rowCoder.copyState(curRow.bufferedEntropy);
@@ -1707,8 +1709,8 @@ void FrameEncoder::processRowEncoder(int intRow,
ThreadLocalData& tld)
                              m_frame->m_poc, row, qpBase,
curEncData.m_cuStat[cuAddr].baseQp);

                     // prevent the WaveFront::findJob() method from
providing new jobs
-                    m_vbvResetTriggerRow = row;
-                    m_bAllRowsStop = true;
+                    m_vbvResetTriggerRow[curRow.sliceId] = row;
+                    m_bAllRowsStop[curRow.sliceId] = true;

                     for (uint32_t r = m_sliceBaseRow[sliceId + 1] - 1; r
>= row; r--)
                     {
@@ -1720,7 +1722,7 @@ void FrameEncoder::processRowEncoder(int intRow,
ThreadLocalData& tld)
                             stopRow.lock.acquire();
                             while (stopRow.active)
                             {
-                                if (dequeueRow(r * 2))
+                                if (dequeueRow(m_row_to_idx[r] * 2))
                                     stopRow.active = false;
                                 else
                                 {
@@ -1758,13 +1760,13 @@ void FrameEncoder::processRowEncoder(int intRow,
ThreadLocalData& tld)
                         curEncData.m_rowStat[r].sumQpAq = 0;
                     }

-                    m_bAllRowsStop = false;
+                    m_bAllRowsStop[curRow.sliceId] = false;
                 }
             }
         }

         if (m_param->bEnableWavefront && curRow.completed >= 2 &&
!bLastRowInSlice &&
-            (!m_bAllRowsStop || intRow + 1 < m_vbvResetTriggerRow))
+            (!m_bAllRowsStop[curRow.sliceId] || intRow + 1 <
m_vbvResetTriggerRow[curRow.sliceId]))
         {
             /* activate next row */
             ScopedLock below(m_rows[row + 1].lock);
@@ -1779,7 +1781,7 @@ void FrameEncoder::processRowEncoder(int intRow,
ThreadLocalData& tld)
         }

         ScopedLock self(curRow.lock);
-        if ((m_bAllRowsStop && intRow > m_vbvResetTriggerRow) ||
+        if ((m_bAllRowsStop[curRow.sliceId] && intRow >
m_vbvResetTriggerRow[curRow.sliceId]) ||
             (!bFirstRowInSlice && ((curRow.completed < numCols - 1) ||
(m_rows[row - 1].completed < numCols)) && m_rows[row - 1].completed <
curRow.completed + 2))
         {
             curRow.active = false;
diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h
index 668936872..f4cfc624d 100644
--- a/source/encoder/frameencoder.h
+++ b/source/encoder/frameencoder.h
@@ -140,9 +140,9 @@ public:
     int                      m_localTldIdx;
     bool                     m_reconfigure; /* reconfigure in progress */
     volatile bool            m_threadActive;
-    volatile bool            m_bAllRowsStop;
+    volatile bool            *m_bAllRowsStop;
     volatile int             m_completionCount;
-    volatile int             m_vbvResetTriggerRow;
+    volatile int             *m_vbvResetTriggerRow;
     volatile int             m_sliceCnt;

     uint32_t                 m_numRows;
-- 
2.18.0.windows.1


-- 

Thanks & Regards
*Niranjan Kumar B*
Video Codec Engineer
Media & AI Analytics
+91 958 511 1449
<https://multicorewareinc.com/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210122/bcec2a39/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Fix_hang_when_vbv_is_used_with_slices.diff
Type: application/octet-stream
Size: 7066 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210122/bcec2a39/attachment-0001.obj>


More information about the x265-devel mailing list