<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Sep 6, 2014 at 10:08 PM, Steve Borho <span dir="ltr"><<a href="mailto:steve@borho.org" target="_blank">steve@borho.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Steve Borho <<a href="mailto:steve@borho.org">steve@borho.org</a>><br>
# Date 1409932577 -7200<br>
# Fri Sep 05 17:56:17 2014 +0200<br>
# Node ID 07d69bce1760a28be1b1ee1821dfeb3335602422<br>
# Parent 795878af39730deb24e2ee0e585c625084bb031b<br>
frameencoder: remove second encodeCU() pass over CTUs when SAO is disabled<br>
<br>
This is a performance optimization, it allows the encoder to generate the final<br>
bitstream of each CTU as it is compressed and cache hot.<br>
<br>
When SAO is enabled, SAO analysis must be performed and coded at the start of<br>
the CTU but SAO analysis currently requires surrounding CTUs to be encoded<br>
making the second pass unavoidable.<br>
<br>
diff -r 795878af3973 -r 07d69bce1760 source/encoder/frameencoder.cpp<br>
--- a/source/encoder/frameencoder.cpp Fri Sep 05 16:03:44 2014 +0200<br>
+++ b/source/encoder/frameencoder.cpp Fri Sep 05 17:56:17 2014 +0200<br>
@@ -192,16 +192,6 @@<br>
}<br>
}<br>
<br>
- uint32_t numSubstreams = m_param->bEnableWavefront ? m_frame->getPicSym()->getFrameHeightInCU() : 1;<br>
- if (!m_outStreams)<br>
- {<br>
- m_outStreams = new Bitstream[numSubstreams];<br>
- m_substreamSizes = X265_MALLOC(uint32_t, numSubstreams);<br>
- }<br>
- else<br>
- for (uint32_t i = 0; i < numSubstreams; i++)<br>
- m_outStreams[i].resetBits();<br>
-<br>
/* Get the QP for this frame from rate control. This call may block until<br>
* frames ahead of it in encode order have called rateControlEnd() */<br>
int qp = m_top->m_rateControl->rateControlStart(m_frame, &m_rce, m_top);<br>
@@ -214,6 +204,24 @@<br>
<br>
m_frameFilter.start(m_frame, m_initSliceContext, qp);<br>
<br>
+ // reset entropy coders<br>
+ m_entropyCoder.load(m_initSliceContext);<br>
+ for (int i = 0; i < m_numRows; i++)<br>
+ m_rows[i].init(m_initSliceContext);<br>
+<br>
+ uint32_t numSubstreams = m_param->bEnableWavefront ? m_frame->getPicSym()->getFrameHeightInCU() : 1;<br>
+ if (!m_outStreams)<br>
+ {<br>
+ m_outStreams = new Bitstream[numSubstreams];<br>
+ m_substreamSizes = X265_MALLOC(uint32_t, numSubstreams);<br>
+ if (!m_param->bEnableSAO)<br>
+ for (uint32_t i = 0; i < numSubstreams; i++)<br>
+ m_rows[i].rdEntropyCoders[0][CI_CURR_BEST].setBitstream(&m_outStreams[i]);<br>
+ }<br>
+ else<br>
+ for (uint32_t i = 0; i < numSubstreams; i++)<br>
+ m_outStreams[i].resetBits();<br>
+<br>
if (m_frame->m_lowres.bKeyframe)<br>
{<br>
if (m_param->bEmitHRDSEI)<br>
@@ -328,7 +336,7 @@<br>
m_entropyCoder.setBitstream(&m_bs);<br>
m_entropyCoder.codeSliceHeader(slice);<br>
<br>
- // re-encode each row of CUs for the final time (TODO: get rid of this second pass)<br>
+ // finish encode of each CTU row<br>
encodeSlice();<br>
<br>
// serialize each row, record final lengths in slice header<br>
@@ -409,8 +417,40 @@<br>
const uint32_t widthInLCUs = m_frame->getPicSym()->getFrameWidthInCU();<br>
const uint32_t lastCUAddr = (slice->m_endCUAddr + m_frame->getNumPartInCU() - 1) / m_frame->getNumPartInCU();<br>
const int numSubstreams = m_param->bEnableWavefront ? m_frame->getPicSym()->getFrameHeightInCU() : 1;<br>
+<br>
+ if (!m_param->bEnableSAO)<br>
+ {<br>
+ /* terminate each row and collect stats */<br>
+ for (uint32_t cuAddr = 0; cuAddr < lastCUAddr; cuAddr++)<br>
+ {<br>
+ uint32_t col = cuAddr % widthInLCUs;<br>
+<br>
+ if (m_param->bEnableWavefront && col == widthInLCUs - 1)<br>
+ {<br>
+ uint32_t lin = cuAddr / widthInLCUs;<br>
+ uint32_t subStrm = lin % numSubstreams;<br>
+ m_rows[subStrm].rdEntropyCoders[0][CI_CURR_BEST].codeTerminatingBit(1);<br>
+ m_rows[subStrm].rdEntropyCoders[0][CI_CURR_BEST].codeSliceFinish();<br>
+ m_outStreams[subStrm].writeByteAlignment();<br>
+ }<br>
+<br>
+ // Collect Frame Stats for 2 pass<br>
+ TComDataCU* cu = m_frame->getCU(cuAddr);<br>
+ m_frameStats.mvBits += cu->m_mvBits;<br>
+ m_frameStats.coeffBits += cu->m_coeffBits;<br>
+ m_frameStats.miscBits += cu->m_totalBits - (cu->m_mvBits + cu->m_coeffBits);<br>
+ }<br>
+ if (!m_param->bEnableWavefront)<br>
+ {<br>
+ m_rows[0].rdEntropyCoders[0][CI_CURR_BEST].codeTerminatingBit(1);<br>
+ m_rows[0].rdEntropyCoders[0][CI_CURR_BEST].codeSliceFinish();<br>
+ m_outStreams[0].writeByteAlignment();<br>
+ }<br>
+<br>
+ return;<br>
+ }<br>
+<br>
SAOParam *saoParam = slice->m_pic->getPicSym()->m_saoParam;<br>
-<br>
for (uint32_t cuAddr = 0; cuAddr < lastCUAddr; cuAddr++)<br>
{<br>
uint32_t col = cuAddr % widthInLCUs;<br>
@@ -487,11 +527,6 @@<br>
PPAScopeEvent(FrameEncoder_compressRows);<br>
Slice* slice = m_frame->m_picSym->m_slice;<br>
<br>
- // reset entropy coders<br>
- m_entropyCoder.load(m_initSliceContext);<br>
- for (int i = 0; i < m_numRows; i++)<br>
- m_rows[i].init(m_initSliceContext);<br>
-<br>
m_bAllRowsStop = false;<br>
m_vbvResetTriggerRow = -1;<br>
<br>
@@ -672,15 +707,17 @@<br>
}<br>
<br>
if (m_param->bEnableWavefront && col == 0 && row > 0)<br>
+ {<br>
// Load SBAC coder context from previous row.<br>
+ curRow.rdEntropyCoders[0][CI_CURR_BEST].copyState(m_initSliceContext);<br>
curRow.rdEntropyCoders[0][CI_CURR_BEST].loadContexts(m_rows[row - 1].bufferEntropyCoder);<br></blockquote><div><br></div><div>It's the same thing in encodeSlice as well, but why are we copying State from m_initSliceContext, and context from the saved previous row Coder? Shouldnt both state and context be copied from the previous row coder?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ }<br>
<br>
tld.cuCoder.m_quant.setQPforQuant(cu);<br>
tld.cuCoder.compressCU(cu); // Does all the CU analysis<br>
<br>
/* advance top-level CI_CURR_BEST to include the context of this CTU.<br>
- * Note that if SAO was disabled this could directly write to a<br>
- * bitstream object and we could skip most of encodeSlice() */<br>
+ * if SAO is disabled, this writes final CTU bitstream */<br>
curRow.rdEntropyCoders[0][CI_CURR_BEST].encodeCU(cu);<br>
<br>
if (m_param->bEnableWavefront && col == 1)<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br></div></div>