[x265] [PATCH] Reorder miniGOP based on temporal layer hierarchy and add support for more B frame layers
Kirithika Kalirathnam
kirithika at multicorewareinc.com
Mon Dec 26 11:36:29 UTC 2022
>From 726b72802553ebcab1cc4758f3181f25a4f9105d Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 16 Dec 2022 19:05:38 +0530
Subject: [PATCH] Reorder miniGOP based on temporal layer hierarchy and add
support for more B frame layers
---
source/common/frame.h | 2 +
source/encoder/encoder.cpp | 8 +
source/encoder/slicetype.cpp | 570 +++++++++++++++++++++++++++++------
source/encoder/slicetype.h | 5 +
4 files changed, 491 insertions(+), 94 deletions(-)
diff --git a/source/common/frame.h b/source/common/frame.h
index 1ef0547bd..c916f7714 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -90,6 +90,7 @@ public:
int m_poc;
int m_encodeOrder;
+ int m_gopOffset;
int64_t m_pts; // user provided
presentation time stamp
int64_t m_reorderedPts;
int64_t m_dts;
@@ -161,6 +162,7 @@ public:
/*Frame's temporal layer info*/
uint8_t m_tempLayer;
+ int8_t m_gopId;
Frame();
bool create(x265_param *param, float* quantOffsets);
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 91c0ae24f..51068a875 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -2307,6 +2307,14 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
analysis->numPartitions = m_param->num4x4Partitions;
x265_alloc_analysis_data(m_param, analysis);
}
+ if (m_param->bEnableTemporalSubLayers > 2)
+ {
+ //Re-assign temporalid if the current frame is at the end
of encode or when I slice is encountered
+ if ((frameEnc->m_poc == (m_param->totalFrames - 1)) ||
(frameEnc->m_lowres.sliceType == X265_TYPE_I) ||
(frameEnc->m_lowres.sliceType == X265_TYPE_IDR))
+ {
+ frameEnc->m_tempLayer = (int8_t)0;
+ }
+ }
/* determine references, setup RPS, etc */
m_dpb->prepareEncode(frameEnc);
diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
index 78977bed8..ca5c5ae4a 100644
--- a/source/encoder/slicetype.cpp
+++ b/source/encoder/slicetype.cpp
@@ -1082,6 +1082,24 @@ Lookahead::Lookahead(x265_param *param, ThreadPool*
pool)
m_resetRunningAvg = true;
m_segmentCountThreshold =
(uint32_t)(((float)((NUMBER_OF_SEGMENTS_IN_WIDTH *
NUMBER_OF_SEGMENTS_IN_HEIGHT) * 50) / 100) + 0.5);
+
+ if (m_param->bEnableTemporalSubLayers > 2)
+ {
+ switch (m_param->bEnableTemporalSubLayers)
+ {
+ case 3:
+ m_gopId = 0;
+ break;
+ case 4:
+ m_gopId = 1;
+ break;
+ case 5:
+ m_gopId = 2;
+ break;
+ default:
+ break;
+ }
+ }
}
#if DETAILED_CU_STATS
@@ -1793,6 +1811,53 @@ void PreLookaheadGroup::processTasks(int
workerThreadID)
m_lock.release();
}
+
+void Lookahead::placeBref(Frame** frames, int start, int end, int num, int
*brefs)
+{
+ int avg = (start + end) / 2;
+ if (m_param->bEnableTemporalSubLayers < 2)
+ {
+ (*frames[avg]).m_lowres.sliceType = X265_TYPE_BREF;
+ (*brefs)++;
+ return;
+ }
+ else
+ {
+ if (num <= 2)
+ return;
+ else
+ {
+ (*frames[avg]).m_lowres.sliceType = X265_TYPE_BREF;
+ (*brefs)++;
+ placeBref(frames, start, avg, avg - start, brefs);
+ placeBref(frames, avg + 1, end, end - avg, brefs);
+ return;
+ }
+ }
+}
+
+
+void Lookahead::compCostBref(Lowres **frames, int start, int end, int num)
+{
+ CostEstimateGroup estGroup(*this, frames);
+ int avg = (start + end) / 2;
+ if (num <= 2)
+ {
+ for (int i = start; i < end; i++)
+ {
+ estGroup.singleCost(start, end + 1, i + 1);
+ }
+ return;
+ }
+ else
+ {
+ estGroup.singleCost(start, end + 1, avg + 1);
+ compCostBref(frames, start, avg, avg - start);
+ compCostBref(frames, avg + 1, end, end - avg);
+ return;
+ }
+}
+
/* called by API thread or worker thread with inputQueueLock acquired */
void Lookahead::slicetypeDecide()
{
@@ -2038,137 +2103,454 @@ void Lookahead::slicetypeDecide()
break;
}
}
- if (bframes)
- list[bframes - 1]->m_lowres.bLastMiniGopBFrame = true;
- list[bframes]->m_lowres.leadingBframes = bframes;
- m_lastNonB = &list[bframes]->m_lowres;
- /* insert a bref into the sequence */
- if (m_param->bBPyramid && bframes > 1 && !brefs)
- {
- list[bframes / 2]->m_lowres.sliceType = X265_TYPE_BREF;
- brefs++;
- }
- /* calculate the frame costs ahead of time for estimateFrameCost while
we still have lowres */
- if (m_param->rc.rateControlMode != X265_RC_CQP)
+ if (m_param->bEnableTemporalSubLayers > 2)
{
- int p0, p1, b;
- /* For zero latency tuning, calculate frame cost to be used later
in RC */
- if (!maxSearch)
+ //Split the partial mini GOP into sub mini GOPs when temporal sub
layers are enabled
+ if (bframes < m_param->bframes)
{
- for (int i = 0; i <= bframes; i++)
- frames[i + 1] = &list[i]->m_lowres;
- }
+ int leftOver = bframes + 1;
+ int8_t gopId = m_gopId - 1;
+ int gopLen = x265_gop_ra_length[gopId];
+ int listReset = 0;
- /* estimate new non-B cost */
- p1 = b = bframes + 1;
- p0 = (IS_X265_TYPE_I(frames[bframes + 1]->sliceType)) ? b : 0;
+ m_outputLock.acquire();
- CostEstimateGroup estGroup(*this, frames);
+ while ((gopId >= 0) && (leftOver > 3))
+ {
+ if (leftOver < gopLen)
+ {
+ gopId = gopId - 1;
+ gopLen = x265_gop_ra_length[gopId];
+ continue;
+ }
+ else
+ {
+ int newbFrames = listReset + gopLen - 1;
+ //Re-assign GOP
+ list[newbFrames]->m_lowres.sliceType =
IS_X265_TYPE_I(list[newbFrames]->m_lowres.sliceType) ?
list[newbFrames]->m_lowres.sliceType : X265_TYPE_P;
+ if (newbFrames)
+ list[newbFrames - 1]->m_lowres.bLastMiniGopBFrame
= true;
+ list[newbFrames]->m_lowres.leadingBframes = newbFrames;
+ m_lastNonB = &list[newbFrames]->m_lowres;
+
+ /* insert a bref into the sequence */
+ if (m_param->bBPyramid && newbFrames)
+ {
+ placeBref(list, listReset, newbFrames, newbFrames
+ 1, &brefs);
+ }
+ if (m_param->rc.rateControlMode != X265_RC_CQP)
+ {
+ int p0, p1, b;
+ /* For zero latency tuning, calculate frame cost
to be used later in RC */
+ if (!maxSearch)
+ {
+ for (int i = listReset; i <= newbFrames; i++)
+ frames[i + 1] = &list[listReset +
i]->m_lowres;
+ }
- estGroup.singleCost(p0, p1, b);
+ /* estimate new non-B cost */
+ p1 = b = newbFrames + 1;
+ p0 = (IS_X265_TYPE_I(frames[newbFrames +
1]->sliceType)) ? b : listReset;
- if (bframes)
- {
- p0 = 0; // last nonb
- bool isp0available = frames[bframes + 1]->sliceType ==
X265_TYPE_IDR ? false : true;
+ CostEstimateGroup estGroup(*this, frames);
+
+ estGroup.singleCost(p0, p1, b);
+
+ if (newbFrames)
+ compCostBref(frames, listReset, newbFrames,
newbFrames + 1);
+ }
+
+ m_inputLock.acquire();
+ /* dequeue all frames from inputQueue that are about
to be enqueued
+ * in the output queue. The order is important because
Frame can
+ * only be in one list at a time */
+ int64_t pts[X265_BFRAME_MAX + 1];
+ for (int i = 0; i < gopLen; i++)
+ {
+ Frame *curFrame;
+ curFrame = m_inputQueue.popFront();
+ pts[i] = curFrame->m_pts;
+ maxSearch--;
+ }
+ m_inputLock.release();
+
+ int idx = 0;
+ /* add non-B to output queue */
+ list[newbFrames]->m_reorderedPts = pts[idx++];
+ list[newbFrames]->m_gopOffset = 0;
+ list[newbFrames]->m_gopId = gopId;
+ list[newbFrames]->m_tempLayer =
x265_gop_ra[gopId][0].layer;
+ m_outputQueue.pushBack(*list[newbFrames]);
+
+ /* add B frames to output queue */
+ int i = 1, j = 1;
+ while (i < gopLen)
+ {
+ int offset = listReset +
(x265_gop_ra[gopId][j].poc_offset - 1);
+ if (!list[offset] || offset == newbFrames)
+ continue;
+
+ // Assign gop offset and temporal layer of frames
+ list[offset]->m_gopOffset = j;
+ list[bframes]->m_gopId = gopId;
+ list[offset]->m_tempLayer =
x265_gop_ra[gopId][j++].layer;
+
+ list[offset]->m_reorderedPts = pts[idx++];
+ m_outputQueue.pushBack(*list[offset]);
+ i++;
+ }
+
+ listReset += gopLen;
+ leftOver = leftOver - gopLen;
+ gopId -= 1;
+ gopLen = (gopId >= 0) ? x265_gop_ra_length[gopId] : 0;
+ }
+ }
- for (b = 1; b <= bframes; b++)
+ if (leftOver > 0 && leftOver < 4)
{
- if (!isp0available)
- p0 = b;
+ int64_t pts[X265_BFRAME_MAX + 1];
+ int idx = 0;
- if (frames[b]->sliceType == X265_TYPE_B)
- for (p1 = b; frames[p1]->sliceType == X265_TYPE_B;
p1++)
- ; // find new nonb or bref
- else
- p1 = bframes + 1;
+ int newbFrames = listReset + leftOver - 1;
+ list[newbFrames]->m_lowres.sliceType =
IS_X265_TYPE_I(list[newbFrames]->m_lowres.sliceType) ?
list[newbFrames]->m_lowres.sliceType : X265_TYPE_P;
+ if (newbFrames)
+ list[newbFrames - 1]->m_lowres.bLastMiniGopBFrame
= true;
+ list[newbFrames]->m_lowres.leadingBframes = newbFrames;
+ m_lastNonB = &list[newbFrames]->m_lowres;
- estGroup.singleCost(p0, p1, b);
+ /* insert a bref into the sequence */
+ if (m_param->bBPyramid && (newbFrames- listReset) > 1)
+ placeBref(list, listReset, newbFrames, newbFrames + 1,
&brefs);
+
+ if (m_param->rc.rateControlMode != X265_RC_CQP)
+ {
+ int p0, p1, b;
+ /* For zero latency tuning, calculate frame cost to be
used later in RC */
+ if (!maxSearch)
+ {
+ for (int i = listReset; i <= newbFrames; i++)
+ frames[i + 1] = &list[listReset + i]->m_lowres;
+ }
+
+ /* estimate new non-B cost */
+ p1 = b = newbFrames + 1;
+ p0 = (IS_X265_TYPE_I(frames[newbFrames +
1]->sliceType)) ? b : listReset;
+
+ CostEstimateGroup estGroup(*this, frames);
+
+ estGroup.singleCost(p0, p1, b);
- if (frames[b]->sliceType == X265_TYPE_BREF)
+ if (newbFrames)
+ compCostBref(frames, listReset, newbFrames,
newbFrames + 1);
+ }
+
+ m_inputLock.acquire();
+ /* dequeue all frames from inputQueue that are about to be
enqueued
+ * in the output queue. The order is important because
Frame can
+ * only be in one list at a time */
+ for (int i = 0; i < leftOver; i++)
+ {
+ Frame *curFrame;
+ curFrame = m_inputQueue.popFront();
+ pts[i] = curFrame->m_pts;
+ maxSearch--;
+ }
+ m_inputLock.release();
+
+ m_lastNonB = &list[newbFrames]->m_lowres;
+ list[newbFrames]->m_reorderedPts = pts[idx++];
+ list[newbFrames]->m_gopOffset = 0;
+ list[newbFrames]->m_gopId = -1;
+ list[newbFrames]->m_tempLayer = 0;
+ m_outputQueue.pushBack(*list[newbFrames]);
+ if (brefs)
{
- p0 = b;
- isp0available = true;
+ for (int i = listReset; i < newbFrames; i++)
+ {
+ if (list[i]->m_lowres.sliceType == X265_TYPE_BREF)
+ {
+ list[i]->m_reorderedPts = pts[idx++];
+ list[i]->m_gopOffset = 0;
+ list[i]->m_gopId = -1;
+ list[i]->m_tempLayer = 0;
+ m_outputQueue.pushBack(*list[i]);
+ }
+ }
+ }
+
+ /* add B frames to output queue */
+ for (int i = listReset; i < newbFrames; i++)
+ {
+ /* push all the B frames into output queue except
B-ref, which already pushed into output queue */
+ if (list[i]->m_lowres.sliceType != X265_TYPE_BREF)
+ {
+ list[i]->m_reorderedPts = pts[idx++];
+ list[i]->m_gopOffset = 0;
+ list[i]->m_gopId = -1;
+ list[i]->m_tempLayer = 1;
+ m_outputQueue.pushBack(*list[i]);
+ }
}
}
}
- }
+ else
+ // Fill the complete mini GOP when temporal sub layers are enabled
+ {
- m_inputLock.acquire();
- /* dequeue all frames from inputQueue that are about to be enqueued
- * in the output queue. The order is important because Frame can
- * only be in one list at a time */
- int64_t pts[X265_BFRAME_MAX + 1];
- for (int i = 0; i <= bframes; i++)
- {
- Frame *curFrame;
- curFrame = m_inputQueue.popFront();
- pts[i] = curFrame->m_pts;
- maxSearch--;
- }
- m_inputLock.release();
+ list[bframes - 1]->m_lowres.bLastMiniGopBFrame = true;
+ list[bframes]->m_lowres.leadingBframes = bframes;
+ m_lastNonB = &list[bframes]->m_lowres;
- m_outputLock.acquire();
- /* add non-B to output queue */
- int idx = 0;
- list[bframes]->m_reorderedPts = pts[idx++];
- m_outputQueue.pushBack(*list[bframes]);
- /* Add B-ref frame next to P frame in output queue, the B-ref encode
before non B-ref frame */
- if (brefs)
- {
- for (int i = 0; i < bframes; i++)
+ /* insert a bref into the sequence */
+ if (m_param->bBPyramid && !brefs)
+ {
+ placeBref(list, 0, bframes, bframes + 1, &brefs);
+ }
+
+ /* calculate the frame costs ahead of time for
estimateFrameCost while we still have lowres */
+ if (m_param->rc.rateControlMode != X265_RC_CQP)
+ {
+ int p0, p1, b;
+ /* For zero latency tuning, calculate frame cost to be
used later in RC */
+ if (!maxSearch)
+ {
+ for (int i = 0; i <= bframes; i++)
+ frames[i + 1] = &list[i]->m_lowres;
+ }
+
+ /* estimate new non-B cost */
+ p1 = b = bframes + 1;
+ p0 = (IS_X265_TYPE_I(frames[bframes + 1]->sliceType)) ? b
: 0;
+
+ CostEstimateGroup estGroup(*this, frames);
+ estGroup.singleCost(p0, p1, b);
+
+ compCostBref(frames, 0, bframes, bframes + 1);
+ }
+
+ m_inputLock.acquire();
+ /* dequeue all frames from inputQueue that are about to be
enqueued
+ * in the output queue. The order is important because Frame can
+ * only be in one list at a time */
+ int64_t pts[X265_BFRAME_MAX + 1];
+ for (int i = 0; i <= bframes; i++)
+ {
+ Frame *curFrame;
+ curFrame = m_inputQueue.popFront();
+ pts[i] = curFrame->m_pts;
+ maxSearch--;
+ }
+ m_inputLock.release();
+
+ m_outputLock.acquire();
+
+ int idx = 0;
+ /* add non-B to output queue */
+ list[bframes]->m_reorderedPts = pts[idx++];
+ list[bframes]->m_gopOffset = 0;
+ list[bframes]->m_gopId = m_gopId;
+ list[bframes]->m_tempLayer = x265_gop_ra[m_gopId][0].layer;
+ m_outputQueue.pushBack(*list[bframes]);
+
+ int i = 1, j = 1;
+ while (i <= bframes)
+ {
+ int offset = x265_gop_ra[m_gopId][j].poc_offset - 1;
+ if (!list[offset] || offset == bframes)
+ continue;
+
+ // Assign gop offset and temporal layer of frames
+ list[offset]->m_gopOffset = j;
+ list[offset]->m_gopId = m_gopId;
+ list[offset]->m_tempLayer =
x265_gop_ra[m_gopId][j++].layer;
+
+ /* add B frames to output queue */
+ list[offset]->m_reorderedPts = pts[idx++];
+ m_outputQueue.pushBack(*list[offset]);
+ i++;
+ }
+ }
+
+ bool isKeyFrameAnalyse = (m_param->rc.cuTree ||
(m_param->rc.vbvBufferSize && m_param->lookaheadDepth));
+ if (isKeyFrameAnalyse && IS_X265_TYPE_I(m_lastNonB->sliceType))
{
- if (list[i]->m_lowres.sliceType == X265_TYPE_BREF)
+ m_inputLock.acquire();
+ Frame *curFrame = m_inputQueue.first();
+ frames[0] = m_lastNonB;
+ int j;
+ for (j = 0; j < maxSearch; j++)
{
- list[i]->m_reorderedPts = pts[idx++];
- m_outputQueue.pushBack(*list[i]);
+ frames[j + 1] = &curFrame->m_lowres;
+ curFrame = curFrame->m_next;
+ }
+ m_inputLock.release();
+
+ frames[j + 1] = NULL;
+ if (!m_param->rc.bStatRead)
+ slicetypeAnalyse(frames, true);
+ bool bIsVbv = m_param->rc.vbvBufferSize > 0 &&
m_param->rc.vbvMaxBitrate > 0;
+ if ((m_param->analysisLoad && m_param->scaleFactor && bIsVbv)
|| m_param->bliveVBV2pass)
+ {
+ int numFrames;
+ for (numFrames = 0; numFrames < maxSearch; numFrames++)
+ {
+ Lowres *fenc = frames[numFrames + 1];
+ if (!fenc)
+ break;
+ }
+ vbvLookahead(frames, numFrames, true);
}
}
- }
- /* add B frames to output queue */
- for (int i = 0; i < bframes; i++)
+
+ m_outputLock.release();
+ }
+ else
{
- /* push all the B frames into output queue except B-ref, which
already pushed into output queue */
- if (list[i]->m_lowres.sliceType != X265_TYPE_BREF)
+
+ if (bframes)
+ list[bframes - 1]->m_lowres.bLastMiniGopBFrame = true;
+ list[bframes]->m_lowres.leadingBframes = bframes;
+ m_lastNonB = &list[bframes]->m_lowres;
+
+ /* insert a bref into the sequence */
+ if (m_param->bBPyramid && bframes > 1 && !brefs)
{
- list[i]->m_reorderedPts = pts[idx++];
- m_outputQueue.pushBack(*list[i]);
+ placeBref(list, 0, bframes, bframes + 1, &brefs);
+ }
+ /* calculate the frame costs ahead of time for estimateFrameCost
while we still have lowres */
+ if (m_param->rc.rateControlMode != X265_RC_CQP)
+ {
+ int p0, p1, b;
+ /* For zero latency tuning, calculate frame cost to be used
later in RC */
+ if (!maxSearch)
+ {
+ for (int i = 0; i <= bframes; i++)
+ frames[i + 1] = &list[i]->m_lowres;
+ }
+
+ /* estimate new non-B cost */
+ p1 = b = bframes + 1;
+ p0 = (IS_X265_TYPE_I(frames[bframes + 1]->sliceType)) ? b : 0;
+
+ CostEstimateGroup estGroup(*this, frames);
+ estGroup.singleCost(p0, p1, b);
+
+ if (m_param->bEnableTemporalSubLayers > 1 && bframes)
+ {
+ compCostBref(frames, 0, bframes, bframes + 1);
+ }
+ else
+ {
+ if (bframes)
+ {
+ p0 = 0; // last nonb
+ bool isp0available = frames[bframes + 1]->sliceType ==
X265_TYPE_IDR ? false : true;
+
+ for (b = 1; b <= bframes; b++)
+ {
+ if (!isp0available)
+ p0 = b;
+
+ if (frames[b]->sliceType == X265_TYPE_B)
+ for (p1 = b; frames[p1]->sliceType ==
X265_TYPE_B; p1++)
+ ; // find new nonb or bref
+ else
+ p1 = bframes + 1;
+
+ estGroup.singleCost(p0, p1, b);
+
+ if (frames[b]->sliceType == X265_TYPE_BREF)
+ {
+ p0 = b;
+ isp0available = true;
+ }
+ }
+ }
+ }
}
- }
- bool isKeyFrameAnalyse = (m_param->rc.cuTree ||
(m_param->rc.vbvBufferSize && m_param->lookaheadDepth));
- if (isKeyFrameAnalyse && IS_X265_TYPE_I(m_lastNonB->sliceType))
- {
m_inputLock.acquire();
- Frame *curFrame = m_inputQueue.first();
- frames[0] = m_lastNonB;
- int j;
- for (j = 0; j < maxSearch; j++)
+ /* dequeue all frames from inputQueue that are about to be enqueued
+ * in the output queue. The order is important because Frame can
+ * only be in one list at a time */
+ int64_t pts[X265_BFRAME_MAX + 1];
+ for (int i = 0; i <= bframes; i++)
{
- frames[j + 1] = &curFrame->m_lowres;
- curFrame = curFrame->m_next;
+ Frame *curFrame;
+ curFrame = m_inputQueue.popFront();
+ pts[i] = curFrame->m_pts;
+ maxSearch--;
}
m_inputLock.release();
- frames[j + 1] = NULL;
- if (!m_param->rc.bStatRead)
- slicetypeAnalyse(frames, true);
- bool bIsVbv = m_param->rc.vbvBufferSize > 0 &&
m_param->rc.vbvMaxBitrate > 0;
- if ((m_param->analysisLoad && m_param->scaleFactor && bIsVbv) ||
m_param->bliveVBV2pass)
+ m_outputLock.acquire();
+
+ /* add non-B to output queue */
+ int idx = 0;
+ list[bframes]->m_reorderedPts = pts[idx++];
+ m_outputQueue.pushBack(*list[bframes]);
+
+ /* Add B-ref frame next to P frame in output queue, the B-ref
encode before non B-ref frame */
+ if (brefs)
{
- int numFrames;
- for (numFrames = 0; numFrames < maxSearch; numFrames++)
+ for (int i = 0; i < bframes; i++)
{
- Lowres *fenc = frames[numFrames + 1];
- if (!fenc)
- break;
+ if (list[i]->m_lowres.sliceType == X265_TYPE_BREF)
+ {
+ list[i]->m_reorderedPts = pts[idx++];
+ m_outputQueue.pushBack(*list[i]);
+ }
+ }
+ }
+
+ /* add B frames to output queue */
+ for (int i = 0; i < bframes; i++)
+ {
+ /* push all the B frames into output queue except B-ref, which
already pushed into output queue */
+ if (list[i]->m_lowres.sliceType != X265_TYPE_BREF)
+ {
+ list[i]->m_reorderedPts = pts[idx++];
+ m_outputQueue.pushBack(*list[i]);
+ }
+ }
+
+
+ bool isKeyFrameAnalyse = (m_param->rc.cuTree ||
(m_param->rc.vbvBufferSize && m_param->lookaheadDepth));
+ if (isKeyFrameAnalyse && IS_X265_TYPE_I(m_lastNonB->sliceType))
+ {
+ m_inputLock.acquire();
+ Frame *curFrame = m_inputQueue.first();
+ frames[0] = m_lastNonB;
+ int j;
+ for (j = 0; j < maxSearch; j++)
+ {
+ frames[j + 1] = &curFrame->m_lowres;
+ curFrame = curFrame->m_next;
+ }
+ m_inputLock.release();
+
+ frames[j + 1] = NULL;
+ if (!m_param->rc.bStatRead)
+ slicetypeAnalyse(frames, true);
+ bool bIsVbv = m_param->rc.vbvBufferSize > 0 &&
m_param->rc.vbvMaxBitrate > 0;
+ if ((m_param->analysisLoad && m_param->scaleFactor && bIsVbv)
|| m_param->bliveVBV2pass)
+ {
+ int numFrames;
+ for (numFrames = 0; numFrames < maxSearch; numFrames++)
+ {
+ Lowres *fenc = frames[numFrames + 1];
+ if (!fenc)
+ break;
+ }
+ vbvLookahead(frames, numFrames, true);
}
- vbvLookahead(frames, numFrames, true);
}
+
+ m_outputLock.release();
}
- m_outputLock.release();
}
void Lookahead::vbvLookahead(Lowres **frames, int numFrames, int keyframe)
diff --git a/source/encoder/slicetype.h b/source/encoder/slicetype.h
index 05cef800b..f4184e4e2 100644
--- a/source/encoder/slicetype.h
+++ b/source/encoder/slicetype.h
@@ -200,6 +200,8 @@ public:
bool m_resetRunningAvg;
uint32_t m_segmentCountThreshold;
+ int8_t m_gopId;
+
Lookahead(x265_param *param, ThreadPool *pool);
#if DETAILED_CU_STATS
int64_t m_slicetypeDecideElapsedTime;
@@ -251,6 +253,9 @@ protected:
/* called by getEstimatedPictureCost() to finalize cuTree costs */
int64_t frameCostRecalculate(Lowres **frames, int p0, int p1, int b);
+ /*Compute index for positioning B-Ref frames*/
+ void placeBref(Frame** frames, int start, int end, int num, int
*brefs);
+ void compCostBref(Lowres **frame, int start, int end, int num);
};
class PreLookaheadGroup : public BondedTaskGroup
--
2.28.0.windows.1
*Thanks,*
*Kirithika*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20221226/626ae7a2/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-4.diff
Type: application/octet-stream
Size: 27560 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20221226/626ae7a2/attachment-0001.obj>
More information about the x265-devel
mailing list