[x265] [PATCH Alpha 07/10] Add support for reconstructed file corresponding to Alpha layer
Anusuya Kumarasamy
anusuya.kumarasamy at multicorewareinc.com
Mon Aug 5 11:08:21 UTC 2024
>From 9a1baf8cbcfa95be89fd72b00c6b531ede4fb66f Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 5 Jul 2024 15:28:10 +0530
Subject: [PATCH] Add support for reconstructed file corresponding to Alpha
layer.
This commit also does :
1.Receive and proccess frames of all layers corresponding to same POC from
the Frame encoder thread.
---
source/abrEncApp.cpp | 34 ++-
source/encoder/api.cpp | 4 +-
source/encoder/encoder.cpp | 456 ++++++++++++++++----------------
source/encoder/encoder.h | 4 +-
source/encoder/frameencoder.cpp | 24 +-
source/encoder/frameencoder.h | 3 +-
source/x265.h | 4 +-
source/x265cli.cpp | 54 ++--
source/x265cli.h | 5 +-
9 files changed, 320 insertions(+), 268 deletions(-)
diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp
index 96c854de6..eabfb7d2b 100644
--- a/source/abrEncApp.cpp
+++ b/source/abrEncApp.cpp
@@ -530,11 +530,13 @@ ret:
x265_log(m_param, X265_LOG_ERROR, "Unable to register
CTRL+C handler: %s in %s\n",
strerror(errno), profileName);
- x265_picture pic_orig, pic_out;
+ x265_picture pic_orig, pic_out[MAX_SCALABLE_LAYERS];
x265_picture *pic_in = &pic_orig;
/* 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;
- x265_picture *pic_recon = (m_cliopt.recon ||
m_param->analysisSave || m_param->analysisLoad || pts_queue || reconPlay ||
m_param->csvLogLevel) ? &pic_out : NULL;
+ x265_picture *pic_recon[MAX_SCALABLE_LAYERS];
+ for(int i = 0; i < m_param->numScalableLayers; 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;
x265_nal *p_nal;
@@ -545,7 +547,7 @@ ret:
uint8_t *rpuPayload = NULL;
int inputPicNum = 1;
x265_picture picField1, picField2;
- x265_analysis_data* analysisInfo =
(x265_analysis_data*)(&pic_out.analysisData);
+ x265_analysis_data* analysisInfo =
(x265_analysis_data*)(&pic_out[0].analysisData);
bool isAbrSave = m_cliopt.saveLevel && (m_parent->m_numEncodes
> 1);
if (!m_param->bRepeatHeaders && !m_param->bEnableSvtHevc)
@@ -735,7 +737,7 @@ ret:
}
if (reconPlay && numEncoded)
- reconPlay->writePicture(*pic_recon);
+ reconPlay->writePicture(*pic_recon[0]);
outFrameCount += numEncoded;
@@ -744,14 +746,17 @@ ret:
copyInfo(analysisInfo);
}
- if (numEncoded && pic_recon && m_cliopt.recon)
- m_cliopt.recon->writePicture(pic_out);
+ for (int i = 0; i < m_param->numScalableLayers; i++)
+ {
+ if (numEncoded && pic_recon[i] &&
m_cliopt.recon[i])
+ m_cliopt.recon[i]->writePicture(pic_out[i]);
+ }
if (nal)
{
- m_cliopt.totalbytes +=
m_cliopt.output->writeFrame(p_nal, nal, pic_out);
+ m_cliopt.totalbytes +=
m_cliopt.output->writeFrame(p_nal, nal, pic_out[0]);
if (pts_queue)
{
- pts_queue->push(-pic_out.pts);
+ pts_queue->push(-pic_out[0].pts);
if (pts_queue->size() > 2)
pts_queue->pop();
}
@@ -771,7 +776,7 @@ ret:
}
if (reconPlay && numEncoded)
- reconPlay->writePicture(*pic_recon);
+ reconPlay->writePicture(*pic_recon[0]);
outFrameCount += numEncoded;
if (isAbrSave && numEncoded)
@@ -779,14 +784,17 @@ ret:
copyInfo(analysisInfo);
}
- if (numEncoded && pic_recon && m_cliopt.recon)
- m_cliopt.recon->writePicture(pic_out);
+ for (int i = 0; i < m_param->numScalableLayers; i++)
+ {
+ if (numEncoded && pic_recon[i] && m_cliopt.recon[i])
+ m_cliopt.recon[i]->writePicture(pic_out[i]);
+ }
if (nal)
{
- m_cliopt.totalbytes +=
m_cliopt.output->writeFrame(p_nal, nal, pic_out);
+ m_cliopt.totalbytes +=
m_cliopt.output->writeFrame(p_nal, nal, pic_out[0]);
if (pts_queue)
{
- pts_queue->push(-pic_out.pts);
+ pts_queue->push(-pic_out[0].pts);
if (pts_queue->size() > 2)
pts_queue->pop();
}
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 33e98a066..60893f4d1 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -406,7 +406,7 @@ int x265_encoder_reconfig_zone(x265_encoder* enc,
x265_zone* zone_in)
return 0;
}
-int x265_encoder_encode(x265_encoder *enc, x265_nal **pp_nal, uint32_t
*pi_nal, x265_picture *pic_in, x265_picture *pic_out)
+int x265_encoder_encode(x265_encoder *enc, x265_nal **pp_nal, uint32_t
*pi_nal, x265_picture *pic_in, x265_picture **pic_out)
{
if (!enc)
return -1;
@@ -602,7 +602,7 @@ fail:
*pi_nal = 0;
if (numEncoded && encoder->m_param->csvLogLevel &&
encoder->m_outputCount >= encoder->m_latestParam->chunkStart)
- x265_csvlog_frame(encoder->m_param, pic_out);
+ x265_csvlog_frame(encoder->m_param, pic_out[0]);
if (numEncoded < 0)
encoder->m_aborted = true;
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index e61db1ebc..4ac71f654 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -134,7 +134,6 @@ Encoder::Encoder()
m_lookahead = NULL;
m_rateControl = NULL;
m_dpb = NULL;
- m_exportedPic = NULL;
m_numDelayedPic = 0;
m_outputCount = 0;
m_param = NULL;
@@ -150,6 +149,8 @@ Encoder::Encoder()
m_rpsInSpsCount = 0;
m_cB = 1.0;
m_cR = 1.0;
+ for (int i = 0; i < MAX_SCALABLE_LAYERS; i++)
+ m_exportedPic[i] = NULL;
for (int i = 0; i < X265_MAX_FRAME_THREADS; i++)
m_frameEncoder[i] = NULL;
for (uint32_t i = 0; i < DUP_BUFFER; i++)
@@ -861,10 +862,13 @@ void Encoder::destroy()
X265_FREE(m_rdCost);
X265_FREE(m_trainingCount);
}
- if (m_exportedPic)
+ for (int layer = 0; layer < m_param->numScalableLayers; layer++)
{
- ATOMIC_DEC(&m_exportedPic->m_countRefEncoders);
- m_exportedPic = NULL;
+ if (m_exportedPic[layer])
+ {
+ ATOMIC_DEC(&m_exportedPic[layer]->m_countRefEncoders);
+ m_exportedPic[layer] = NULL;
+ }
}
if (m_param->bEnableFrameDuplication)
@@ -1462,7 +1466,7 @@ bool Encoder::generateMcstfRef(Frame* frameEnc,
FrameEncoder* currEncoder)
* returns 0 if no frames are currently available for output
* 1 if frame was output, m_nalList contains access unit
* negative on malloc error or abort */
-int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
+int Encoder::encode(const x265_picture* pic_in, x265_picture** pic_out)
{
#if CHECKED_BUILD || _DEBUG
if (g_checkFailures)
@@ -1479,14 +1483,16 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
bool dontRead = false;
bool dropflag = false;
- if (m_exportedPic)
+ if (*m_exportedPic)
{
if (!m_param->bUseAnalysisFile && m_param->analysisSave)
- x265_free_analysis_data(m_param,
&m_exportedPic->m_analysisData);
-
- ATOMIC_DEC(&m_exportedPic->m_countRefEncoders);
+ x265_free_analysis_data(m_param,
&m_exportedPic[0]->m_analysisData);
- m_exportedPic = NULL;
+ for (int i = 0; i < m_param->numScalableLayers; i++)
+ {
+ ATOMIC_DEC(&m_exportedPic[i]->m_countRefEncoders);
+ m_exportedPic[i] = NULL;
+ }
m_dpb->recycleUnreferenced();
if (m_param->bEnableTemporalFilter)
@@ -1579,7 +1585,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
Frame* inFrame[MAX_SCALABLE_LAYERS];
x265_param *p = (m_reconfigure || m_reconfigureRc) ? m_latestParam
: m_param;
- for (int layer = 0; layer < MAX_SCALABLE_LAYERS; layer++)
+ for (int layer = 0; layer < m_param->numScalableLayers; layer++)
{
if (m_dpb->m_freeList.empty())
{
@@ -1648,6 +1654,8 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
inFrame[layer]->m_tempLayer = 0;
inFrame[layer]->m_sameLayerRefPic = 0;
inFrame[layer]->m_sLayerId = layer;
+ inFrame[layer]->m_valid = false;
+ inFrame[layer]->m_lowres.bKeyframe = false;
}
/* Copy input picture into a Frame and PicYuv, send to
lookahead */
@@ -1887,7 +1895,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
* and then to give it a new frame to work on. In zero-latency mode,
we must encode this
* 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* outFrame = NULL;
+ Frame** outFrames = { NULL };
Frame* frameEnc[MAX_SCALABLE_LAYERS] = { NULL };
int pass = 0;
do
@@ -1896,243 +1904,246 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
* encoding the frame. This is how back-pressure through the API
is
* accomplished when the encoder is full */
if (!m_bZeroLatency || pass)
- outFrame = curEncoder->getEncodedPicture(m_nalList);
- if (outFrame)
+ outFrames = curEncoder->getEncodedPicture(m_nalList);
+ if (outFrames)
{
- Slice *slice = outFrame->m_encData->m_slice;
- x265_frame_stats* frameData = NULL;
-
- /* Free up inputPic->analysisData since it has already been
used */
- if ((m_param->analysisLoad && !m_param->analysisSave) ||
((m_param->bAnalysisType == AVC_INFO) && slice->m_sliceType != I_SLICE))
- x265_free_analysis_data(m_param,
&outFrame->m_analysisData);
-
- if (pic_out)
+ for (int sLayer = 0; sLayer < m_param->numScalableLayers;
sLayer++)
{
- PicYuv *recpic = outFrame->m_reconPic;
- pic_out->poc = slice->m_poc;
- pic_out->bitDepth = X265_DEPTH;
- pic_out->userData = outFrame->m_userData;
- pic_out->colorSpace = m_param->internalCsp;
- pic_out->frameData.tLayer = outFrame->m_tempLayer;
- frameData = &(pic_out->frameData);
-
- pic_out->pts = outFrame->m_pts;
- pic_out->dts = outFrame->m_dts;
- pic_out->reorderedPts = outFrame->m_reorderedPts;
- pic_out->sliceType = outFrame->m_lowres.sliceType;
- pic_out->planes[0] = recpic->m_picOrg[0];
- pic_out->stride[0] = (int)(recpic->m_stride *
sizeof(pixel));
- if (m_param->internalCsp != X265_CSP_I400)
+ Frame* outFrame = *(outFrames + sLayer);
+ Slice* slice = outFrame->m_encData->m_slice;
+ x265_frame_stats* frameData = NULL;
+
+ /* Free up inputPic->analysisData since it has already
been used */
+ if ((m_param->analysisLoad && !m_param->analysisSave) ||
((m_param->bAnalysisType == AVC_INFO) && slice->m_sliceType != I_SLICE))
+ x265_free_analysis_data(m_param,
&outFrame->m_analysisData);
+ if (pic_out[sLayer])
{
- pic_out->planes[1] = recpic->m_picOrg[1];
- pic_out->stride[1] = (int)(recpic->m_strideC *
sizeof(pixel));
- pic_out->planes[2] = recpic->m_picOrg[2];
- pic_out->stride[2] = (int)(recpic->m_strideC *
sizeof(pixel));
- }
+ PicYuv* recpic = outFrame->m_reconPic;
+ pic_out[sLayer]->poc = slice->m_poc;
+ pic_out[sLayer]->bitDepth = X265_DEPTH;
+ pic_out[sLayer]->userData = outFrame->m_userData;
+ pic_out[sLayer]->colorSpace = m_param->internalCsp;
+ pic_out[sLayer]->frameData.tLayer =
outFrame->m_tempLayer;
+ frameData = &(pic_out[sLayer]->frameData);
+
+ pic_out[sLayer]->pts = outFrame->m_pts;
+ pic_out[sLayer]->dts = outFrame->m_dts;
+ pic_out[sLayer]->reorderedPts =
outFrame->m_reorderedPts;
+ pic_out[sLayer]->sliceType =
outFrame->m_lowres.sliceType;
+ pic_out[sLayer]->planes[0] = recpic->m_picOrg[0];
+ pic_out[sLayer]->stride[0] = (int)(recpic->m_stride *
sizeof(pixel));
+ if (m_param->internalCsp != X265_CSP_I400)
+ {
+ pic_out[sLayer]->planes[1] = recpic->m_picOrg[1];
+ pic_out[sLayer]->stride[1] =
(int)(recpic->m_strideC * sizeof(pixel));
+ pic_out[sLayer]->planes[2] = recpic->m_picOrg[2];
+ pic_out[sLayer]->stride[2] =
(int)(recpic->m_strideC * sizeof(pixel));
+ }
- /* Dump analysis data from pic_out to file in save mode
and free */
- if (m_param->analysisSave)
- {
- pic_out->analysisData.poc = pic_out->poc;
- pic_out->analysisData.sliceType = pic_out->sliceType;
- pic_out->analysisData.bScenecut =
outFrame->m_lowres.bScenecut;
- pic_out->analysisData.satdCost =
outFrame->m_lowres.satdCost;
- pic_out->analysisData.numCUsInFrame =
outFrame->m_analysisData.numCUsInFrame;
- pic_out->analysisData.numPartitions =
outFrame->m_analysisData.numPartitions;
- pic_out->analysisData.wt = outFrame->m_analysisData.wt;
- pic_out->analysisData.interData =
outFrame->m_analysisData.interData;
- pic_out->analysisData.intraData =
outFrame->m_analysisData.intraData;
- pic_out->analysisData.distortionData =
outFrame->m_analysisData.distortionData;
- pic_out->analysisData.modeFlag[0] =
outFrame->m_analysisData.modeFlag[0];
- pic_out->analysisData.modeFlag[1] =
outFrame->m_analysisData.modeFlag[1];
- if (m_param->bDisableLookahead)
+ /* Dump analysis data from pic_out[sLayer] to file in
save mode and free */
+ if (m_param->analysisSave)
{
- int factor = 1;
- if (m_param->scaleFactor)
- factor = m_param->scaleFactor * 2;
- pic_out->analysisData.numCuInHeight =
outFrame->m_analysisData.numCuInHeight;
- pic_out->analysisData.lookahead.dts =
outFrame->m_dts;
- pic_out->analysisData.lookahead.reorderedPts =
outFrame->m_reorderedPts;
- pic_out->analysisData.satdCost *= factor;
- pic_out->analysisData.lookahead.keyframe =
outFrame->m_lowres.bKeyframe;
- pic_out->analysisData.lookahead.lastMiniGopBFrame
= outFrame->m_lowres.bLastMiniGopBFrame;
- if (m_rateControl->m_isVbv)
+ pic_out[sLayer]->analysisData.poc =
pic_out[sLayer]->poc;
+ pic_out[sLayer]->analysisData.sliceType =
pic_out[sLayer]->sliceType;
+ pic_out[sLayer]->analysisData.bScenecut =
outFrame->m_lowres.bScenecut;
+ pic_out[sLayer]->analysisData.satdCost =
outFrame->m_lowres.satdCost;
+ pic_out[sLayer]->analysisData.numCUsInFrame =
outFrame->m_analysisData.numCUsInFrame;
+ pic_out[sLayer]->analysisData.numPartitions =
outFrame->m_analysisData.numPartitions;
+ pic_out[sLayer]->analysisData.wt =
outFrame->m_analysisData.wt;
+ pic_out[sLayer]->analysisData.interData =
outFrame->m_analysisData.interData;
+ pic_out[sLayer]->analysisData.intraData =
outFrame->m_analysisData.intraData;
+ pic_out[sLayer]->analysisData.distortionData =
outFrame->m_analysisData.distortionData;
+ pic_out[sLayer]->analysisData.modeFlag[0] =
outFrame->m_analysisData.modeFlag[0];
+ pic_out[sLayer]->analysisData.modeFlag[1] =
outFrame->m_analysisData.modeFlag[1];
+ if (m_param->bDisableLookahead)
{
- int vbvCount = m_param->lookaheadDepth +
m_param->bframes + 2;
- for (int index = 0; index < vbvCount; index++)
- {
-
pic_out->analysisData.lookahead.plannedSatd[index] =
outFrame->m_lowres.plannedSatd[index];
-
pic_out->analysisData.lookahead.plannedType[index] =
outFrame->m_lowres.plannedType[index];
- }
- for (uint32_t index = 0; index <
pic_out->analysisData.numCuInHeight; index++)
- {
-
outFrame->m_analysisData.lookahead.intraSatdForVbv[index] =
outFrame->m_encData->m_rowStat[index].intraSatdForVbv;
-
outFrame->m_analysisData.lookahead.satdForVbv[index] =
outFrame->m_encData->m_rowStat[index].satdForVbv;
- }
-
pic_out->analysisData.lookahead.intraSatdForVbv =
outFrame->m_analysisData.lookahead.intraSatdForVbv;
- pic_out->analysisData.lookahead.satdForVbv =
outFrame->m_analysisData.lookahead.satdForVbv;
- for (uint32_t index = 0; index <
pic_out->analysisData.numCUsInFrame; index++)
+ int factor = 1;
+ if (m_param->scaleFactor)
+ factor = m_param->scaleFactor * 2;
+ pic_out[sLayer]->analysisData.numCuInHeight =
outFrame->m_analysisData.numCuInHeight;
+ pic_out[sLayer]->analysisData.lookahead.dts =
outFrame->m_dts;
+
pic_out[sLayer]->analysisData.lookahead.reorderedPts =
outFrame->m_reorderedPts;
+ pic_out[sLayer]->analysisData.satdCost *=
factor;
+
pic_out[sLayer]->analysisData.lookahead.keyframe =
outFrame->m_lowres.bKeyframe;
+
pic_out[sLayer]->analysisData.lookahead.lastMiniGopBFrame =
outFrame->m_lowres.bLastMiniGopBFrame;
+ if (m_rateControl->m_isVbv)
{
-
outFrame->m_analysisData.lookahead.intraVbvCost[index] =
outFrame->m_encData->m_cuStat[index].intraVbvCost;
-
outFrame->m_analysisData.lookahead.vbvCost[index] =
outFrame->m_encData->m_cuStat[index].vbvCost;
+ int vbvCount = m_param->lookaheadDepth +
m_param->bframes + 2;
+ for (int index = 0; index < vbvCount;
index++)
+ {
+
pic_out[sLayer]->analysisData.lookahead.plannedSatd[index] =
outFrame->m_lowres.plannedSatd[index];
+
pic_out[sLayer]->analysisData.lookahead.plannedType[index] =
outFrame->m_lowres.plannedType[index];
+ }
+ for (uint32_t index = 0; index <
pic_out[sLayer]->analysisData.numCuInHeight; index++)
+ {
+
outFrame->m_analysisData.lookahead.intraSatdForVbv[index] =
outFrame->m_encData->m_rowStat[index].intraSatdForVbv;
+
outFrame->m_analysisData.lookahead.satdForVbv[index] =
outFrame->m_encData->m_rowStat[index].satdForVbv;
+ }
+
pic_out[sLayer]->analysisData.lookahead.intraSatdForVbv =
outFrame->m_analysisData.lookahead.intraSatdForVbv;
+
pic_out[sLayer]->analysisData.lookahead.satdForVbv =
outFrame->m_analysisData.lookahead.satdForVbv;
+ for (uint32_t index = 0; index <
pic_out[sLayer]->analysisData.numCUsInFrame; index++)
+ {
+
outFrame->m_analysisData.lookahead.intraVbvCost[index] =
outFrame->m_encData->m_cuStat[index].intraVbvCost;
+
outFrame->m_analysisData.lookahead.vbvCost[index] =
outFrame->m_encData->m_cuStat[index].vbvCost;
+ }
+
pic_out[sLayer]->analysisData.lookahead.intraVbvCost =
outFrame->m_analysisData.lookahead.intraVbvCost;
+
pic_out[sLayer]->analysisData.lookahead.vbvCost =
outFrame->m_analysisData.lookahead.vbvCost;
}
- pic_out->analysisData.lookahead.intraVbvCost =
outFrame->m_analysisData.lookahead.intraVbvCost;
- pic_out->analysisData.lookahead.vbvCost =
outFrame->m_analysisData.lookahead.vbvCost;
}
+ writeAnalysisFile(&pic_out[sLayer]->analysisData,
*outFrame->m_encData);
+ pic_out[sLayer]->analysisData.saveParam =
pic_out[sLayer]->analysisData.saveParam;
+ if (m_param->bUseAnalysisFile)
+ x265_free_analysis_data(m_param,
&pic_out[sLayer]->analysisData);
}
- writeAnalysisFile(&pic_out->analysisData,
*outFrame->m_encData);
- pic_out->analysisData.saveParam =
pic_out->analysisData.saveParam;
- if (m_param->bUseAnalysisFile)
- x265_free_analysis_data(m_param,
&pic_out->analysisData);
- }
- }
- if (m_param->rc.bStatWrite &&
(m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion))
- {
- if (pic_out)
- {
- pic_out->analysisData.poc = pic_out->poc;
- pic_out->analysisData.interData =
outFrame->m_analysisData.interData;
- pic_out->analysisData.intraData =
outFrame->m_analysisData.intraData;
- pic_out->analysisData.distortionData =
outFrame->m_analysisData.distortionData;
- }
- writeAnalysisFileRefine(&outFrame->m_analysisData,
*outFrame->m_encData);
- }
- if (m_param->analysisMultiPassRefine ||
m_param->analysisMultiPassDistortion)
- x265_free_analysis_data(m_param,
&outFrame->m_analysisData);
- if (m_param->internalCsp == X265_CSP_I400)
- {
- if (slice->m_sliceType == P_SLICE)
- {
- if (slice->m_weightPredTable[0][0][0].wtPresent)
- m_numLumaWPFrames++;
}
- else if (slice->m_sliceType == B_SLICE)
+ if (m_param->rc.bStatWrite &&
(m_param->analysisMultiPassRefine || m_param->analysisMultiPassDistortion))
{
- bool bLuma = false;
- for (int l = 0; l < 2; l++)
+ if (pic_out[sLayer])
{
- if (slice->m_weightPredTable[l][0][0].wtPresent)
- bLuma = true;
+ pic_out[sLayer]->analysisData.poc =
pic_out[sLayer]->poc;
+ pic_out[sLayer]->analysisData.interData =
outFrame->m_analysisData.interData;
+ pic_out[sLayer]->analysisData.intraData =
outFrame->m_analysisData.intraData;
+ pic_out[sLayer]->analysisData.distortionData =
outFrame->m_analysisData.distortionData;
}
- if (bLuma)
- m_numLumaWPBiFrames++;
+ writeAnalysisFileRefine(&outFrame->m_analysisData,
*outFrame->m_encData);
}
- }
- else
- {
- if (slice->m_sliceType == P_SLICE)
+ if (m_param->analysisMultiPassRefine ||
m_param->analysisMultiPassDistortion)
+ x265_free_analysis_data(m_param,
&outFrame->m_analysisData);
+ if (m_param->internalCsp == X265_CSP_I400)
{
- if (slice->m_weightPredTable[0][0][0].wtPresent)
- m_numLumaWPFrames++;
- if (slice->m_weightPredTable[0][0][1].wtPresent ||
- slice->m_weightPredTable[0][0][2].wtPresent)
- m_numChromaWPFrames++;
+ if (slice->m_sliceType == P_SLICE)
+ {
+ if (slice->m_weightPredTable[0][0][0].wtPresent)
+ m_numLumaWPFrames++;
+ }
+ else if (slice->m_sliceType == B_SLICE)
+ {
+ bool bLuma = false;
+ for (int l = 0; l < 2; l++)
+ {
+ if
(slice->m_weightPredTable[l][0][0].wtPresent)
+ bLuma = true;
+ }
+ if (bLuma)
+ m_numLumaWPBiFrames++;
+ }
}
- else if (slice->m_sliceType == B_SLICE)
+ else
{
- bool bLuma = false, bChroma = false;
- for (int l = 0; l < 2; l++)
+ if (slice->m_sliceType == P_SLICE)
{
- if (slice->m_weightPredTable[l][0][0].wtPresent)
- bLuma = true;
- if (slice->m_weightPredTable[l][0][1].wtPresent ||
- slice->m_weightPredTable[l][0][2].wtPresent)
- bChroma = true;
+ if (slice->m_weightPredTable[0][0][0].wtPresent)
+ m_numLumaWPFrames++;
+ if (slice->m_weightPredTable[0][0][1].wtPresent ||
+ slice->m_weightPredTable[0][0][2].wtPresent)
+ m_numChromaWPFrames++;
}
+ else if (slice->m_sliceType == B_SLICE)
+ {
+ bool bLuma = false, bChroma = false;
+ for (int l = 0; l < 2; l++)
+ {
+ if
(slice->m_weightPredTable[l][0][0].wtPresent)
+ bLuma = true;
+ if
(slice->m_weightPredTable[l][0][1].wtPresent ||
+
slice->m_weightPredTable[l][0][2].wtPresent)
+ bChroma = true;
+ }
- if (bLuma)
- m_numLumaWPBiFrames++;
- if (bChroma)
- m_numChromaWPBiFrames++;
+ if (bLuma)
+ m_numLumaWPBiFrames++;
+ if (bChroma)
+ m_numChromaWPBiFrames++;
+ }
}
- }
- if (m_aborted)
- return -1;
+ if (m_aborted)
+ return -1;
- if ((m_outputCount + 1) >= m_param->chunkStart)
- finishFrameStats(outFrame, curEncoder, frameData,
m_pocLast);
- if (m_param->analysisSave)
- {
- pic_out->analysisData.frameBits = frameData->bits;
- if (!slice->isIntra())
+ if ((m_outputCount + 1) >= m_param->chunkStart && !sLayer)
+ finishFrameStats(outFrame, curEncoder, frameData,
m_pocLast);
+ if (m_param->analysisSave)
{
- for (int ref = 0; ref < MAX_NUM_REF; ref++)
- pic_out->analysisData.list0POC[ref] =
frameData->list0POC[ref];
+ pic_out[sLayer]->analysisData.frameBits =
frameData->bits;
+ if (!slice->isIntra())
+ {
+ for (int ref = 0; ref < MAX_NUM_REF; ref++)
+ pic_out[sLayer]->analysisData.list0POC[ref] =
frameData->list0POC[ref];
- double totalIntraPercent = 0;
+ double totalIntraPercent = 0;
- for (uint32_t depth = 0; depth < m_param->maxCUDepth;
depth++)
- for (uint32_t intramode = 0; intramode < 3;
intramode++)
- totalIntraPercent +=
frameData->cuStats.percentIntraDistribution[depth][intramode];
- totalIntraPercent +=
frameData->cuStats.percentIntraNxN;
+ for (uint32_t depth = 0; depth <
m_param->maxCUDepth; depth++)
+ for (uint32_t intramode = 0; intramode < 3;
intramode++)
+ totalIntraPercent +=
frameData->cuStats.percentIntraDistribution[depth][intramode];
+ totalIntraPercent +=
frameData->cuStats.percentIntraNxN;
- for (uint32_t depth = 0; depth < m_param->maxCUDepth;
depth++)
- totalIntraPercent +=
frameData->puStats.percentIntraPu[depth];
- pic_out->analysisData.totalIntraPercent =
totalIntraPercent;
+ for (uint32_t depth = 0; depth <
m_param->maxCUDepth; depth++)
+ totalIntraPercent +=
frameData->puStats.percentIntraPu[depth];
+ pic_out[sLayer]->analysisData.totalIntraPercent =
totalIntraPercent;
- if (!slice->isInterP())
- {
- for (int ref = 0; ref < MAX_NUM_REF; ref++)
- pic_out->analysisData.list1POC[ref] =
frameData->list1POC[ref];
+ if (!slice->isInterP())
+ {
+ for (int ref = 0; ref < MAX_NUM_REF; ref++)
+
pic_out[sLayer]->analysisData.list1POC[ref] = frameData->list1POC[ref];
+ }
}
}
- }
-
- /* Write RateControl Frame level stats in multipass encodes */
- if (m_param->rc.bStatWrite)
- if (m_rateControl->writeRateControlFrameStats(outFrame,
&curEncoder->m_rce))
- m_aborted = true;
- if (pic_out)
- {
- /* m_rcData is allocated for every frame */
- pic_out->rcData = outFrame->m_rcData;
- outFrame->m_rcData->qpaRc = outFrame->m_encData->m_avgQpRc;
- outFrame->m_rcData->qRceq = curEncoder->m_rce.qRceq;
- outFrame->m_rcData->qpNoVbv = curEncoder->m_rce.qpNoVbv;
- outFrame->m_rcData->coeffBits =
outFrame->m_encData->m_frameStats.coeffBits;
- outFrame->m_rcData->miscBits =
outFrame->m_encData->m_frameStats.miscBits;
- outFrame->m_rcData->mvBits =
outFrame->m_encData->m_frameStats.mvBits;
- outFrame->m_rcData->qScale = outFrame->m_rcData->newQScale
= x265_qp2qScale(outFrame->m_encData->m_avgQpRc);
- outFrame->m_rcData->poc = curEncoder->m_rce.poc;
- outFrame->m_rcData->encodeOrder =
curEncoder->m_rce.encodeOrder;
- outFrame->m_rcData->sliceType =
curEncoder->m_rce.sliceType;
- outFrame->m_rcData->keptAsRef =
curEncoder->m_rce.sliceType == B_SLICE && !IS_REFERENCED(outFrame) ? 0 : 1;
- outFrame->m_rcData->qpAq = outFrame->m_encData->m_avgQpAq;
- outFrame->m_rcData->iCuCount =
outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu;
- outFrame->m_rcData->pCuCount =
outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu;
- outFrame->m_rcData->skipCuCount =
outFrame->m_encData->m_frameStats.percent8x8Skip * m_rateControl->m_ncu;
- outFrame->m_rcData->currentSatd =
curEncoder->m_rce.coeffBits;
- }
- if (m_param->bEnableTemporalFilter)
- {
- Frame *curFrame =
m_origPicBuffer->m_mcstfPicList.getPOCMCSTF(outFrame->m_poc);
- X265_CHECK(curFrame, "Outframe not found in DPB's
mcstfPicList");
- curFrame->m_refPicCnt[0]--;
- curFrame->m_refPicCnt[1]--;
- curFrame =
m_origPicBuffer->m_mcstfOrigPicList.getPOCMCSTF(outFrame->m_poc);
- X265_CHECK(curFrame, "Outframe not found in OPB's
mcstfOrigPicList");
- curFrame->m_refPicCnt[1]--;
- }
+ /* Write RateControl Frame level stats in multipass
encodes */
+ if (m_param->rc.bStatWrite)
+ if
(m_rateControl->writeRateControlFrameStats(outFrame, &curEncoder->m_rce))
+ m_aborted = true;
+ if (pic_out[sLayer])
+ {
+ /* m_rcData is allocated for every frame */
+ pic_out[sLayer]->rcData = outFrame->m_rcData;
+ outFrame->m_rcData->qpaRc =
outFrame->m_encData->m_avgQpRc;
+ outFrame->m_rcData->qRceq = curEncoder->m_rce.qRceq;
+ outFrame->m_rcData->qpNoVbv =
curEncoder->m_rce.qpNoVbv;
+ outFrame->m_rcData->coeffBits =
outFrame->m_encData->m_frameStats.coeffBits;
+ outFrame->m_rcData->miscBits =
outFrame->m_encData->m_frameStats.miscBits;
+ outFrame->m_rcData->mvBits =
outFrame->m_encData->m_frameStats.mvBits;
+ outFrame->m_rcData->qScale =
outFrame->m_rcData->newQScale =
x265_qp2qScale(outFrame->m_encData->m_avgQpRc);
+ outFrame->m_rcData->poc = curEncoder->m_rce.poc;
+ outFrame->m_rcData->encodeOrder =
curEncoder->m_rce.encodeOrder;
+ outFrame->m_rcData->sliceType =
curEncoder->m_rce.sliceType;
+ outFrame->m_rcData->keptAsRef =
curEncoder->m_rce.sliceType == B_SLICE && !IS_REFERENCED(outFrame) ? 0 : 1;
+ outFrame->m_rcData->qpAq =
outFrame->m_encData->m_avgQpAq;
+ outFrame->m_rcData->iCuCount =
outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu;
+ outFrame->m_rcData->pCuCount =
outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu;
+ outFrame->m_rcData->skipCuCount =
outFrame->m_encData->m_frameStats.percent8x8Skip * m_rateControl->m_ncu;
+ outFrame->m_rcData->currentSatd =
curEncoder->m_rce.coeffBits;
+ }
- /* Allow this frame to be recycled if no frame encoders are
using it for reference */
- if (!pic_out)
- {
- ATOMIC_DEC(&outFrame->m_countRefEncoders);
- m_dpb->recycleUnreferenced();
if (m_param->bEnableTemporalFilter)
- m_origPicBuffer->recycleOrigPicList();
- }
- else
- m_exportedPic = outFrame;
-
- m_outputCount++;
- if (m_param->chunkEnd == m_outputCount)
- m_numDelayedPic = 0;
- else
- m_numDelayedPic--;
+ {
+ Frame* curFrame =
m_origPicBuffer->m_mcstfPicList.getPOCMCSTF(outFrame->m_poc);
+ X265_CHECK(curFrame, "Outframe not found in DPB's
mcstfPicList");
+ curFrame->m_refPicCnt[0]--;
+ curFrame->m_refPicCnt[1]--;
+ curFrame =
m_origPicBuffer->m_mcstfOrigPicList.getPOCMCSTF(outFrame->m_poc);
+ X265_CHECK(curFrame, "Outframe not found in OPB's
mcstfOrigPicList");
+ curFrame->m_refPicCnt[1]--;
+ }
+
+ /* Allow this frame to be recycled if no frame encoders
are using it for reference */
+ if (!pic_out[sLayer])
+ {
+ ATOMIC_DEC(&outFrame->m_countRefEncoders);
+ m_dpb->recycleUnreferenced();
+ if (m_param->bEnableTemporalFilter)
+ m_origPicBuffer->recycleOrigPicList();
+ }
+ else
+ m_exportedPic[sLayer] = outFrame;
+
+ m_outputCount++;
+ if (m_param->chunkEnd == m_outputCount)
+ m_numDelayedPic = 0;
+ else if (outFrame->m_sLayerId == m_param->bEnableAlpha)
+ m_numDelayedPic--;
- ret = 1;
+ ret = 1;
+ }
}
/* pop a single frame from decided list, then provide to frame
encoder
@@ -2142,9 +2153,12 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
if (frameEnc[0] && !pass && (!m_param->chunkEnd ||
(m_encodedFrameNum < m_param->chunkEnd)))
{
//Pop non base view pictures from DPB piclist
- frameEnc[1] = m_dpb->m_picList.getPOC(frameEnc[0]->m_poc, 1);
- m_dpb->m_picList.remove(*frameEnc[1]);
- frameEnc[1]->m_lowres.sliceType =
frameEnc[0]->m_lowres.sliceType;
+ for (int layer = 1; layer < m_param->numScalableLayers;
layer++)
+ {
+ Frame* currentFrame =
m_dpb->m_picList.getPOC(frameEnc[0]->m_poc, layer);
+ frameEnc[layer] =
m_dpb->m_picList.removeFrame(*currentFrame);
+ frameEnc[layer]->m_lowres.sliceType =
frameEnc[0]->m_lowres.sliceType;
+ }
if ((m_param->bEnableSceneCutAwareQp & FORWARD) &&
m_param->rc.bStatRead)
{
@@ -2208,7 +2222,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 < MAX_SCALABLE_LAYERS; layer++)
+ for (int layer = 0; layer < m_param->numScalableLayers;
layer++)
{
if (m_dpb->m_frameDataFreeList)
{
@@ -2339,7 +2353,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
}
}
/* determine references, setup RPS, etc */
- for (int layer = 0; layer < MAX_SCALABLE_LAYERS; layer++)
+ for (int layer = 0; layer < m_param->numScalableLayers;
layer++)
m_dpb->prepareEncode(frameEnc[layer]);
if (m_param->bEnableTemporalFilter)
@@ -2361,7 +2375,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 < MAX_SCALABLE_LAYERS; layer++)
+ for (int layer = 0; layer < m_param->numScalableLayers;
layer++)
{
if (!!m_param->selectiveSAO)
{
diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
index 77e32fe42..22976b180 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;
+ Frame* m_exportedPic[MAX_SCALABLE_LAYERS];
FILE* m_analysisFileIn;
FILE* m_analysisFileOut;
FILE* m_naluFile;
@@ -300,7 +300,7 @@ public:
void stopJobs();
void destroy();
- int encode(const x265_picture* pic, x265_picture *pic_out);
+ int encode(const x265_picture* pic, x265_picture **pic_out);
int reconfigureParam(x265_param* encParam, x265_param* param);
diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index ebaf3e840..b36094f33 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -62,6 +62,7 @@ FrameEncoder::FrameEncoder()
memset(&m_rce, 0, sizeof(RateControlEntry));
for(int layer = 0; layer < MAX_SCALABLE_LAYERS; layer++)
m_frame[layer] = NULL;
+ m_retFrameBuffer = { NULL };
}
void FrameEncoder::destroy()
@@ -95,6 +96,7 @@ void FrameEncoder::destroy()
X265_FREE(m_ctuGeomMap);
X265_FREE(m_substreamSizes);
X265_FREE(m_nr);
+ X265_FREE(m_retFrameBuffer);
m_frameFilter.destroy();
@@ -217,6 +219,9 @@ 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[layer] = NULL;
return ok;
}
@@ -286,7 +291,7 @@ bool FrameEncoder::initializeGeoms()
bool FrameEncoder::startCompressFrame(Frame* curFrame[MAX_SCALABLE_LAYERS])
{
m_slicetypeWaitTime = x265_mdate() - m_prevOutputTime;
- for (int layer = 0; layer < MAX_SCALABLE_LAYERS; layer++)
+ for (int layer = 0; layer < m_param->numScalableLayers; layer++)
{
m_frame[layer] = curFrame[layer];
curFrame[layer]->m_encData->m_frameEncoderID = m_jpId;
@@ -368,7 +373,7 @@ void FrameEncoder::threadMain()
m_frame[0]->m_copyMVType.wait();
}
- for(int layer = 0; layer < MAX_SCALABLE_LAYERS; layer ++)
+ for(int layer = 0; layer < m_param->numScalableLayers; layer ++)
compressFrame(layer);
m_done.trigger(); /* FrameEncoder::getEncodedPicture() blocks for
this event */
m_enable.wait();
@@ -604,7 +609,7 @@ void FrameEncoder::compressFrame(int layer)
/* Get the QP for this frame from rate control. This call may block
until
* frames ahead of it in encode order have called rateControlEnd() */
- int qp = (layer == 0) ?
m_top->m_rateControl->rateControlStart(m_frame[layer], &m_rce, m_top) :
m_rce.newQp;
+ int qp = (layer == 0) ?
m_top->m_rateControl->rateControlStart(m_frame[layer], &m_rce, m_top) :
(int)m_rce.newQp;
m_rce.newQp = qp;
@@ -2267,18 +2272,21 @@ void FrameEncoder::vmafFrameLevelScore()
}
#endif
-Frame *FrameEncoder::getEncodedPicture(NALList& output)
+Frame** FrameEncoder::getEncodedPicture(NALList& output)
{
- if (m_frame[0])
+ if (m_frame && m_frame[0])
{
/* block here until worker thread completes */
m_done.wait();
- Frame *ret = m_frame[0];
- m_frame[0] = NULL;
+ for (int i = 0; i < m_param->numScalableLayers; i++)
+ {
+ m_retFrameBuffer[i] = m_frame[i];
+ m_frame[i] = NULL;
+ }
output.takeContents(m_nalList);
m_prevOutputTime = x265_mdate();
- return ret;
+ return m_retFrameBuffer;
}
return NULL;
diff --git a/source/encoder/frameencoder.h b/source/encoder/frameencoder.h
index fa4bad60f..9fcd2dcf5 100644
--- a/source/encoder/frameencoder.h
+++ b/source/encoder/frameencoder.h
@@ -159,7 +159,7 @@ public:
bool startCompressFrame(Frame* curFrame[MAX_SCALABLE_LAYERS]);
/* blocks until worker thread is done, returns access unit */
- Frame *getEncodedPicture(NALList& list);
+ Frame **getEncodedPicture(NALList& list);
void initDecodedPictureHashSEI(int row, int cuAddr, int height, int
layer);
@@ -218,6 +218,7 @@ public:
Encoder* m_top;
x265_param* m_param;
Frame* m_frame[MAX_SCALABLE_LAYERS];
+ Frame** m_retFrameBuffer;
NoiseReduction* m_nr;
ThreadLocalData* m_tld; /* for --no-wpp */
Bitstream* m_outStreams;
diff --git a/source/x265.h b/source/x265.h
index e994ea3e2..7c1acfea3 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -2441,7 +2441,7 @@ int x265_encoder_headers(x265_encoder *, x265_nal
**pp_nal, uint32_t *pi_nal);
* the payloads of all output NALs are guaranteed to be sequential in
memory.
* To flush the encoder and retrieve delayed output pictures, pass
pic_in as NULL.
* Once flushing has begun, all subsequent calls must pass pic_in as
NULL. */
-int x265_encoder_encode(x265_encoder *encoder, x265_nal **pp_nal, uint32_t
*pi_nal, x265_picture *pic_in, x265_picture *pic_out);
+int x265_encoder_encode(x265_encoder *encoder, x265_nal **pp_nal, uint32_t
*pi_nal, x265_picture *pic_in, x265_picture **pic_out);
/* x265_encoder_reconfig:
* various parameters from x265_param are copied.
@@ -2595,7 +2595,7 @@ typedef struct x265_api
int (*encoder_reconfig)(x265_encoder*, x265_param*);
int (*encoder_reconfig_zone)(x265_encoder*, x265_zone*);
int (*encoder_headers)(x265_encoder*, x265_nal**, uint32_t*);
- int (*encoder_encode)(x265_encoder*, x265_nal**, uint32_t*,
x265_picture*, x265_picture*);
+ int (*encoder_encode)(x265_encoder*, x265_nal**, uint32_t*,
x265_picture*, x265_picture**);
void (*encoder_get_stats)(x265_encoder*, x265_stats*,
uint32_t);
void (*encoder_log)(x265_encoder*, int, char**);
void (*encoder_close)(x265_encoder*);
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 070011cf0..6bb81f6d4 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -422,9 +422,12 @@ namespace X265_NS {
if (input)
input->release();
input = NULL;
- if (recon)
- recon->release();
- recon = NULL;
+ for (int i = 0; i < param->numScalableLayers; i++)
+ {
+ if (recon[i])
+ recon[i]->release();
+ recon[i] = NULL;
+ }
if (qpfile)
fclose(qpfile);
qpfile = NULL;
@@ -581,7 +584,7 @@ namespace X265_NS {
int outputBitDepth = 0;
int reconFileBitDepth = 0;
const char *inputfn = NULL;
- const char *reconfn = NULL;
+ const char* reconfn[MAX_SCALABLE_LAYERS] = { NULL };
const char *outputfn = NULL;
const char *preset = NULL;
const char *tune = NULL;
@@ -721,7 +724,7 @@ namespace X265_NS {
OPT("no-progress") this->bProgress = false;
OPT("output") outputfn = optarg;
OPT("input") inputfn = optarg;
- OPT("recon") reconfn = optarg;
+ OPT("recon") reconfn[0] = optarg;
OPT("input-depth") inputBitDepth =
(uint32_t)x265_atoi(optarg, bError);
OPT("dither") this->bDither = true;
OPT("recon-depth") reconFileBitDepth =
(uint32_t)x265_atoi(optarg, bError);
@@ -915,23 +918,40 @@ namespace X265_NS {
this->input->startReader();
- if (reconfn)
+ if (reconfn[0])
{
if (reconFileBitDepth == 0)
reconFileBitDepth = param->internalBitDepth;
- this->recon = ReconFile::open(reconfn, param->sourceWidth,
param->sourceHeight, reconFileBitDepth,
- param->fpsNum, param->fpsDenom, param->internalCsp,
param->sourceBitDepth);
- if (this->recon->isFail())
+#if ENABLE_ALPHA
+ if (param->bEnableAlpha)
{
- x265_log(param, X265_LOG_WARNING, "unable to write
reconstructed outputs file\n");
- this->recon->release();
- this->recon = 0;
+ char* temp = new char[strlen(reconfn[0])];
+ strcpy(temp, reconfn[0]);
+ const char* token = strtok(temp, ".");
+ for (int view = 0; view < param->numScalableLayers; view++)
+ {
+ char* buf = new char[strlen(temp) + 7];
+ sprintf(buf, "%s-%d.yuv", token, view);
+ reconfn[view] = buf;
+ }
+ }
+#endif
+ for (int i = 0; i < param->numScalableLayers; i++)
+ {
+ this->recon[i] = ReconFile::open(reconfn[i],
param->sourceWidth, param->sourceHeight, reconFileBitDepth,
+ param->fpsNum, param->fpsDenom, param->internalCsp,
param->sourceBitDepth);
+ if (this->recon[i]->isFail())
+ {
+ x265_log(param, X265_LOG_WARNING, "unable to write
reconstructed outputs file\n");
+ this->recon[i]->release();
+ this->recon[i] = 0;
+ }
+ else
+ general_log(param, this->recon[i]->getName(),
X265_LOG_INFO,
+ "reconstructed images %dx%d fps %d/%d %s\n",
+ param->sourceWidth, param->sourceHeight,
param->fpsNum, param->fpsDenom,
+ x265_source_csp_names[param->internalCsp]);
}
- else
- general_log(param, this->recon->getName(), X265_LOG_INFO,
- "reconstructed images %dx%d fps %d/%d %s\n",
- param->sourceWidth, param->sourceHeight, param->fpsNum,
param->fpsDenom,
- x265_source_csp_names[param->internalCsp]);
}
#if ENABLE_LIBVMAF
if (!reconfn)
diff --git a/source/x265cli.h b/source/x265cli.h
index 9bdaba0f3..7abf91eb8 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -397,7 +397,7 @@ static const struct option long_options[] =
struct CLIOptions
{
InputFile* input;
- ReconFile* recon;
+ ReconFile* recon[MAX_SCALABLE_LAYERS];
OutputFile* output;
FILE* qpfile;
FILE* zoneFile;
@@ -435,7 +435,8 @@ static const struct option long_options[] =
CLIOptions()
{
input = NULL;
- recon = NULL;
+ for (int i = 0; i < MAX_SCALABLE_LAYERS; i++)
+ recon[i] = NULL;
output = NULL;
qpfile = NULL;
zoneFile = NULL;
--
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240805/0e4be793/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0007-Add-support-for-reconstructed-file-corresponding-to-.patch
Type: application/octet-stream
Size: 51526 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240805/0e4be793/attachment-0001.obj>
More information about the x265-devel
mailing list