# HG changeset patch
# User Steve Borho <[email protected]>
# 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;
_______________________________________________
x265-devel mailing list
[email protected]
https://mailman.videolan.org/listinfo/x265-devel