<div dir="ltr">Yes, sending once again.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Sep 28, 2017 at 2:59 PM, Pradeep Ramachandran <span dir="ltr"><<a href="mailto:pradeep@multicorewareinc.com" target="_blank">pradeep@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Thu, Sep 28, 2017 at 2:16 PM,  <span dir="ltr"><<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span># HG changeset patch<br>
# User Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>><br>
</span># Date 1506091858 -19800<br>
#  Â  Â  Fri Sep 22 20:20:58 2017 +0530<br>
# Node ID c838e60c7c6ba0ab07e2d4130a5c2b<wbr>a22e0b1eea<br>
# Parent  e62b12bd8b4573b15290ebf110e01c<wbr>8fafce55be<br>
<span>vbv hanging issue; fix for multiple slices<br>
When multiple slices are enabled, vbv rate control must take care of<br>
correct rows in slices, since multiple slices are encoding simultaneously.<br>
<br></span></blockquote><div><br></div></span><div>This patch doesn't apply on the current tip of the default branch. Please fix and resend.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><span>
</span>diff -r e62b12bd8b45 -r c838e60c7c6b source/encoder/frameencoder.cp<wbr>p<br>
--- a/source/encoder/frameencoder.<wbr>cpp  Â Thu Jun 29 13:13:56 2017 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>cpp  Â Fri Sep 22 20:20:58 2017 +0530<br>
<div><div class="m_4073142056016003513h5">@@ -88,6 +88,7 @@<br>
  Â  Â delete[] m_outStreams;<br>
  Â  Â delete[] m_backupStreams;<br>
  Â  Â X265_FREE(m_sliceBaseRow);<br>
+  Â  X265_FREE(m_sliceMaxBlockRow);<br>
  Â  Â X265_FREE(m_cuGeoms);<br>
  Â  Â X265_FREE(m_ctuGeomMap);<br>
  Â  Â X265_FREE(m_substreamSizes);<br>
@@ -118,6 +119,40 @@<br>
<br>
  Â  Â m_sliceBaseRow = X265_MALLOC(uint32_t, m_param->maxSlices + 1);<br>
  Â  Â ok &= !!m_sliceBaseRow;<br>
+  Â  m_sliceGroupSize = (uint16_t)(m_numRows + m_param->maxSlices - 1) / m_param->maxSlices;<br>
+  Â  uint32_t sliceGroupSizeAccu = (m_numRows << 8) / m_param->maxSlices;<br>
+  Â  uint32_t rowSum = sliceGroupSizeAccu;<br>
+  Â  uint32_t sidx = 0;<br>
+  Â  for (uint32_t i = 0; i < m_numRows; i++)<br>
+  Â  {<br>
+  Â  Â  Â  const uint32_t rowRange = (rowSum >> 8);<br>
+  Â  Â  Â  if ((i >= rowRange) & (sidx != m_param->maxSlices - 1))<br>
+  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  rowSum += sliceGroupSizeAccu;<br>
+  Â  Â  Â  Â  Â  m_sliceBaseRow[++sidx] = i;<br>
+  Â  Â  Â  }<br>
+  Â  }<br>
+  Â  X265_CHECK(sidx < m_param->maxSlices, "sliceID check failed!");<br>
+  Â  m_sliceBaseRow[0] = 0;<br>
+  Â  m_sliceBaseRow[m_param->maxSli<wbr>ces] = m_numRows;<br>
+<br>
+  Â  m_sliceMaxBlockRow = X265_MALLOC(uint32_t, m_param->maxSlices + 1);<br>
+  Â  ok &= !!m_sliceMaxBlockRow;<br>
+  Â  uint32_t maxBlockRows = (m_param->sourceHeight + (16 - 1)) / 16;<br>
+  Â  sliceGroupSizeAccu = (maxBlockRows << 8) / m_param->maxSlices;<br>
+  Â  rowSum = sliceGroupSizeAccu;<br>
+  Â  sidx = 0;<br>
+  Â  for (uint32_t i = 0; i < maxBlockRows; i++)<br>
+  Â  {<br>
+  Â  Â  Â  const uint32_t rowRange = (rowSum >> 8);<br>
+  Â  Â  Â  if ((i >= rowRange) & (sidx != m_param->maxSlices - 1))<br>
+  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  rowSum += sliceGroupSizeAccu;<br>
+  Â  Â  Â  Â  Â  m_sliceMaxBlockRow[++sidx] = i;<br>
+  Â  Â  Â  }<br>
+  Â  }<br>
+  Â  m_sliceMaxBlockRow[0] = 0;<br>
+  Â  m_sliceMaxBlockRow[m_param->ma<wbr>xSlices] = maxBlockRows;<br>
<br>
  Â  Â /* determine full motion search range */<br>
  Â  Â int range  = m_param->searchRange;  Â  Â  Â /* fpel search */<br>
@@ -341,6 +376,8 @@<br>
  Â  Â m_completionCount = 0;<br>
  Â  Â m_bAllRowsStop = false;<br>
  Â  Â m_vbvResetTriggerRow = -1;<br>
+  Â  m_rowSliceTotalBits[0] = 0;<br>
+  Â  m_rowSliceTotalBits[1] = 0;<br>
<br>
  Â  Â m_SSDY = m_SSDU = m_SSDV = 0;<br>
  Â  Â m_ssim = 0;<br>
@@ -550,28 +587,13 @@<br>
<br>
  Â  Â /* reset entropy coders and compute slice id */<br>
  Â  Â m_entropyCoder.load(m_initSli<wbr>ceContext);<br>
-  Â  const uint32_t sliceGroupSize = (m_numRows + m_param->maxSlices - 1) / m_param->maxSlices;<br>
-  Â  const uint32_t sliceGroupSizeAccu = (m_numRows << 8) / m_param->maxSlices;<br>
-  Â  m_sliceGroupSize = (uint16_t)sliceGroupSize;<br>
+<br>
+  Â  for (uint32_t sliceId = 0; sliceId < m_param->maxSlices; sliceId++)<br>
+  Â  Â  Â  for (uint32_t row = m_sliceBaseRow[sliceId]; row < m_sliceBaseRow[sliceId + 1]; row++)<br>
+  Â  Â  Â  Â  Â  m_rows[row].init(m_initSliceCo<wbr>ntext, sliceId);<br>
<br>
-  Â  uint32_t rowSum = sliceGroupSizeAccu;<br>
-  Â  uint32_t sidx = 0;<br>
-  Â  for (uint32_t i = 0; i < m_numRows; i++)<br>
-  Â  {<br>
-  Â  Â  Â  const uint32_t rowRange = (rowSum >> 8);<br>
-<br>
-  Â  Â  Â  if ((i >= rowRange) & (sidx != m_param->maxSlices - 1))<br>
-  Â  Â  Â  {<br>
-  Â  Â  Â  Â  Â  rowSum += sliceGroupSizeAccu;<br>
-  Â  Â  Â  Â  Â  m_sliceBaseRow[++sidx] = i;<br>
-  Â  Â  Â  }<br>
-<br>
-  Â  Â  Â  m_rows[i].init(m_initSliceCont<wbr>ext, sidx);<br>
-  Â  }<br>
-  Â  X265_CHECK(sidx < m_param->maxSlices, "sliceID check failed!");<br>
-<br>
-  Â  m_sliceBaseRow[0] = 0;<br>
-  Â  m_sliceBaseRow[m_param->maxSli<wbr>ces] = m_numRows;<br>
+  Â  // reset slice counter for rate control update<br>
+  Â  m_sliceCnt = 0;<br>
<br>
  Â  Â uint32_t numSubstreams = m_param->bEnableWavefront ? slice->m_sps->numCuInHeight : m_param->maxSlices;<br>
  Â  Â X265_CHECK(m_param->bEnableWa<wbr>vefront || (m_param->maxSlices == 1), "Multiple slices without WPP unsupport now!");<br>
@@ -586,8 +608,10 @@<br>
  Â  Â  Â  Â  Â  Â  Â  Â m_rows[i].rowGoOnCoder.setBit<wbr>stream(&m_outStreams[i]);<br>
  Â  Â }<br>
  Â  Â else<br>
+  Â  {<br>
  Â  Â  Â  Â for (uint32_t i = 0; i < numSubstreams; i++)<br>
  Â  Â  Â  Â  Â  Â m_outStreams[i].resetBits();<br>
+  Â  }<br>
<br>
  Â  Â int prevBPSEI = m_rce.encodeOrder ? m_top->m_lastBPSEI : 0;<br>
<br>
@@ -697,10 +721,9 @@<br>
  Â  Â  * compressed in a wave-front pattern if WPP is enabled. Row based loop<br>
  Â  Â  * filters runs behind the CTU compression and reconstruction */<br>
<br>
-  Â  for (uint32_t sliceId = 0; sliceId < m_param->maxSlices; sliceId++)<br>
-  Â  {<br>
+  Â  for (uint32_t sliceId = 0; sliceId < m_param->maxSlices; sliceId++)<br>
  Â  Â  Â  Â m_rows[m_sliceBaseRow[<wbr>sliceId]].active = true;<br>
-  Â  }<br>
+<br>
  Â  Â if (m_param->bEnableWavefront)<br>
  Â  Â {<br>
  Â  Â  Â  Â int i = 0;<br>
</div></div>@@ -719,6 +742,7 @@<br>
  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â }<br>
  Â  Â }<br>
+<br>
  Â  Â if (m_param->bEnableWavefront)<br>
  Â  Â {<br>
  Â  Â  Â  Â for (uint32_t rowInSlice = 0; rowInSlice < m_sliceGroupSize; rowInSlice++)<br>
@@ -751,6 +775,7 @@<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â m_mref[l][ref].applyWeight(ro<wbr>wIdx, m_numRows, sliceEndRow, sliceId);<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â  Â  Â }<br>
+<br>
  Â  Â  Â  Â  Â  Â  Â  Â enableRowEncoder(m_row_to_<wbr>idx[row]); /* clear external dependency for this row */<br>
  Â  Â  Â  Â  Â  Â  Â  Â if (!rowInSlice)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
@@ -980,9 +1005,8 @@<br>
<span>  Â  Â  Â  Â  Â  Â // complete the slice header by writing WPP row-starts<br>
  Â  Â  Â  Â  Â  Â m_entropyCoder.setBitstream(&<wbr>m_bs);<br>
  Â  Â  Â  Â  Â  Â if (slice->m_pps->bEntropyCodingS<wbr>yncEnabled)<br>
-  Â  Â  Â  Â  Â  {<br>
  Â  Â  Â  Â  Â  Â  Â  Â m_entropyCoder.codeSliceHeade<wbr>rWPPEntryPoints(&m_<wbr>substreamSizes[prevSliceRow], (nextSliceRow - prevSliceRow - 1), maxStreamSize);<br>
-  Â  Â  Â  Â  Â  }<br>
+<br>
  Â  Â  Â  Â  Â  Â m_bs.writeByteAlignment();<br>
<br>
  Â  Â  Â  Â  Â  Â m_nalList.serialize(slice->m_<wbr>nalUnitType, m_bs);<br>
</span>@@ -1211,17 +1235,21 @@<br>
  Â  Â int64_t startTime = x265_mdate();<br>
  Â  Â if (ATOMIC_INC(&m_activeWorkerCou<wbr>nt) == 1 && m_stallStartTime)<br>
  Â  Â  Â  Â m_totalNoWorkerTime += x265_mdate() - m_stallStartTime;<br>
+<br>
  Â  Â const uint32_t realRow = m_idx_to_row[row >> 1];<br>
  Â  Â const uint32_t typeNum = m_idx_to_row[row & 1];<br>
+<br>
  Â  Â if (!typeNum)<br>
  Â  Â  Â  Â processRowEncoder(realRow, m_tld[threadId]);<br>
  Â  Â else<br>
  Â  Â {<br>
  Â  Â  Â  Â m_frameFilter.processRow(real<wbr>Row);<br>
+<br>
  Â  Â  Â  Â // NOTE: Active next row<br>
  Â  Â  Â  Â if (realRow != m_sliceBaseRow[m_rows[realRow]<wbr>.sliceId + 1] - 1)<br>
  Â  Â  Â  Â  Â  Â enqueueRowFilter(m_row_to_<wbr>idx[realRow + 1]);<br>
  Â  Â }<br>
+<br>
  Â  Â if (ATOMIC_DEC(&m_activeWorkerCou<wbr>nt) == 0)<br>
  Â  Â  Â  Â m_stallStartTime = x265_mdate();<br>
<br>
@@ -1264,20 +1292,18 @@<br>
<span>  Â  Â const uint32_t lineStartCUAddr = row * numCols;<br>
  Â  Â bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;<br>
<br>
+  Â  const uint32_t sliceId = curRow.sliceId;<br>
  Â  Â uint32_t maxBlockCols = (m_frame->m_fencPic->m_picWidt<wbr>h + (16 - 1)) / 16;<br>
-  Â  uint32_t maxBlockRows = (m_frame->m_fencPic->m_picHeig<wbr>ht + (16 - 1)) / 16;<br>
  Â  Â uint32_t noOfBlocks = m_param->maxCUSize / 16;<br>
  Â  Â const uint32_t bFirstRowInSlice = ((row == 0) || (m_rows[row - 1].sliceId != curRow.sliceId)) ? 1 : 0;<br>
  Â  Â const uint32_t bLastRowInSlice = ((row == m_numRows - 1) || (m_rows[row + 1].sliceId != curRow.sliceId)) ? 1 : 0;<br>
-  Â  const uint32_t sliceId = curRow.sliceId;<br>
  Â  Â const uint32_t endRowInSlicePlus1 = m_sliceBaseRow[sliceId + 1];<br>
  Â  Â const uint32_t rowInSlice = row - m_sliceBaseRow[sliceId];<br>
<br>
-  Â  if (bFirstRowInSlice && !curRow.completed)<br>
-  Â  {<br>
-  Â  Â  Â  // Load SBAC coder context from previous row and initialize row state.<br>
-  Â  Â  Â  rowCoder.load(m_initSliceConte<wbr>xt);<br>
-  Â  }<br>
+  Â  // Load SBAC coder context from previous row and initialize row state.<br>
+  Â  if (bFirstRowInSlice && !curRow.completed)<br>
+  Â  Â  Â  rowCoder.load(m_initSliceConte<wbr>xt);<br>
</span>+<br>
<span>  Â  Â // calculate mean QP for consistent deltaQP signalling calculation<br>
  Â  Â if (m_param->bOptCUDeltaQP)<br>
  Â  Â {<br>
</span>@@ -1287,15 +1313,12 @@<br>
<span>  Â  Â  Â  Â  Â  Â if (m_param->bEnableWavefront || !row)<br>
  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â double meanQPOff = 0;<br>
-  Â  Â  Â  Â  Â  Â  Â  uint32_t loopIncr, count = 0;<br>
  Â  Â  Â  Â  Â  Â  Â  Â bool isReferenced = IS_REFERENCED(m_frame);<br>
  Â  Â  Â  Â  Â  Â  Â  Â double *qpoffs = (isReferenced && m_param->rc.cuTree) ? m_frame->m_lowres.qpCuTreeOffs<wbr>et : m_frame->m_lowres.qpAqOffset;<br>
  Â  Â  Â  Â  Â  Â  Â  Â if (qpoffs)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  if (m_param->rc.qgSize == 8)<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  loopIncr = 8;<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  else<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  loopIncr = 16;<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  uint32_t loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16;<br>
+<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â uint32_t cuYStart = 0, height = m_frame->m_fencPic->m_picHeigh<wbr>t;<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â if (m_param->bEnableWavefront)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
</span>@@ -1305,6 +1328,7 @@<br>
<span><br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â uint32_t qgSize = m_param->rc.qgSize, width = m_frame->m_fencPic->m_picWidth<wbr>;<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â uint32_t maxOffsetCols = (m_frame->m_fencPic->m_picWidt<wbr>h + (loopIncr - 1)) / loopIncr;<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  uint32_t count = 0;<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â for (uint32_t cuY = cuYStart; cuY < height && (cuY < m_frame->m_fencPic->m_picHeigh<wbr>t); cuY += qgSize)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â for (uint32_t cuX = 0; cuX < width; cuX += qgSize)<br>
</span>@@ -1336,7 +1360,8 @@<br>
  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â curRow.avgQPComputed = 1;<br>
  Â  Â  Â  Â }<br>
-  Â  }<br>
+  Â  }<br>
+<br>
  Â  Â // Initialize restrict on MV range in slices<br>
  Â  Â tld.analysis.m_sliceMinY = -(int16_t)(rowInSlice * m_param->maxCUSize * 4) + 3 * 4;<br>
  Â  Â tld.analysis.m_sliceMaxY = (int16_t)((endRowInSlicePlus1 - 1 - row) * (m_param->maxCUSize * 4) - 4 * 4);<br>
@@ -1364,16 +1389,16 @@<br>
<span>  Â  Â  Â  Â  Â  Â  Â  Â curRow.bufferedEntropy.copySt<wbr>ate(rowCoder);<br>
  Â  Â  Â  Â  Â  Â  Â  Â curRow.bufferedEntropy.loadCo<wbr>ntexts(rowCoder);<br>
  Â  Â  Â  Â  Â  Â }<br>
-  Â  Â  Â  Â  Â  if (!row && m_vbvResetTriggerRow != intRow)<br>
+  Â  Â  Â  Â  Â  if (bFirstRowInSlice && m_vbvResetTriggerRow != intRow)<br>
  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[row].row<wbr>Qp = curEncData.m_avgQpRc;<br>
  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[row].row<wbr>QpScale = x265_qp2qScale(curEncData.m_av<wbr>gQpRc);<br>
  Â  Â  Â  Â  Â  Â }<br>
<br>
  Â  Â  Â  Â  Â  Â FrameData::RCStatCU& cuStat = curEncData.m_cuStat[cuAddr];<br>
-  Â  Â  Â  Â  Â  if (m_param->bEnableWavefront && row >= col && row && m_vbvResetTriggerRow != intRow)<br>
+  Â  Â  Â  Â  Â  if (m_param->bEnableWavefront && rowInSlice >= col && !bFirstRowInSlice && m_vbvResetTriggerRow != intRow)<br>
  Â  Â  Â  Â  Â  Â  Â  Â cuStat.baseQp = curEncData.m_cuStat[cuAddr - numCols + 1].baseQp;<br>
-  Â  Â  Â  Â  Â  else if (!m_param->bEnableWavefront && row && m_vbvResetTriggerRow != intRow)<br>
+  Â  Â  Â  Â  Â  else if (!m_param->bEnableWavefront && !bFirstRowInSlice && m_vbvResetTriggerRow != intRow)<br>
  Â  Â  Â  Â  Â  Â  Â  Â cuStat.baseQp = curEncData.m_rowStat[row - 1].rowQp;<br>
  Â  Â  Â  Â  Â  Â else<br>
  Â  Â  Â  Â  Â  Â  Â  Â cuStat.baseQp = curEncData.m_rowStat[row].rowQ<wbr>p;<br>
</span>@@ -1385,7 +1410,8 @@<br>
<span>  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â cuStat.vbvCost = 0;<br>
  Â  Â  Â  Â  Â  Â  Â  Â cuStat.intraVbvCost = 0;<br>
-  Â  Â  Â  Â  Â  Â  Â  for (uint32_t h = 0; h < noOfBlocks && block_y < maxBlockRows; h++, block_y++)<br>
+<br>
+  Â  Â  Â  Â  Â  Â  Â  for (uint32_t h = 0; h < noOfBlocks && block_y < m_sliceMaxBlockRow[sliceId + 1]; h++, block_y++)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â uint32_t idx = block_x + (block_y * maxBlockCols);<br>
<br>
</span>@@ -1433,11 +1459,12 @@<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â // NOTE: in VBV mode, we may reencode anytime, so we can't do Deblock stage-Horizon and SAO<br>
  Â  Â  Â  Â  Â  Â if (!bIsVbv)<br>
-  Â  Â  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  {<br>
  Â  Â  Â  Â  Â  Â  Â  Â // Delay one row to avoid intra prediction conflict<br>
  Â  Â  Â  Â  Â  Â  Â  Â if (m_pool && !bFirstRowInSlice)<br>
-  Â  Â  Â  Â  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  Â  Â  {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â int allowCol = col;<br>
+<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â // avoid race condition on last column<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â if (rowInSlice >= 2)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
@@ -1446,11 +1473,13 @@<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â m_frameFilter.m_parallelFilte<wbr>r[row - 1].m_allowedCol.set(allowCol);<br>
  Â  Â  Â  Â  Â  Â  Â  Â }<br>
+<br>
  Â  Â  Â  Â  Â  Â  Â  Â // Last Row may start early<br>
  Â  Â  Â  Â  Â  Â  Â  Â if (m_pool && bLastRowInSlice)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â // Deblocking last row<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â int allowCol = col;<br>
+<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â // avoid race condition on last column<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â if (rowInSlice >= 2)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
@@ -1472,6 +1501,7 @@<br>
<br>
  Â  Â  Â  Â FrameStats frameLog;<br>
  Â  Â  Â  Â curEncData.m_rowStat[row].sum<wbr>QpAq += collectCTUStatistics(*ctu, &frameLog);<br>
+<br>
  Â  Â  Â  Â // copy number of intra, inter cu per row into frame stats for 2 pass<br>
  Â  Â  Â  Â if (m_param->rc.bStatWrite)<br>
  Â  Â  Â  Â {<br>
@@ -1485,10 +1515,8 @@<br>
<span>  Â  Â  Â  Â  Â  Â  Â  Â int shift = 2 * (m_param->maxCUDepth - depth);<br>
  Â  Â  Â  Â  Â  Â  Â  Â int cuSize = m_param->maxCUSize >> depth;<br>
<br>
-  Â  Â  Â  Â  Â  Â  Â  if (cuSize == 8)<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  curRow.rowStats.intra8x8Cnt += (int)(frameLog.cntIntra[depth] + frameLog.cntIntraNxN);<br>
-  Â  Â  Â  Â  Â  Â  Â  else<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  curRow.rowStats.intra8x8Cnt += (int)(frameLog.cntIntra[depth] << shift);<br>
+  Â  Â  Â  Â  Â  Â  Â  curRow.rowStats.intra8x8Cnt += (cuSize == 8) ? (int)(frameLog.cntIntra[depth] + frameLog.cntIntraNxN) :<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â (int)(frameLog.cntIntra[<wbr>depth] << shift);<br>
<br>
  Â  Â  Â  Â  Â  Â  Â  Â curRow.rowStats.inter8x8Cnt += (int)(frameLog.cntInter[depth] << shift);<br>
  Â  Â  Â  Â  Â  Â  Â  Â curRow.rowStats.skip8x8Cnt += (int)((frameLog.cntSkipCu[dept<wbr>h] + frameLog.cntMergeCu[depth]) << shift);<br>
</span>@@ -1518,12 +1546,13 @@<br>
<span>  Â  Â  Â  Â if (bIsVbv)<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â // Update encoded bits, satdCost, baseQP for each CU if tune grain is disabled<br>
-  Â  Â  Â  Â  Â  if ((m_param->bEnableWavefront && (!cuAddr || !m_param->rc.bEnableConstVbv)) || !m_param->bEnableWavefront)<br>
+  Â  Â  Â  Â  Â  FrameData::RCStatCU& cuStat = curEncData.m_cuStat[cuAddr];<br>
+  Â  Â  Â  Â  Â  if ((m_param->bEnableWavefront && ((cuAddr == m_sliceBaseRow[sliceId] * numCols) || !m_param->rc.bEnableConstVbv)) || !m_param->bEnableWavefront)<br>
  Â  Â  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].rowS<wbr>atd += curEncData.m_cuStat[cuAddr].vb<wbr>vCost;<br>
-  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].rowI<wbr>ntraSatd += curEncData.m_cuStat[cuAddr].in<wbr>traVbvCost;<br>
-  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].enco<wbr>dedBits += curEncData.m_cuStat[cuAddr].to<wbr>talBits;<br>
-  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].sumQ<wbr>pRc += curEncData.m_cuStat[cuAddr].ba<wbr>seQp;<br>
+  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].rowS<wbr>atd += cuStat.vbvCost;<br>
+  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].rowI<wbr>ntraSatd += cuStat.intraVbvCost;<br>
+  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].enco<wbr>dedBits += cuStat.totalBits;<br>
+  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].sumQ<wbr>pRc += cuStat.baseQp;<br>
  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[row].num<wbr>EncodedCUs = cuAddr;<br>
  Â  Â  Â  Â  Â  Â }<br>
<br>
</span>@@ -1531,7 +1560,7 @@<br>
<span>  Â  Â  Â  Â  Â  Â if (!m_param->bEnableWavefront && col == numCols - 1)<br>
  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â double qpBase = curEncData.m_cuStat[cuAddr].ba<wbr>seQp;<br>
-  Â  Â  Â  Â  Â  Â  Â  int reEncode = m_top->m_rateControl->rowVbvRa<wbr>teControl(m_frame, row, &m_rce, qpBase);<br>
+  Â  Â  Â  Â  Â  Â  Â  int reEncode = m_top->m_rateControl->rowVbvRa<wbr>teControl(m_frame, row, &m_rce, qpBase, m_sliceBaseRow, sliceId);<br>
  Â  Â  Â  Â  Â  Â  Â  Â qpBase = x265_clip3((double)m_param->rc<wbr>.qpMin, (double)m_param->rc.qpMax, qpBase);<br>
  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[row].row<wbr>Qp = qpBase;<br>
  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[row].row<wbr>QpScale = x265_qp2qScale(qpBase);<br>
</span>@@ -1557,15 +1586,16 @@<br>
<span>  Â  Â  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â // If current block is at row diagonal checkpoint, call vbv ratecontrol.<br>
-  Â  Â  Â  Â  Â  else if (m_param->bEnableWavefront && row == col && row)<br>
+  Â  Â  Â  Â  Â  else if (m_param->bEnableWavefront && rowInSlice == col && !bFirstRowInSlice)<br>
  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â if (m_param->rc.bEnableConstVbv)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  int32_t startCuAddr = numCols * row;<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  int32_t EndCuAddr = startCuAddr + col;<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  for (int32_t r = row; r >= 0; r--)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  uint32_t startCuAddr = numCols * row;<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  uint32_t EndCuAddr = startCuAddr + col;<br>
+<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  for (int32_t r = row; r >= (int32_t)m_sliceBaseRow[sliceI<wbr>d]; r--)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  for (int32_t c = startCuAddr; c <= EndCuAddr && c <= (int32_t)numCols * (r + 1) - 1; c++)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  for (uint32_t c = startCuAddr; c <= EndCuAddr && c <= numCols * (r + 1) - 1; c++)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[r].rowSa<wbr>td += curEncData.m_cuStat[c].vbvCost<wbr>;<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[r].rowIn<wbr>traSatd += curEncData.m_cuStat[c].intraVb<wbr>vCost;<br>
</span>@@ -1578,10 +1608,10 @@<br>
<span>  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â  Â  Â }<br>
  Â  Â  Â  Â  Â  Â  Â  Â double qpBase = curEncData.m_cuStat[cuAddr].ba<wbr>seQp;<br>
-  Â  Â  Â  Â  Â  Â  Â  int reEncode = m_top->m_rateControl->rowVbvRa<wbr>teControl(m_frame, row, &m_rce, qpBase);<br>
+  Â  Â  Â  Â  Â  Â  Â  int reEncode = m_top->m_rateControl->rowVbvRa<wbr>teControl(m_frame, row, &m_rce, qpBase, m_sliceBaseRow, sliceId);<br>
  Â  Â  Â  Â  Â  Â  Â  Â qpBase = x265_clip3((double)m_param->rc<wbr>.qpMin, (double)m_param->rc.qpMax, qpBase);<br>
  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[row].row<wbr>Qp = qpBase;<br>
-  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].rowQ<wbr>pScale =  x265_qp2qScale(qpBase);<br>
+  Â  Â  Â  Â  Â  Â  Â  curEncData.m_rowStat[row].rowQ<wbr>pScale = x265_qp2qScale(qpBase);<br>
<br>
  Â  Â  Â  Â  Â  Â  Â  Â if (reEncode < 0)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
</span>@@ -1592,7 +1622,7 @@<br>
<span>  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â m_vbvResetTriggerRow = row;<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â m_bAllRowsStop = true;<br>
<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  for (uint32_t r = m_numRows - 1; r >= row; r--)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  for (uint32_t r = m_sliceBaseRow[sliceId + 1] - 1; r >= row; r--)<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â CTURow& stopRow = m_rows[r];<br>
<br>
</span>@@ -1670,14 +1700,15 @@<br>
  Â  Â  Â  Â  Â  Â return;<br>
  Â  Â  Â  Â }<br>
  Â  Â }<br>
+<br>
<span>  Â  Â /* this row of CTUs has been compressed */<br>
  Â  Â if (m_param->bEnableWavefront && m_param->rc.bEnableConstVbv)<br>
  Â  Â {<br>
-  Â  Â  Â  if (row == m_numRows - 1)<br>
+  Â  Â  Â  if (bLastRowInSlice)<br>
  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  for (int32_t r = 0; r < (int32_t)m_numRows; r++)<br>
+  Â  Â  Â  Â  Â  for (uint32_t r = m_sliceBaseRow[sliceId]; r < m_sliceBaseRow[sliceId + 1]; r++)<br>
  Â  Â  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  Â  Â  for (int32_t c = curEncData.m_rowStat[r].numEnc<wbr>odedCUs + 1; c < (int32_t)numCols * (r + 1); c++)<br>
+  Â  Â  Â  Â  Â  Â  Â  for (uint32_t c = curEncData.m_rowStat[r].numEnc<wbr>odedCUs + 1; c < numCols * (r + 1); c++)<br>
  Â  Â  Â  Â  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[r].rowSa<wbr>td += curEncData.m_cuStat[c].vbvCost<wbr>;<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â curEncData.m_rowStat[r].rowIn<wbr>traSatd += curEncData.m_cuStat[c].intraVb<wbr>vCost;<br>
</span>@@ -1695,26 +1726,41 @@<br>
<span>  Â  Â  * after half the frame is encoded, but after this initial period we update<br>
  Â  Â  * after refLagRows (the number of rows reference frames must have completed<br>
  Â  Â  * before referencees may begin encoding) */<br>
-  Â  uint32_t rowCount = 0;<br>
  Â  Â if (m_param->rc.rateControlMode == X265_RC_ABR || bIsVbv)<br>
  Â  Â {<br>
+  Â  Â  Â  uint32_t rowCount = 0;<br>
+  Â  Â  Â  uint32_t maxRows = m_sliceBaseRow[sliceId + 1] - m_sliceBaseRow[sliceId];<br>
  Â  Â  Â  Â if (!m_rce.encodeOrder)<br>
-  Â  Â  Â  Â  Â  rowCount = m_numRows - 1;<br>
+  Â  Â  Â  Â  Â  rowCount = maxRows - 1;<br>
  Â  Â  Â  Â else if ((uint32_t)m_rce.encodeOrder <= 2 * (m_param->fpsNum / m_param->fpsDenom))<br>
-  Â  Â  Â  Â  Â  rowCount = X265_MIN((m_numRows + 1) / 2, m_numRows - 1);<br>
+  Â  Â  Â  Â  Â  rowCount = X265_MIN((maxRows + 1) / 2, maxRows - 1);<br>
  Â  Â  Â  Â else<br>
-  Â  Â  Â  Â  Â  rowCount = X265_MIN(m_refLagRows, m_numRows - 1);<br>
-  Â  Â  Â  if (row == rowCount)<br>
</span>+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â rowCount = X265_MIN(m_refLagRows / m_param->maxSlices, maxRows - 1);<br>
+<br>
+  Â  Â  Â  if (rowInSlice == rowCount)<br>
<span>  Â  Â  Â  Â {<br>
-  Â  Â  Â  Â  Â  m_rce.rowTotalBits = 0;<br>
+  Â  Â  Â  Â  Â  m_rowSliceTotalBits[sliceId] = 0;<br>
  Â  Â  Â  Â  Â  Â if (bIsVbv)<br>
-  Â  Â  Â  Â  Â  Â  Â  for (uint32_t i = 0; i < rowCount; i++)<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  m_rce.rowTotalBits += curEncData.m_rowStat[i].encode<wbr>dBits;<br>
+  Â  Â  Â  Â  Â  {<br>
</span>+  Â  Â  Â  Â  Â  Â  Â  for (uint32_t i = m_sliceBaseRow[sliceId]; i < rowCount + m_sliceBaseRow[sliceId]; i++)<br>
<span>+  Â  Â  Â  Â  Â  Â  Â  Â  Â  m_rowSliceTotalBits[sliceId] += curEncData.m_rowStat[i].encode<wbr>dBits;<br>
+  Â  Â  Â  Â  Â  }<br>
  Â  Â  Â  Â  Â  Â else<br>
-  Â  Â  Â  Â  Â  Â  Â  for (uint32_t cuAddr = 0; cuAddr < rowCount * numCols; cuAddr++)<br>
-  Â  Â  Â  Â  Â  Â  Â  Â  Â  m_rce.rowTotalBits += curEncData.m_cuStat[cuAddr].to<wbr>talBits;<br>
+  Â  Â  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  Â  Â  uint32_t startAddr = rowCount * numCols * sliceId;<br>
+  Â  Â  Â  Â  Â  Â  Â  uint32_t finishAddr = startAddr + rowCount * numCols;<br>
+<br>
+  Â  Â  Â  Â  Â  Â  Â  for (uint32_t cuAddr = startAddr; cuAddr < finishAddr; cuAddr++)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  m_rowSliceTotalBits[sliceId] += curEncData.m_cuStat[cuAddr].to<wbr>talBits;<br>
+  Â  Â  Â  Â  Â  }<br>
<br>
-  Â  Â  Â  Â  Â  m_top->m_rateControl->rateCont<wbr>rolUpdateStats(&m_rce);<br>
+  Â  Â  Â  Â  Â  if (ATOMIC_INC(&m_sliceCnt) == (int)m_param->maxSlices)<br>
+  Â  Â  Â  Â  Â  {<br>
+  Â  Â  Â  Â  Â  Â  Â  m_rce.rowTotalBits = 0;<br>
+  Â  Â  Â  Â  Â  Â  Â  for (uint32_t i = 0; i < m_param->maxSlices; i++)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  m_rce.rowTotalBits += m_rowSliceTotalBits[i];<br>
+  Â  Â  Â  Â  Â  Â  Â  m_top->m_rateControl->rateCont<wbr>rolUpdateStats(&m_rce);<br>
+  Â  Â  Â  Â  Â  }<br>
  Â  Â  Â  Â }<br>
  Â  Â }<br>
<br>
</span>@@ -1742,11 +1788,13 @@<br>
  Â  Â  Â  Â if (rowInSlice >= m_filterRowDelay)<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â enableRowFilter(m_row_to_idx[<wbr>row - m_filterRowDelay]);<br>
+<br>
  Â  Â  Â  Â  Â  Â /* NOTE: Activate filter if first row (row 0) */<br>
  Â  Â  Â  Â  Â  Â if (rowInSlice == m_filterRowDelay)<br>
  Â  Â  Â  Â  Â  Â  Â  Â enqueueRowFilter(m_row_to_<wbr>idx[row - m_filterRowDelay]);<br>
  Â  Â  Â  Â  Â  Â tryWakeOne();<br>
  Â  Â  Â  Â }<br>
+<br>
  Â  Â  Â  Â if (bLastRowInSlice)<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â for (uint32_t i = endRowInSlicePlus1 - m_filterRowDelay; i < endRowInSlicePlus1; i++)<br>
diff -r e62b12bd8b45 -r c838e60c7c6b source/encoder/frameencoder.h<br>
--- a/source/encoder/frameencoder.<wbr>h  Â  Â Thu Jun 29 13:13:56 2017 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>h  Â  Â Fri Sep 22 20:20:58 2017 +0530<br>
<span>@@ -138,6 +138,7 @@<br>
  Â  Â volatile bool  Â  Â  Â  Â  Â  m_bAllRowsStop;<br>
  Â  Â volatile int  Â  Â  Â  Â  Â  Â m_completionCount;<br>
  Â  Â volatile int  Â  Â  Â  Â  Â  Â m_vbvResetTriggerRow;<br>
+  Â  volatile int  Â  Â  Â  Â  Â  Â m_sliceCnt;<br>
<br>
  Â  Â uint32_t  Â  Â  Â  Â  Â  Â  Â  Â m_numRows;<br>
  Â  Â uint32_t  Â  Â  Â  Â  Â  Â  Â  Â m_numCols;<br>
@@ -147,8 +148,10 @@<br>
<br>
  Â  Â CTURow*  Â  Â  Â  Â  Â  Â  Â  Â  m_rows;<br>
  Â  Â uint16_t  Â  Â  Â  Â  Â  Â  Â  Â m_sliceAddrBits;<br>
-  Â  uint16_t  Â  Â  Â  Â  Â  Â  Â  Â m_sliceGroupSize;<br>
-  Â  uint32_t*  Â  Â  Â  Â  Â  Â  Â  m_sliceBaseRow;<br>
+  Â  uint32_t  Â  Â  Â  Â  Â  Â  Â  Â m_sliceGroupSize;<br>
+  Â  uint32_t*  Â  Â  Â  Â  Â  Â  Â  m_sliceBaseRow;<br>
+  Â  uint32_t*  Â  Â  Â  Â  Â  Â  Â  m_sliceMaxBlockRow;<br>
+  Â  int64_t  Â  Â  Â  Â  Â  Â  Â  Â  m_rowSliceTotalBits[2];<br>
  Â  Â RateControlEntry  Â  Â  Â  Â m_rce;<br>
  Â  Â SEIDecodedPictureHash  Â  m_seiReconPictureDigest;<br>
<br>
</span>diff -r e62b12bd8b45 -r c838e60c7c6b source/encoder/ratecontrol.cpp<br>
--- a/source/encoder/ratecontrol.c<wbr>pp  Â  Thu Jun 29 13:13:56 2017 +0530<br>
+++ b/source/encoder/ratecontrol.c<wbr>pp  Â  Fri Sep 22 20:20:58 2017 +0530<br>
<div><div class="m_4073142056016003513h5">@@ -732,7 +732,6 @@<br>
  Â  Â m_bitrate = m_param->rc.bitrate * 1000;<br>
 }<br>
<br>
-<br>
 void RateControl::initHRD(SPS& sps)<br>
 {<br>
  Â  Â int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;<br>
@@ -765,6 +764,7 @@<br>
<br>
  Â  Â #undef MAX_DURATION<br>
 }<br>
+<br>
 bool RateControl::analyseABR2Pass(u<wbr>int64_t allAvailableBits)<br>
 {<br>
  Â  Â double rateFactor, stepMult;<br>
@@ -1473,6 +1473,7 @@<br>
<br>
  Â  Â return q;<br>
 }<br>
+<br>
 double RateControl::countExpectedBits<wbr>(int startPos, int endPos)<br>
 {<br>
  Â  Â double expectedBits = 0;<br>
@@ -1484,6 +1485,7 @@<br>
  Â  Â }<br>
  Â  Â return expectedBits;<br>
 }<br>
+<br>
 bool RateControl::findUnderflow(dou<wbr>ble *fills, int *t0, int *t1, int over, int endPos)<br>
 {<br>
  Â  Â /* find an interval ending on an overflow or underflow (depending on whether<br>
@@ -1531,6 +1533,7 @@<br>
  Â  Â }<br>
  Â  Â return adjusted;<br>
 }<br>
+<br>
 bool RateControl::cuTreeReadFor2Pas<wbr>s(Frame* frame)<br>
 {<br>
  Â  Â int index = m_encOrder[frame->m_poc];<br>
@@ -1579,24 +1582,24 @@<br>
 double RateControl::tuneAbrQScaleFrom<wbr>Feedback(double qScale)<br>
 {<br>
  Â  Â double abrBuffer = 2 * m_rateTolerance * m_bitrate;<br>
-  Â  Â  Â  /* use framesDone instead of POC as poc count is not serial with bframes enabled */<br>
-  Â  Â  Â  double overflow = 1.0;<br>
-  Â  Â  Â  double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * m_frameDuration;<br>
-  Â  Â  Â  double wantedBits = timeDone * m_bitrate;<br>
-  Â  Â  Â  int64_t encodedBits = m_totalBits;<br>
-  Â  Â  Â  if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)<br>
-  Â  Â  Â  {<br>
-  Â  Â  Â  Â  Â  abrBuffer = m_param->totalFrames * (m_bitrate / m_fps);<br>
-  Â  Â  Â  Â  Â  encodedBits = m_encodedBits;<br>
-  Â  Â  Â  }<br>
+  Â  /* use framesDone instead of POC as poc count is not serial with bframes enabled */<br>
+  Â  double overflow = 1.0;<br>
+  Â  double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * m_frameDuration;<br>
+  Â  double wantedBits = timeDone * m_bitrate;<br>
+  Â  int64_t encodedBits = m_totalBits;<br>
+  Â  if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)<br>
+  Â  {<br>
+  Â  Â  Â  abrBuffer = m_param->totalFrames * (m_bitrate / m_fps);<br>
+  Â  Â  Â  encodedBits = m_encodedBits;<br>
+  Â  }<br>
<br>
-  Â  Â  Â  if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||<br>
-  Â  Â  Â  Â  Â  m_param->rc.bStrictCbr || m_isGrainEnabled))<br>
-  Â  Â  Â  {<br>
-  Â  Â  Â  Â  Â  abrBuffer *= X265_MAX(1, sqrt(timeDone));<br>
-  Â  Â  Â  Â  Â  overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) / abrBuffer);<br>
-  Â  Â  Â  Â  Â  qScale *= overflow;<br>
-  Â  Â  Â  }<br>
+  Â  if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||<br>
+  Â  Â  Â  m_param->rc.bStrictCbr || m_isGrainEnabled))<br>
+  Â  {<br>
+  Â  Â  Â  abrBuffer *= X265_MAX(1, sqrt(timeDone));<br>
+  Â  Â  Â  overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) / abrBuffer);<br>
+  Â  Â  Â  qScale *= overflow;<br>
+  Â  }<br>
  Â  Â return qScale;<br>
 }<br>
<br>
@@ -2330,17 +2333,18 @@<br>
  Â  Â return totalSatdBits + encodedBitsSoFar;<br>
 }<br>
<br>
-int RateControl::rowVbvRateControl<wbr>(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv)<br>
+int RateControl::rowVbvRateControl<wbr>(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv, uint32_t* m_sliceBaseRow, uint32_t sliceId)<br>
 {<br>
  Â  Â FrameData& curEncData = *curFrame->m_encData;<br>
  Â  Â double qScaleVbv = x265_qp2qScale(qpVbv);<br>
  Â  Â uint64_t rowSatdCost = curEncData.m_rowStat[row].rowS<wbr>atd;<br>
  Â  Â double encodedBits = curEncData.m_rowStat[row].enco<wbr>dedBits;<br>
+  Â  uint32_t rowInSlice = row - m_sliceBaseRow[sliceId];<br>
<br>
-  Â  if (m_param->bEnableWavefront && row == 1)<br>
+  Â  if (m_param->bEnableWavefront && rowInSlice == 1)<br>
  Â  Â {<br>
-  Â  Â  Â  rowSatdCost += curEncData.m_rowStat[0].rowSat<wbr>d;<br>
-  Â  Â  Â  encodedBits += curEncData.m_rowStat[0].encode<wbr>dBits;<br>
+  Â  Â  Â  rowSatdCost += curEncData.m_rowStat[row - 1].rowSatd;<br>
+  Â  Â  Â  encodedBits += curEncData.m_rowStat[row - 1].encodedBits;<br>
  Â  Â }<br>
  Â  Â rowSatdCost >>= X265_DEPTH - 8;<br>
  Â  Â updatePredictor(rce->rowPred[<wbr>0], qScaleVbv, (double)rowSatdCost, encodedBits);<br>
@@ -2350,8 +2354,8 @@<br>
  Â  Â  Â  Â if (qpVbv < refFrame->m_encData->m_rowStat<wbr>[row].rowQp)<br>
  Â  Â  Â  Â {<br>
  Â  Â  Â  Â  Â  Â uint64_t intraRowSatdCost = curEncData.m_rowStat[row].rowI<wbr>ntraSatd;<br>
-  Â  Â  Â  Â  Â  if (m_param->bEnableWavefront && row == 1)<br>
-  Â  Â  Â  Â  Â  Â  Â  intraRowSatdCost += curEncData.m_rowStat[0].rowInt<wbr>raSatd;<br>
+  Â  Â  Â  Â  Â  if (m_param->bEnableWavefront && rowInSlice == 1)<br>
+  Â  Â  Â  Â  Â  Â  Â  intraRowSatdCost += curEncData.m_rowStat[row - 1].rowIntraSatd;<br>
  Â  Â  Â  Â  Â  Â intraRowSatdCost >>= X265_DEPTH - 8;<br>
  Â  Â  Â  Â  Â  Â updatePredictor(rce->rowPred[<wbr>1], qScaleVbv, (double)intraRowSatdCost, encodedBits);<br>
  Â  Â  Â  Â }<br>
@@ -2376,7 +2380,7 @@<br>
  Â  Â const SPS& sps = *curEncData.m_slice->m_sps;<br>
  Â  Â double maxFrameError = X265_MAX(0.05, 1.0 / sps.numCuInHeight);<br>
<br>
-  Â  if (row < sps.numCuInHeight - 1)<br>
+  Â  if (row < m_sliceBaseRow[sliceId + 1] - 1)<br>
  Â  Â {<br>
  Â  Â  Â  Â /* More threads means we have to be more cautious in letting ratecontrol use up extra bits. */<br>
  Â  Â  Â  Â double rcTol = bufferLeftPlanned / m_param->frameNumThreads * m_rateTolerance;<br>
@@ -2693,8 +2697,8 @@<br>
  Â  Â  Â  Â  Â  Â m_encodedBitsWindow[pos % s_slidingWindowFrames] = actualBits;<br>
  Â  Â  Â  Â if(rce->sliceType != I_SLICE)<br>
  Â  Â  Â  Â {<br>
-  Â  Â  Â  int qp = int (rce->qpaRc + 0.5);<br>
-  Â  Â  Â  m_qpToEncodedBits[qp] =  m_qpToEncodedBits[qp] == 0 ? actualBits : (m_qpToEncodedBits[qp] + actualBits) * 0.5;<br>
+  Â  Â  Â  Â  Â  int qp = int (rce->qpaRc + 0.5);<br>
+  Â  Â  Â  Â  Â  m_qpToEncodedBits[qp] =  m_qpToEncodedBits[qp] == 0 ? actualBits : (m_qpToEncodedBits[qp] + actualBits) * 0.5;<br>
  Â  Â  Â  Â }<br>
  Â  Â  Â  Â curFrame->m_rcData->wantedBit<wbr>sWindow = m_wantedBitsWindow;<br>
  Â  Â  Â  Â curFrame->m_rcData->cplxrSum = m_cplxrSum;<br>
@@ -2779,7 +2783,8 @@<br>
  Â  Â  Â  Â  Â  Â curFrame->m_encData->m_frameS<wbr>tats.percent8x8Skip  * m_ncu) < 0)<br>
  Â  Â  Â  Â  Â  Â goto writeFailure;<br>
  Â  Â }<br>
-  Â  else{<br>
+  Â  else<br>
+  Â  {<br>
  Â  Â  Â  Â RPS* rpsWriter = &curFrame->m_encData->m_slice-<wbr>>m_rps;<br>
  Â  Â  Â  Â int i, num = rpsWriter->numberOfPictures;<br>
  Â  Â  Â  Â char deltaPOC[128];<br>
</div></div>diff -r e62b12bd8b45 -r c838e60c7c6b source/encoder/ratecontrol.h<br>
--- a/source/encoder/ratecontrol.<wbr>h  Â  Â  Thu Jun 29 13:13:56 2017 +0530<br>
+++ b/source/encoder/ratecontrol.<wbr>h  Â  Â  Fri Sep 22 20:20:58 2017 +0530<br>
</div></div><div class="m_4073142056016003513HOEnZb"><div class="m_4073142056016003513h5"><div><div class="h5">@@ -244,7 +244,7 @@<br>
  Â  Â int  rateControlStart(Frame* curFrame, RateControlEntry* rce, Encoder* enc);<br>
  Â  Â void rateControlUpdateStats(RateCon<wbr>trolEntry* rce);<br>
  Â  Â int  rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce, int *filler);<br>
-  Â  int  rowVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv);<br>
+  Â  int  rowVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv, uint32_t* m_sliceBaseRow, uint32_t sliceId);<br>
  Â  Â int  rateControlSliceType(int frameNum);<br>
  Â  Â bool cuTreeReadFor2Pass(Frame* curFrame);<br>
  Â  Â void hrdFullness(SEIBufferingPeriod<wbr>* sei);<br></div></div><span class="">
______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/l<wbr>istinfo/x265-devel</a><br>
</span></div></div></blockquote></div><br></div></div>
<br>______________________________<wbr>_________________<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" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
<br></blockquote></div><br></div>