[x265] [PATCH MV-HEVC 05/10] Add encoding and reconstruction support for multiview
Anusuya Kumarasamy
anusuya.kumarasamy at multicorewareinc.com
Tue Aug 6 10:49:13 UTC 2024
>From 120d31502652ba9e5eccbf4627be2094b2cb2e92 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 12 Jul 2024 16:03:28 +0530
Subject: [PATCH 05/10] This commit does the following things:
1.Extend the encoding and reconstruction support for multiview
2.Add support for reference picture set construction
---
source/abrEncApp.cpp | 25 ++++------
source/common/param.cpp | 3 ++
source/common/picyuv.h | 2 +-
source/common/slice.cpp | 60 +++++++++++++++++++++++-
source/common/slice.h | 11 ++---
source/encoder/api.cpp | 6 +--
source/encoder/dpb.cpp | 7 +++
source/encoder/encoder.cpp | 82 +++++++++++++++++++++------------
source/encoder/encoder.h | 10 ++--
source/encoder/frameencoder.cpp | 14 +++---
source/encoder/frameencoder.h | 36 +++++++--------
source/encoder/search.cpp | 6 ++-
source/x265.h | 6 +++
source/x265cli.cpp | 13 +++---
source/x265cli.h | 4 +-
15 files changed, 190 insertions(+), 95 deletions(-)
diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp
index 6874c4d74..b14db5900 100644
--- a/source/abrEncApp.cpp
+++ b/source/abrEncApp.cpp
@@ -594,15 +594,10 @@ ret:
pic_in[view] = &pic_orig[view];
/* Allocate recon picture if analysis save/load is enabled */
std::priority_queue<int64_t>* pts_queue =
m_cliopt.output->needPTS() ? new std::priority_queue<int64_t>() : NULL;
-#if ENABLE_MULTIVIEW
- x265_picture* pic_recon[MAX_VIEWS];
- x265_picture pic_out[MAX_VIEWS];
- for (int i = 0; i < m_param->numViews; i++)
-#else
- x265_picture* pic_recon[MAX_SCALABLE_LAYERS];
- x265_picture pic_out[MAX_SCALABLE_LAYERS];
- for (int i = 0; i < m_param->numScalableLayers; i++)
-#endif
+ x265_picture* pic_recon[MAX_LAYERS];
+ x265_picture pic_out[MAX_LAYERS];
+
+ for (int i = 0; i < m_param->numLayers; i++)
pic_recon[i] = (m_cliopt.recon[i] || m_param->analysisSave
|| m_param->analysisLoad || pts_queue || reconPlay || m_param->csvLogLevel)
? &pic_out[i] : NULL;
uint32_t inFrameCount = 0;
uint32_t outFrameCount = 0;
@@ -818,10 +813,10 @@ ret:
copyInfo(analysisInfo);
}
- for (int i = 0; i < m_param->numScalableLayers; i++)
+ for (int layer = 0; layer < m_param->numLayers;
layer++)
{
- if (numEncoded && pic_recon[i] &&
m_cliopt.recon[i])
- m_cliopt.recon[i]->writePicture(pic_out[i]);
+ if (numEncoded && pic_recon[layer] &&
m_cliopt.recon[layer])
+
m_cliopt.recon[layer]->writePicture(pic_out[layer]);
}
if (nal)
{
@@ -856,10 +851,10 @@ ret:
copyInfo(analysisInfo);
}
- for (int i = 0; i < m_param->numScalableLayers; i++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
- if (numEncoded && pic_recon[i] && m_cliopt.recon[i])
- m_cliopt.recon[i]->writePicture(pic_out[i]);
+ if (numEncoded && pic_recon[layer] &&
m_cliopt.recon[layer])
+
m_cliopt.recon[layer]->writePicture(pic_out[layer]);
}
if (nal)
{
diff --git a/source/common/param.cpp b/source/common/param.cpp
index c2efb11cf..8b7d268d2 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -406,6 +406,8 @@ void x265_param_default(x265_param* param)
/* Multi-View Encoding*/
param->numViews = 1;
+
+ param->numLayers = 1;
}
int x265_param_default_preset(x265_param* param, const char* preset, const
char* tune)
@@ -2916,6 +2918,7 @@ void x265_copy_params(x265_param* dst, x265_param*
src)
#if ENABLE_MULTIVIEW
dst->numViews = src->numViews;
#endif
+ dst->numLayers = src->numLayers;
if (src->videoSignalTypePreset) dst->videoSignalTypePreset =
strdup(src->videoSignalTypePreset);
else dst->videoSignalTypePreset = NULL;
diff --git a/source/common/picyuv.h b/source/common/picyuv.h
index ec9ff69c2..89d843f38 100644
--- a/source/common/picyuv.h
+++ b/source/common/picyuv.h
@@ -83,7 +83,7 @@ public:
void destroy();
int getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t
picCsp);
- void copyFromPicture(const x265_picture&, const x265_param& param,
int padx, int pady, bool isBase);
+ void copyFromPicture(const x265_picture&, const x265_param& param,
int padx, int pady, bool isBase = true);
void copyFromFrame(PicYuv* source);
intptr_t getChromaAddrOffset(uint32_t ctuAddr, uint32_t absPartIdx)
const { return m_cuOffsetC[ctuAddr] + m_buOffsetC[absPartIdx]; }
diff --git a/source/common/slice.cpp b/source/common/slice.cpp
index dd257b48d..7f62695ee 100644
--- a/source/common/slice.cpp
+++ b/source/common/slice.cpp
@@ -29,7 +29,31 @@
using namespace X265_NS;
-void Slice::setRefPicList(PicList& picList, int sLayerId)
+#if ENABLE_MULTIVIEW
+void Slice::createInterLayerReferencePictureSet(PicList& picList, PicList&
refPicSetInterLayer0, PicList& refPicSetInterLayer1)
+{
+
+ for (int i = 0; i < 1; i++)
+ {
+ int layerIdRef = 0;// getRefPicLayerId(i);
+ Frame* refPic = picList.getPOC(m_poc, 0);
+ int viewIdCur = 0;
+ int viewIdZero = 1;
+ int viewIdRef = 1;
+
+ if ((viewIdCur <= viewIdZero && viewIdCur <= viewIdRef) ||
(viewIdCur >= viewIdZero && viewIdCur >= viewIdRef))
+ {
+ refPicSetInterLayer0.pushBackSubDPB(*refPic);
+ }
+ else
+ {
+ refPicSetInterLayer1.pushBackSubDPB(*refPic);
+ }
+ }
+}
+#endif
+
+void Slice::setRefPicList(PicList& picList, PicList& refPicSetInterLayer0,
PicList& refPicSetInterLayer1, int sLayerId)
{
if (m_sliceType == I_SLICE)
{
@@ -75,18 +99,34 @@ void Slice::setRefPicList(PicList& picList, int
sLayerId)
// ref_pic_list_init
Frame* rpsCurrList0[MAX_NUM_REF + 1];
Frame* rpsCurrList1[MAX_NUM_REF + 1];
+#if ENABLE_MULTIVIEW
+ int numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr +
refPicSetInterLayer0.size() + refPicSetInterLayer1.size();
+#else
int numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr;
+#endif
int cIdx = 0;
for (i = 0; i < numPocStCurr0; i++, cIdx++)
rpsCurrList0[cIdx] = refPicSetStCurr0[i];
+#if ENABLE_MULTIVIEW
+ if (m_param->numViews > 1)
+ for (i = 0; i < refPicSetInterLayer0.size(); i++, cIdx++)
+ rpsCurrList0[cIdx] = refPicSetInterLayer0.getPOC(m_poc, 0);
+#endif
+
for (i = 0; i < numPocStCurr1; i++, cIdx++)
rpsCurrList0[cIdx] = refPicSetStCurr1[i];
for (i = 0; i < numPocLtCurr; i++, cIdx++)
rpsCurrList0[cIdx] = refPicSetLtCurr[i];
+#if ENABLE_MULTIVIEW
+ if (m_param->numViews > 1)
+ for (i = 0; i < refPicSetInterLayer1.size(); i++, cIdx++)
+ rpsCurrList0[cIdx] = refPicSetInterLayer1.getPOC(m_poc, 0);
+#endif
+
X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n");
if (m_sliceType == B_SLICE)
@@ -95,12 +135,24 @@ void Slice::setRefPicList(PicList& picList, int
sLayerId)
for (i = 0; i < numPocStCurr1; i++, cIdx++)
rpsCurrList1[cIdx] = refPicSetStCurr1[i];
+#if ENABLE_MULTIVIEW
+ if (m_param->numViews > 1)
+ for (i = 0; i < refPicSetInterLayer1.size(); i++, cIdx++)
+ rpsCurrList1[cIdx] = refPicSetInterLayer1.getPOC(m_poc, 0);
+#endif
+
for (i = 0; i < numPocStCurr0; i++, cIdx++)
rpsCurrList1[cIdx] = refPicSetStCurr0[i];
for (i = 0; i < numPocLtCurr; i++, cIdx++)
rpsCurrList1[cIdx] = refPicSetLtCurr[i];
+#if ENABLE_MULTIVIEW
+ if (m_param->numViews > 1)
+ for (i = 0; i < refPicSetInterLayer0.size(); i++, cIdx++)
+ rpsCurrList1[cIdx] = refPicSetInterLayer0.getPOC(m_poc, 0);
+#endif
+
X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n");
}
@@ -109,6 +161,9 @@ void Slice::setRefPicList(PicList& picList, int
sLayerId)
cIdx = rIdx % numPocTotalCurr;
X265_CHECK(cIdx >= 0 && cIdx < numPocTotalCurr, "RPS index check
fail\n");
m_refFrameList[0][rIdx] = rpsCurrList0[cIdx];
+#if ENABLE_MULTIVIEW
+ m_refFrameList[0][rIdx] = rpsCurrList0[cIdx];
+#endif
}
if (m_sliceType != B_SLICE)
@@ -123,6 +178,9 @@ void Slice::setRefPicList(PicList& picList, int
sLayerId)
cIdx = rIdx % numPocTotalCurr;
X265_CHECK(cIdx >= 0 && cIdx < numPocTotalCurr, "RPS index
check fail\n");
m_refFrameList[1][rIdx] = rpsCurrList1[cIdx];
+#if ENABLE_MULTIVIEW
+ m_refFrameList[1][rIdx] = rpsCurrList1[cIdx];
+#endif
}
}
diff --git a/source/common/slice.h b/source/common/slice.h
index 9a05840a0..90009ae7f 100644
--- a/source/common/slice.h
+++ b/source/common/slice.h
@@ -109,11 +109,7 @@ namespace Level {
struct ProfileTierLevel
{
-#if ENABLE_MULTIVIEW
- int profileIdc[MAX_VIEWS];
-#else
- int profileIdc[MAX_SCALABLE_LAYERS];
-#endif
+ int profileIdc[MAX_LAYERS];
int levelIdc;
uint32_t minCrForLevel;
uint32_t maxLumaSrForLevel;
@@ -425,7 +421,10 @@ public:
void disableWeights();
- void setRefPicList(PicList& picList, int sLayerId);
+ void setRefPicList(PicList& picList, PicList& refPicSetInterLayer0,
PicList& refPicSetInterLayer1, int viewId);
+#if ENABLE_MULTIVIEW
+ void createInterLayerReferencePictureSet(PicList& picList, PicList&
refPicSetInterLayer0, PicList& refPicSetInterLayer1);
+#endif
bool getRapPicFlag() const
{
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 88bc25550..96baf56c9 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -603,7 +603,7 @@ fail:
if (numEncoded && encoder->m_param->csvLogLevel &&
encoder->m_outputCount >= encoder->m_latestParam->chunkStart)
{
- for (int layer = 0; layer < encoder->m_param->numScalableLayers;
layer++)
+ for (int layer = 0; layer < encoder->m_param->numLayers; layer++)
x265_csvlog_frame(encoder->m_param, pic_out[layer]);
}
@@ -656,10 +656,10 @@ void x265_encoder_log(x265_encoder* enc, int argc,
char **argv)
if (enc)
{
Encoder *encoder = static_cast<Encoder*>(enc);
- x265_stats stats[MAX_SCALABLE_LAYERS];
+ x265_stats stats[MAX_LAYERS];
int padx = encoder->m_sps.conformanceWindow.rightOffset;
int pady = encoder->m_sps.conformanceWindow.bottomOffset;
- for (int layer = 0; layer < encoder->m_param->numScalableLayers;
layer++)
+ for (int layer = 0; layer < encoder->m_param->numLayers; layer++)
{
encoder->fetchStats(stats, sizeof(stats[layer]), layer);
x265_csvlog_encode(encoder->m_param, &stats[0], padx, pady,
argc, argv);
diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp
index bce49b500..3b4934df5 100644
--- a/source/encoder/dpb.cpp
+++ b/source/encoder/dpb.cpp
@@ -328,6 +328,13 @@ void DPB::computeRPS(int curPoc, int tempId, bool
isRAP, RPS * rps, unsigned int
{
if ((!m_bTemporalSublayer || (iterPic->m_tempLayer <= tempId))
&& ((m_lastIDR >= curPoc) || (m_lastIDR <= iterPic->m_poc)))
{
+#if ENABLE_MULTIVIEW
+ if (layer && numNeg ==
iterPic->m_param->maxNumReferences - 1 && (iterPic->m_poc - curPoc) < 0)
+ {
+ iterPic = iterPic->m_next;
+ continue;
+ }
+#endif
rps->poc[poci] = iterPic->m_poc;
rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
(rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index ef152f2ae..8a1ed9d88 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -149,7 +149,7 @@ Encoder::Encoder()
m_rpsInSpsCount = 0;
m_cB = 1.0;
m_cR = 1.0;
- for (int i = 0; i < MAX_SCALABLE_LAYERS; i++)
+ for (int i = 0; i < MAX_LAYERS; i++)
m_exportedPic[i] = NULL;
for (int i = 0; i < X265_MAX_FRAME_THREADS; i++)
m_frameEncoder[i] = NULL;
@@ -862,7 +862,7 @@ void Encoder::destroy()
X265_FREE(m_rdCost);
X265_FREE(m_trainingCount);
}
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
if (m_exportedPic[layer])
{
@@ -1488,7 +1488,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
if (!m_param->bUseAnalysisFile && m_param->analysisSave)
x265_free_analysis_data(m_param,
&m_exportedPic[0]->m_analysisData);
- for (int i = 0; i < m_param->numScalableLayers; i++)
+ for (int i = 0; i < m_param->numLayers; i++)
{
ATOMIC_DEC(&m_exportedPic[i]->m_countRefEncoders);
m_exportedPic[i] = NULL;
@@ -1587,19 +1587,18 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
}
x265_param* p = (m_reconfigure || m_reconfigureRc) ? m_latestParam
: m_param;
-#if ENABLE_MULTIVIEW
- Frame* inFrame[MAX_VIEWS];
- for (int layer = 0; layer < m_param->numViews; layer++)
-#else
- Frame* inFrame[MAX_SCALABLE_LAYERS];
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
-#endif
+ Frame* inFrame[MAX_LAYERS];
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
if (m_dpb->m_freeList.empty())
{
inFrame[layer] = new Frame;
inFrame[layer]->m_encodeStartTime = x265_mdate();
+#if ENABLE_MULTIVIEW
+ inFrame[layer]->m_viewId = layer;
+#else
inFrame[layer]->m_sLayerId = layer;
+#endif
inFrame[layer]->m_valid = false;
if (inFrame[layer]->create(p,
inputPic[layer]->quantOffsets))
{
@@ -1670,10 +1669,43 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
#endif
inFrame[layer]->m_valid = false;
inFrame[layer]->m_lowres.bKeyframe = false;
+#if ENABLE_MULTIVIEW
+ //Destroy interlayer References
+ //TODO Move this to end(after compress frame)
+ if (inFrame[layer]->refPicSetInterLayer0.size())
+ {
+ Frame* iterFrame =
inFrame[layer]->refPicSetInterLayer0.first();
+
+ while (iterFrame)
+ {
+ Frame* curFrame = iterFrame;
+ iterFrame = iterFrame->m_nextSubDPB;
+
inFrame[layer]->refPicSetInterLayer0.removeSubDPB(*curFrame);
+ iterFrame =
inFrame[layer]->refPicSetInterLayer0.first();
+ }
+ }
+
+ if (inFrame[layer]->refPicSetInterLayer1.size())
+ {
+ Frame* iterFrame =
inFrame[layer]->refPicSetInterLayer1.first();
+
+ while (iterFrame)
+ {
+ Frame* curFrame = iterFrame;
+ iterFrame = iterFrame->m_nextSubDPB;
+
inFrame[layer]->refPicSetInterLayer1.removeSubDPB(*curFrame);
+ iterFrame =
inFrame[layer]->refPicSetInterLayer1.first();
+ }
+ }
+#endif
}
/* Copy input picture into a Frame and PicYuv, send to
lookahead */
+#if ENABLE_ALPHA
inFrame[layer]->m_fencPic->copyFromPicture(*inputPic[layer],
*m_param, m_sps.conformanceWindow.rightOffset,
m_sps.conformanceWindow.bottomOffset, !layer);
+#else
+ inFrame[layer]->m_fencPic->copyFromPicture(*inputPic[layer],
*m_param, m_sps.conformanceWindow.rightOffset,
m_sps.conformanceWindow.bottomOffset);
+#endif
inFrame[layer]->m_poc = (!layer) ? (++m_pocLast) : m_pocLast;
inFrame[layer]->m_userData = inputPic[0]->userData;
@@ -1919,7 +1951,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
* input picture before returning so the order must be reversed. This
do/while() loop allows
* us to alternate the order of the calls without ugly code
replication */
Frame** outFrames = { NULL };
- Frame* frameEnc[MAX_SCALABLE_LAYERS] = { NULL };
+ Frame* frameEnc[MAX_LAYERS] = { NULL };
int pass = 0;
do
{
@@ -1930,7 +1962,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
outFrames = curEncoder->getEncodedPicture(m_nalList);
if (outFrames)
{
- for (int sLayer = 0; sLayer < m_param->numScalableLayers;
sLayer++)
+ for (int sLayer = 0; sLayer < m_param->numLayers; sLayer++)
{
Frame* outFrame = *(outFrames + sLayer);
Slice* slice = outFrame->m_encData->m_slice;
@@ -2163,7 +2195,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
m_outputCount++;
if (m_param->chunkEnd == m_outputCount)
m_numDelayedPic = 0;
- else if (outFrame->m_sLayerId == m_param->bEnableAlpha)
+ else if (sLayer == m_param->numLayers -1)
m_numDelayedPic--;
ret = 1;
@@ -2176,10 +2208,10 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
frameEnc[0] = m_lookahead->getDecidedPicture();
if (frameEnc[0] && !pass && (!m_param->chunkEnd ||
(m_encodedFrameNum < m_param->chunkEnd)))
{
+
#if ENABLE_ALPHA || ENABLE_MULTIVIEW
//Pop non base view pictures from DPB piclist
- int numLayers = m_param->numViews > 1 ? m_param->numViews :
(m_param->numScalableLayers > 1) ? m_param->numScalableLayers : 1;
- for (int layer = 1; layer < numLayers; layer++)
+ for (int layer = 1; layer < m_param->numLayers; layer++)
{
Frame* currentFrame =
m_dpb->m_picList.getPOC(frameEnc[0]->m_poc, layer);
frameEnc[layer] =
m_dpb->m_picList.removeFrame(*currentFrame);
@@ -2254,7 +2286,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
curEncoder->m_reconfigure = m_reconfigure;
/* give this frame a FrameData instance before encoding */
- for (int layer = 0; layer < m_param->numScalableLayers;
layer++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
if (m_dpb->m_frameDataFreeList)
{
@@ -2385,7 +2417,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
}
}
/* determine references, setup RPS, etc */
- for (int layer = 0; layer < m_param->numScalableLayers;
layer++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
m_dpb->prepareEncode(frameEnc[layer]);
if (m_param->bEnableTemporalFilter)
@@ -2407,7 +2439,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
m_origPicBuffer->setOrigPicList(frameEnc[0], m_pocLast);
}
- for (int layer = 0; layer < m_param->numScalableLayers;
layer++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
if (!!m_param->selectiveSAO)
{
@@ -2762,7 +2794,7 @@ void Encoder::printSummary()
if (m_param->logLevel < X265_LOG_INFO)
return;
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
char buffer[200];
if (m_analyzeI[layer].m_numPics)
@@ -3316,11 +3348,7 @@ void Encoder::getStreamHeaders(NALList& list,
Entropy& sbacCoder, Bitstream& bs)
bs.writeByteAlignment();
list.serialize(NAL_UNIT_VPS, bs);
-#if ENABLE_MULTIVIEW
- for (int layer = 0; layer < m_param->numViews; layer++)
-#else
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
-#endif
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
bs.resetBits();
sbacCoder.codeSPS(m_sps, m_scalingList, m_vps.ptl, layer);
@@ -3328,11 +3356,7 @@ void Encoder::getStreamHeaders(NALList& list,
Entropy& sbacCoder, Bitstream& bs)
list.serialize(NAL_UNIT_SPS, bs, layer);
}
-#if ENABLE_MULTIVIEW
- for (int layer = 0; layer < m_param->numViews; layer++)
-#else
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
-#endif
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
bs.resetBits();
sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1),
m_iPPSQpMinus26, layer);
diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
index 58709e92e..1dbb41596 100644
--- a/source/encoder/encoder.h
+++ b/source/encoder/encoder.h
@@ -202,7 +202,7 @@ public:
ThreadPool* m_threadPool;
FrameEncoder* m_frameEncoder[X265_MAX_FRAME_THREADS];
DPB* m_dpb;
- Frame* m_exportedPic[MAX_SCALABLE_LAYERS];
+ Frame* m_exportedPic[MAX_LAYERS];
FILE* m_analysisFileIn;
FILE* m_analysisFileOut;
FILE* m_naluFile;
@@ -217,10 +217,10 @@ public:
bool m_externalFlush;
/* Collect statistics globally */
- EncStats m_analyzeAll[MAX_SCALABLE_LAYERS];
- EncStats m_analyzeI[MAX_SCALABLE_LAYERS];
- EncStats m_analyzeP[MAX_SCALABLE_LAYERS];
- EncStats m_analyzeB[MAX_SCALABLE_LAYERS];
+ EncStats m_analyzeAll[MAX_LAYERS];
+ EncStats m_analyzeI[MAX_LAYERS];
+ EncStats m_analyzeP[MAX_LAYERS];
+ EncStats m_analyzeB[MAX_LAYERS];
VPS m_vps;
SPS m_sps;
PPS m_pps;
diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index 1aab82b77..97d033fb6 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -58,7 +58,7 @@ FrameEncoder::FrameEncoder()
m_ctuGeomMap = NULL;
m_localTldIdx = 0;
memset(&m_rce, 0, sizeof(RateControlEntry));
- for (int layer = 0; layer < MAX_SCALABLE_LAYERS; layer++)
+ for (int layer = 0; layer < MAX_LAYERS; layer++)
{
m_prevOutputTime[layer] = x265_mdate();
m_slicetypeWaitTime[layer] = 0;
@@ -220,8 +220,8 @@ bool FrameEncoder::init(Encoder *top, int numRows, int
numCols)
ok &= !!m_frameEncTF->createRefPicInfo(&m_mcstfRefList[i],
m_param);
}
- m_retFrameBuffer = X265_MALLOC(Frame*, m_param->numScalableLayers);
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
+ m_retFrameBuffer = X265_MALLOC(Frame*, m_param->numLayers);
+ for (int layer = 0; layer < m_param->numLayers; layer++)
m_retFrameBuffer[layer] = NULL;
return ok;
}
@@ -289,9 +289,9 @@ bool FrameEncoder::initializeGeoms()
return true;
}
-bool FrameEncoder::startCompressFrame(Frame* curFrame[MAX_SCALABLE_LAYERS])
+bool FrameEncoder::startCompressFrame(Frame* curFrame[MAX_LAYERS])
{
- for (int layer = 0; layer < m_param->numScalableLayers; layer++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
{
m_slicetypeWaitTime[layer] = x265_mdate() -
m_prevOutputTime[layer];
m_frame[layer] = curFrame[layer];
@@ -374,7 +374,7 @@ void FrameEncoder::threadMain()
m_frame[0]->m_copyMVType.wait();
}
- for(int layer = 0; layer < m_param->numScalableLayers; layer ++)
+ for (int layer = 0; layer < m_param->numLayers; layer++)
compressFrame(layer);
m_done.trigger(); /* FrameEncoder::getEncodedPicture() blocks for
this event */
m_enable.wait();
@@ -2282,7 +2282,7 @@ Frame** FrameEncoder::getEncodedPicture(NALList&
output)
/* block here until worker thread completes */
m_done.wait();
- for (int i = 0; i < m_param->numScalableLayers; i++)
+ for (int i = 0; i < m_param->numLayers; i++)
{
m_retFrameBuffer[i] = m_frame[i];
m_frame[i] = NULL;
diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h
index 6253cbd84..ebc6e57c5 100644
--- a/source/encoder/frameencoder.h
+++ b/source/encoder/frameencoder.h
@@ -156,7 +156,7 @@ public:
void destroy();
/* triggers encode of a new frame by the worker thread */
- bool startCompressFrame(Frame* curFrame[MAX_SCALABLE_LAYERS]);
+ bool startCompressFrame(Frame* curFrame[MAX_LAYERS]);
/* blocks until worker thread is done, returns access unit */
Frame **getEncodedPicture(NALList& list);
@@ -190,34 +190,34 @@ public:
RateControlEntry m_rce;
SEIDecodedPictureHash m_seiReconPictureDigest;
- uint64_t m_SSDY[MAX_SCALABLE_LAYERS];
- uint64_t m_SSDU[MAX_SCALABLE_LAYERS];
- uint64_t m_SSDV[MAX_SCALABLE_LAYERS];
- double m_ssim[MAX_SCALABLE_LAYERS];
- uint64_t m_accessUnitBits[MAX_SCALABLE_LAYERS];
- uint32_t m_ssimCnt[MAX_SCALABLE_LAYERS];
+ uint64_t m_SSDY[MAX_LAYERS];
+ uint64_t m_SSDU[MAX_LAYERS];
+ uint64_t m_SSDV[MAX_LAYERS];
+ double m_ssim[MAX_LAYERS];
+ uint64_t m_accessUnitBits[MAX_LAYERS];
+ uint32_t m_ssimCnt[MAX_LAYERS];
volatile int m_activeWorkerCount; // count of
workers currently encoding or filtering CTUs
volatile int m_totalActiveWorkerCount; // sum of
m_activeWorkerCount sampled at end of each CTU
volatile int m_activeWorkerCountSamples; // count of times
m_activeWorkerCount was sampled (think vbv restarts)
volatile int m_countRowBlocks; // count of
workers forced to abandon a row because of top dependency
- int64_t m_startCompressTime[MAX_SCALABLE_LAYERS];
// timestamp when frame encoder is given a frame
- int64_t m_row0WaitTime[MAX_SCALABLE_LAYERS];
// timestamp when row 0 is allowed to start
- int64_t m_allRowsAvailableTime[MAX_SCALABLE_LAYERS];
// timestamp when all reference dependencies are resolved
- int64_t m_endCompressTime[MAX_SCALABLE_LAYERS];
// timestamp after all CTUs are compressed
- int64_t m_endFrameTime[MAX_SCALABLE_LAYERS];
// timestamp after RCEnd, NR updates, etc
- int64_t m_stallStartTime[MAX_SCALABLE_LAYERS];
// timestamp when worker count becomes 0
- int64_t m_prevOutputTime[MAX_SCALABLE_LAYERS];
// timestamp when prev frame was retrieved by API thread
- int64_t m_slicetypeWaitTime[MAX_SCALABLE_LAYERS];
// total elapsed time waiting for decided frame
- int64_t
m_totalWorkerElapsedTime[MAX_SCALABLE_LAYERS]; // total elapsed time
spent by worker threads processing CTUs
- int64_t m_totalNoWorkerTime[MAX_SCALABLE_LAYERS];
// total elapsed time without any active worker threads
+ int64_t m_startCompressTime[MAX_LAYERS]; //
timestamp when frame encoder is given a frame
+ int64_t m_row0WaitTime[MAX_LAYERS]; //
timestamp when row 0 is allowed to start
+ int64_t m_allRowsAvailableTime[MAX_LAYERS]; //
timestamp when all reference dependencies are resolved
+ int64_t m_endCompressTime[MAX_LAYERS]; //
timestamp after all CTUs are compressed
+ int64_t m_endFrameTime[MAX_LAYERS]; //
timestamp after RCEnd, NR updates, etc
+ int64_t m_stallStartTime[MAX_LAYERS]; //
timestamp when worker count becomes 0
+ int64_t m_prevOutputTime[MAX_LAYERS]; //
timestamp when prev frame was retrieved by API thread
+ int64_t m_slicetypeWaitTime[MAX_LAYERS]; //
total elapsed time waiting for decided frame
+ int64_t m_totalWorkerElapsedTime[MAX_LAYERS]; //
total elapsed time spent by worker threads processing CTUs
+ int64_t m_totalNoWorkerTime[MAX_LAYERS]; //
total elapsed time without any active worker threads
#if DETAILED_CU_STATS
CUStats m_cuStats;
#endif
Encoder* m_top;
x265_param* m_param;
- Frame* m_frame[MAX_SCALABLE_LAYERS];
+ Frame* m_frame[MAX_LAYERS];
Frame** m_retFrameBuffer;
NoiseReduction* m_nr;
ThreadLocalData* m_tld; /* for --no-wpp */
diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp
index 001115782..3218f4a24 100644
--- a/source/encoder/search.cpp
+++ b/source/encoder/search.cpp
@@ -2102,7 +2102,8 @@ void Search::singleMotionEstimation(Search& master,
Mode& interMode, const Predi
if (!m_param->analysisSave && !m_param->analysisLoad) /* Prevents
load/save outputs from diverging if lowresMV is not available */
{
MV lmv = getLowresMV(interMode.cu, pu, list, ref);
- if (lmv.notZero() && !m_frame->m_sLayerId)
+ int layer = m_param->numViews > 1 ? m_frame->m_viewId :
(m_param->numScalableLayers > 1) ? m_frame->m_sLayerId : 0;
+ if (lmv.notZero() && !layer)
mvc[numMvc++] = lmv;
if (m_param->bEnableHME)
mvp_lowres = lmv;
@@ -2413,7 +2414,8 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
if (!m_param->analysisSave && !m_param->analysisLoad)
/* Prevents load/save outputs from diverging when lowresMV is not available
*/
{
MV lmv = getLowresMV(cu, pu, list, ref);
- if (lmv.notZero() && !m_frame->m_sLayerId)
+ int layer = m_param->numViews > 1 ?
m_frame->m_viewId : (m_param->numScalableLayers > 1) ? m_frame->m_sLayerId
: 0;
+ if (lmv.notZero() && !layer)
mvc[numMvc++] = lmv;
if (m_param->bEnableHME)
mvp_lowres = lmv;
diff --git a/source/x265.h b/source/x265.h
index 091696e03..49880d0f3 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -643,6 +643,10 @@ typedef enum
#define MAX_SCALABLE_LAYERS 1
#endif
+#if ENABLE_ALPHA || ENABLE_MULTIVIEW
+#define MAX_LAYERS 2
+#endif
+
#define X265_IPRATIO_STRENGTH 1.43
typedef struct x265_cli_csp
@@ -2296,6 +2300,8 @@ typedef struct x265_param
/*Multi View Encoding*/
int numViews;
+
+ int numLayers;
} x265_param;
/* x265_param_alloc:
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index b2b357beb..cd42a3bfa 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -429,7 +429,7 @@ namespace X265_NS {
input[i]->release();
input[i] = NULL;
}
- for (int i = 0; i < MAX_SCALABLE_LAYERS; i++)
+ for (int i = 0; i < MAX_LAYERS; i++)
{
if (recon[i])
recon[i]->release();
@@ -595,7 +595,7 @@ namespace X265_NS {
{
inputfn[view] = X265_MALLOC(char, sizeof(char) * 1024);
}
- const char* reconfn[MAX_SCALABLE_LAYERS] = { NULL };
+ const char* reconfn[MAX_LAYERS] = { NULL };
const char *outputfn = NULL;
const char *preset = NULL;
const char *tune = NULL;
@@ -831,6 +831,7 @@ namespace X265_NS {
}
}
#endif
+ param->numLayers = param->numViews > 1 ? param->numViews :
(param->numScalableLayers > 1) ? param->numScalableLayers : 1;
if (!outputfn)
{
x265_log(param, X265_LOG_ERROR, "input or output file not
specified, try --help for help\n");
@@ -967,13 +968,13 @@ namespace X265_NS {
{
if (reconFileBitDepth == 0)
reconFileBitDepth = param->internalBitDepth;
-#if ENABLE_ALPHA
- if (param->bEnableAlpha)
+#if ENABLE_ALPHA || ENABLE_MULTIVIEW
+ if (param->bEnableAlpha || param->numViews > 1)
{
char* temp = new char[strlen(reconfn[0])];
strcpy(temp, reconfn[0]);
const char* token = strtok(temp, ".");
- for (int view = 0; view < param->numScalableLayers; view++)
+ for (int view = 0; view < param->numLayers; view++)
{
char* buf = new char[strlen(temp) + 7];
sprintf(buf, "%s-%d.yuv", token, view);
@@ -981,7 +982,7 @@ namespace X265_NS {
}
}
#endif
- for (int i = 0; i < param->numScalableLayers; i++)
+ for (int i = 0; i < param->numLayers; i++)
{
this->recon[i] = ReconFile::open(reconfn[i],
param->sourceWidth, param->sourceHeight, reconFileBitDepth,
param->fpsNum, param->fpsDenom, param->internalCsp,
param->sourceBitDepth);
diff --git a/source/x265cli.h b/source/x265cli.h
index 0613c81e5..49a88d084 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -401,7 +401,7 @@ static const struct option long_options[] =
struct CLIOptions
{
InputFile* input[MAX_VIEWS];
- ReconFile* recon[MAX_SCALABLE_LAYERS];
+ ReconFile* recon[MAX_LAYERS];
OutputFile* output;
FILE* qpfile;
FILE* zoneFile;
@@ -443,7 +443,7 @@ static const struct option long_options[] =
{
for (int i = 0; i < MAX_VIEWS; i++)
input[i] = NULL;
- for (int i = 0; i < MAX_SCALABLE_LAYERS; i++)
+ for (int i = 0; i < MAX_LAYERS; i++)
recon[i] = NULL;
output = NULL;
qpfile = NULL;
--
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/6182fdcc/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0005-This-commit-does-the-following-things-Extend-the-enc.patch
Type: application/octet-stream
Size: 34772 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/6182fdcc/attachment-0001.obj>
More information about the x265-devel
mailing list