[x265] [PATCH] encoder: refactor frame encoder recon row synchronization
Steve Borho
steve at borho.org
Tue Jan 28 07:30:35 CET 2014
# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1390889848 21600
# Tue Jan 28 00:17:28 2014 -0600
# Branch stable
# Node ID 55953908a310e9a1a556f3ec90fa934c5569dd60
# Parent dd0ef09680fe454b90000c24098d904042605bc9
encoder: refactor frame encoder recon row synchronization
The previous approach depended on a common event (owned by TComPic) being
triggered multiple times for each row, one trigger per referencing frame, but I
believe this was fragile as one frame encoder could steal notifications from
another.
In the new scheme, each frame encoder waits on its own sync event when it blocks
for recon pixels. When a frame encoder finishes reconstructing a CU row, it
calls a top-level encoder function which determines if any frame encoders are
blocked on that POC and wakes them up.
This should prevent deadlocks from frame encoder synchronization
diff -r dd0ef09680fe -r 55953908a310 source/Lib/TLibCommon/TComPic.h
--- a/source/Lib/TLibCommon/TComPic.h Tue Jan 28 07:44:07 2014 +0530
+++ b/source/Lib/TLibCommon/TComPic.h Tue Jan 28 00:17:28 2014 -0600
@@ -79,7 +79,6 @@
//** Frame Parallelism - notification between FrameEncoders of available motion reference rows **
volatile uint32_t m_reconRowCount; // count of CTU rows completely reconstructed and extended for motion reference
volatile uint32_t m_countRefEncoders; // count of FrameEncoder threads monitoring m_reconRowCount
- Event m_reconRowWait; // event triggered m_countRefEncoders times each time a recon row is completed
void* m_userData; // user provided pointer passed in with this picture
int64_t m_pts; // user provided presentation time stamp
diff -r dd0ef09680fe -r 55953908a310 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Tue Jan 28 07:44:07 2014 +0530
+++ b/source/encoder/encoder.cpp Tue Jan 28 00:17:28 2014 -0600
@@ -185,6 +185,20 @@
m_encodeStartTime = x265_mdate();
}
+/* Called when a frame encoder has completed a CTU row of reconstructed
+ * pixels and extended them; making them available for use as reference.
+ * It calls this function with its POC, so the top encoder may waken any
+ * other frame encoders that were waiting for a row of recon pixels from
+ * this picture */
+void Encoder::signalReconRowCompleted(int poc)
+{
+ for (int i = 0; i < param.frameNumThreads; i++)
+ {
+ if (m_frameEncoder[i].m_blockRefPOC == poc)
+ m_frameEncoder[i].m_reconRowWait.trigger();
+ }
+}
+
int Encoder::getStreamHeaders(NALUnitEBSP **nalunits)
{
return m_frameEncoder->getStreamHeaders(nalunits);
diff -r dd0ef09680fe -r 55953908a310 source/encoder/encoder.h
--- a/source/encoder/encoder.h Tue Jan 28 07:44:07 2014 +0530
+++ b/source/encoder/encoder.h Tue Jan 28 00:17:28 2014 -0600
@@ -136,6 +136,8 @@
void updateVbvPlan(RateControl* rc);
+ void signalReconRowCompleted(int poc);
+
protected:
uint64_t calculateHashAndPSNR(TComPic* pic, NALUnitEBSP **nalunits); // Returns total number of bits for encoded pic
diff -r dd0ef09680fe -r 55953908a310 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Tue Jan 28 07:44:07 2014 +0530
+++ b/source/encoder/frameencoder.cpp Tue Jan 28 00:17:28 2014 -0600
@@ -55,6 +55,7 @@
m_nalList[i] = NULL;
}
+ m_blockRefPOC = -1;
m_nalCount = 0;
m_totalTime = 0;
memset(&m_rce, 0, sizeof(RateControlEntry));
@@ -967,9 +968,14 @@
for (int ref = 0; ref < slice->getNumRefIdx(l); ref++)
{
TComPic *refpic = slice->getRefPic(l, ref);
- while ((refpic->m_reconRowCount != (uint32_t)m_numRows) && (refpic->m_reconRowCount < row + refLagRows))
+
+ /* indicate which reference picture we might wait for,
+ * prior to checking recon row count */
+ m_blockRefPOC = refpic->getPOC();
+ while ((refpic->m_reconRowCount != (uint32_t)m_numRows) &&
+ (refpic->m_reconRowCount < row + refLagRows))
{
- refpic->m_reconRowWait.wait();
+ m_reconRowWait.wait();
}
if (slice->getPPS()->getUseWP() && slice->getSliceType() == P_SLICE && m_mref[l][ref].isWeighted)
@@ -1004,9 +1010,14 @@
for (int ref = 0; ref < slice->getNumRefIdx(list); ref++)
{
TComPic *refpic = slice->getRefPic(list, ref);
- while ((refpic->m_reconRowCount != (uint32_t)m_numRows) && (refpic->m_reconRowCount < i + refLagRows))
+
+ /* indicate which reference picture we might wait for,
+ * prior to checking recon row count */
+ m_blockRefPOC = refpic->getPOC();
+ while ((refpic->m_reconRowCount != (uint32_t)m_numRows) &&
+ (refpic->m_reconRowCount < i + refLagRows))
{
- refpic->m_reconRowWait.wait();
+ m_reconRowWait.wait();
}
if (slice->getPPS()->getUseWP() && slice->getSliceType() == P_SLICE && m_mref[l][ref].isWeighted)
diff -r dd0ef09680fe -r 55953908a310 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h Tue Jan 28 07:44:07 2014 +0530
+++ b/source/encoder/frameencoder.h Tue Jan 28 00:17:28 2014 -0600
@@ -113,6 +113,10 @@
}
}
+ int m_blockRefPOC;
+
+ Event m_reconRowWait;
+
TEncEntropy* getEntropyCoder(int row) { return &this->m_rows[row].m_entropyCoder; }
TEncSbac* getSbacCoder(int row) { return &this->m_rows[row].m_sbacCoder; }
diff -r dd0ef09680fe -r 55953908a310 source/encoder/framefilter.cpp
--- a/source/encoder/framefilter.cpp Tue Jan 28 07:44:07 2014 +0530
+++ b/source/encoder/framefilter.cpp Tue Jan 28 00:17:28 2014 -0600
@@ -61,6 +61,7 @@
void FrameFilter::init(Encoder *top, int numRows, TEncSbac* rdGoOnSbacCoder)
{
+ m_top = top;
m_cfg = top;
m_numRows = numRows;
@@ -269,10 +270,8 @@
// Notify other FrameEncoders that this row of reconstructed pixels is available
m_pic->m_reconRowCount++;
- for (uint32_t i = 0; i < m_pic->m_countRefEncoders; i++)
- {
- m_pic->m_reconRowWait.trigger();
- }
+ if (m_pic->m_countRefEncoders)
+ m_top->signalReconRowCompleted(m_pic->getPOC());
int cuAddr = lineStartCUAddr;
if (m_cfg->param.bEnablePsnr)
diff -r dd0ef09680fe -r 55953908a310 source/encoder/framefilter.h
--- a/source/encoder/framefilter.h Tue Jan 28 07:44:07 2014 +0530
+++ b/source/encoder/framefilter.h Tue Jan 28 00:17:28 2014 -0600
@@ -56,6 +56,7 @@
protected:
+ Encoder* m_top;
TEncCfg* m_cfg;
TComPic* m_pic;
More information about the x265-devel
mailing list