[x265] [PATCH] Configure temporal layers and add the temporal layer column in CSV
Kirithika Kalirathnam
kirithika at multicorewareinc.com
Mon Dec 26 11:32:37 UTC 2022
>From f2f87c7bd0eb682From f2f87c7bd0eb6823574ce7d7593fa1da1d8579e3 Mon Sep
17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 16 Dec 2022 18:50:07 +0530
Subject: [PATCH] Configure temporal layers and add the temporal layer column
in CSV
---
doc/reST/cli.rst | 31 +++--
source/common/frame.cpp | 1 +
source/common/frame.h | 2 +
source/common/param.cpp | 4 +-
source/encoder/api.cpp | 4 +
source/encoder/encoder.cpp | 27 +++-
source/x265.h | 263 +++++++++++++++++++++++++++++++++++++
source/x265cli.cpp | 4 +-
source/x265cli.h | 3 +-
9 files changed, 321 insertions(+), 18 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index c7ff17ff8..492b8c1f4 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2630,17 +2630,26 @@ Bitstream options
2. CRC
3. Checksum
-.. option:: --temporal-layers,--no-temporal-layers
-
- Enable a temporal sub layer. All referenced I/P/B frames are in the
- base layer and all unreferenced B frames are placed in a temporal
- enhancement layer. A decoder may choose to drop the enhancement layer
- and only decode and display the base layer slices.
-
- If used with a fixed GOP (:option:`--b-adapt` 0) and :option:`--bframes`
- 3 then the two layers evenly split the frame rate, with a cadence of
- PbBbP. You probably also want :option:`--no-scenecut` and a keyframe
- interval that is a multiple of 4.
+.. option:: --temporal-layers <integer>
+
+ Enable specified number of temporal sub layers. For any frame in layer N,
+ all referenced frames are in the layer N or N-1.A decoder may choose to
drop the enhancement layer
+ and only decode and display the base layer slices.Allowed number of
temporal sub-layers
+ are 2 to 5.(2 and 5 inclusive)
+
+ When enabled,temporal layers 3 through 5 configures a fixed miniGOP with
the number of bframes as shown below
+ unless miniGOP size is modified due to lookahead decisions.Temporal layer
2 is a special case that has
+ all reference frames in base layer and non-reference frames in
enhancement layer without any constraint on the
+ number of bframes.Default disabled.
+ +----------------+--------+
+ | temporal layer | bframes|
+ +================+========+
+ | 3 | 3 |
+ +----------------+--------+
+ | 4 | 7 |
+ +----------------+--------+
+ | 5 | 15 |
+ +----------------+--------+
.. option:: --log2-max-poc-lsb <integer>
diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index 019a5cb76..48c538714 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -74,6 +74,7 @@ Frame::Frame()
m_nextMCSTF = NULL;
m_prevMCSTF = NULL;
+ m_tempLayer = 0;
}
bool Frame::create(x265_param *param, float* quantOffsets)
diff --git a/source/common/frame.h b/source/common/frame.h
index d7bbc42b8..1ef0547bd 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -159,6 +159,8 @@ public:
int m_isInsideWindow;
+ /*Frame's temporal layer info*/
+ uint8_t m_tempLayer;
Frame();
bool create(x265_param *param, float* quantOffsets);
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 03c3beb70..58bc65494 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1152,7 +1152,7 @@ int x265_param_parse(x265_param* p, const char* name,
const char* value)
p->scenecutThreshold = atoi(value);
}
}
- OPT("temporal-layers") p->bEnableTemporalSubLayers = atobool(value);
+ OPT("temporal-layers") p->bEnableTemporalSubLayers = atoi(value);
OPT("keyint") p->keyframeMax = atoi(value);
OPT("min-keyint") p->keyframeMin = atoi(value);
OPT("rc-lookahead") p->lookaheadDepth = atoi(value);
@@ -2270,7 +2270,7 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
BOOL(p->bEmitHRDSEI, "hrd");
BOOL(p->bEmitInfoSEI, "info");
s += sprintf(s, " hash=%d", p->decodedPictureHashSEI);
- BOOL(p->bEnableTemporalSubLayers, "temporal-layers");
+ s += sprintf(s, " temporal-layers=%d", p->bEnableTemporalSubLayers);
BOOL(p->bOpenGOP, "open-gop");
s += sprintf(s, " min-keyint=%d", p->keyframeMin);
s += sprintf(s, " keyint=%d", p->keyframeMax);
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 482ab9b8e..5f1bba67b 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -1297,6 +1297,8 @@ FILE* x265_csvlog_open(const x265_param* param)
if (param->csvLogLevel)
{
fprintf(csvfp, "Encode Order, Type, POC, QP, Bits,
Scenecut, ");
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(csvfp, "Temporal Sub Layer ID, ");
if (param->csvLogLevel >= 2)
fprintf(csvfp, "I/P cost ratio, ");
if (param->rc.rateControlMode == X265_RC_CRF)
@@ -1410,6 +1412,8 @@ void x265_csvlog_frame(const x265_param* param, const
x265_picture* pic)
const x265_frame_stats* frameStats = &pic->frameData;
fprintf(param->csvfpt, "%d, %c-SLICE, %4d, %2.2lf, %10d, %d,",
frameStats->encoderOrder, frameStats->sliceType, frameStats->poc,
frameStats->qp, (int)frameStats->bits, frameStats->bScenecut);
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(param->csvfpt, "%d,", frameStats->tLayer);
if (param->csvLogLevel >= 2)
fprintf(param->csvfpt, "%.2f,", frameStats->ipCostRatio);
if (param->rc.rateControlMode == X265_RC_CRF)
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 38e1e56eb..b2a8ab838 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1899,6 +1899,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
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;
@@ -3880,12 +3881,36 @@ void Encoder::configure(x265_param *p)
p->limitReferences = 0;
}
- if (p->bEnableTemporalSubLayers && !p->bframes)
+ if ((p->bEnableTemporalSubLayers > 2) && !p->bframes)
{
x265_log(p, X265_LOG_WARNING, "B frames not enabled, temporal
sublayer disabled\n");
p->bEnableTemporalSubLayers = 0;
}
+ if (!!p->bEnableTemporalSubLayers && p->bEnableTemporalSubLayers < 2)
+ {
+ p->bEnableTemporalSubLayers = 0;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
less than 2; Disabling temporal layers\n");
+ }
+
+ if (p->bEnableTemporalSubLayers > 5)
+ {
+ p->bEnableTemporalSubLayers = 5;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
more than 5; Reducing the temporal sublayers to 5\n");
+ }
+
+ // Assign number of B frames for temporal layers
+ if (p->bEnableTemporalSubLayers > 2)
+ p->bframes =
x265_temporal_layer_bframes[p->bEnableTemporalSubLayers - 1];
+
+ if (p->bEnableTemporalSubLayers > 2)
+ {
+ if (!p->bFrameAdaptive)
+ x265_log(p, X265_LOG_WARNING, "Disabling adaptive B-frame
placement to support temporal sub-layers\n");
+
+ p->bFrameAdaptive = 0;
+ }
+
m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
diff --git a/source/x265.h b/source/x265.h
index 6fb87a62a..86d324d10 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -312,6 +312,7 @@ typedef struct x265_frame_stats
double vmafFrameScore;
double bufferFillFinal;
double unclippedBufferFillFinal;
+ uint8_t tLayer;
} x265_frame_stats;
typedef struct x265_ctu_info_t
@@ -616,6 +617,10 @@ typedef enum
#define FORWARD_WINDOW 2 /* Scenecut window after a scenecut */
#define BWD_WINDOW_DELTA 0.4
+#define X265_MAX_GOP_CONFIG 3
+#define X265_MAX_GOP_LENGTH 16
+#define MAX_T_LAYERS 7
+
typedef struct x265_cli_csp
{
int planes;
@@ -749,6 +754,264 @@ typedef struct x265_vmaf_commondata
static const x265_vmaf_commondata vcd[] = { { NULL, (char
*)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0,
0, NULL, 0, 1, 0 } };
+typedef struct x265_temporal_layer {
+ int poc_offset; /* POC offset */
+ int8_t layer; /* Current layer */
+ int8_t qp_offset; /* QP offset */
+} x265_temporal_layer;
+
+static const int8_t x265_temporal_layer_bframes[MAX_T_LAYERS] = {-1, -1,
3, 7, 15, -1, -1};
+
+static const int8_t x265_gop_ra_length[X265_MAX_GOP_CONFIG] = { 4, 8, 16};
+static const x265_temporal_layer
x265_gop_ra[X265_MAX_GOP_CONFIG][X265_MAX_GOP_LENGTH] = {
+ {
+ {
+ 4,
+ 0,
+ 1,
+ },
+ {
+ 2,
+ 1,
+ 5,
+ },
+ {
+ 1,
+ 2,
+ 3,
+ },
+ {
+ 3,
+ 2,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ }
+ },
+
+ {
+ {
+ 8,
+ 0,
+ 1,
+ },
+ {
+ 4,
+ 1,
+ 5,
+ },
+ {
+ 2,
+ 2,
+ 4,
+ },
+ {
+ 1,
+ 3,
+ 5,
+ },
+ {
+ 3,
+ 3,
+ 2,
+ },
+ {
+ 6,
+ 2,
+ 5,
+ },
+ {
+ 5,
+ 3,
+ 4,
+ },
+ {
+ 7,
+ 3,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ },
+ {
+ {
+ 16,
+ 0,
+ 1,
+ },
+ {
+ 8,
+ 1,
+ 6,
+ },
+ {
+ 4,
+ 2,
+ 5,
+ },
+ {
+ 2,
+ 3,
+ 6,
+ },
+ {
+ 1,
+ 4,
+ 4,
+ },
+ {
+ 3,
+ 4,
+ 6,
+ },
+ {
+ 6,
+ 3,
+ 5,
+ },
+ {
+ 5,
+ 4,
+ 6,
+ },
+ {
+ 7,
+ 4,
+ 1,
+ },
+ {
+ 12,
+ 2,
+ 6,
+ },
+ {
+ 10,
+ 3,
+ 5,
+ },
+ {
+ 9,
+ 4,
+ 6,
+ },
+ {
+ 11,
+ 4,
+ 4,
+ },
+ {
+ 14,
+ 3,
+ 6,
+ },
+ {
+ 13,
+ 4,
+ 5,
+ },
+ {
+ 15,
+ 4,
+ 6,
+ }
+ }
+};
typedef enum
{
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 53e04fa6b..79e4c2d8e 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -349,8 +349,8 @@ namespace X265_NS {
H0(" --[no-]repeat-headers Emit SPS and PPS headers at
each keyframe. Default %s\n", OPT(param->bRepeatHeaders));
H0(" --[no-]info Emit SEI identifying encoder
and parameters. Default %s\n", OPT(param->bEmitInfoSEI));
H0(" --[no-]hrd Enable HRD parameters
signaling. Default %s\n", OPT(param->bEmitHRDSEI));
- H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
- H0(" --[no-]temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
+ H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
+ H0(" --temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
H0(" --[no-]aud Emit access unit delimiters
at the start of each access unit. Default %s\n",
OPT(param->bEnableAccessUnitDelimiters));
H0(" --[no-]eob Emit end of bitstream nal
unit at the end of the bitstream. Default %s\n",
OPT(param->bEnableEndOfBitstream));
H0(" --[no-]eos Emit end of sequence nal unit
at the end of every coded video sequence. Default %s\n",
OPT(param->bEnableEndOfSequence));
diff --git a/source/x265cli.h b/source/x265cli.h
index f4e748787..d5b816e80 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -304,8 +304,7 @@ static const struct option long_options[] =
{ "dynamic-refine", no_argument, NULL, 0 },
{ "no-dynamic-refine", no_argument, NULL, 0 },
{ "strict-cbr", no_argument, NULL, 0 },
- { "temporal-layers", no_argument, NULL, 0 },
- { "no-temporal-layers", no_argument, NULL, 0 },
+ { "temporal-layers", required_argument, NULL, 0 },
{ "qg-size", required_argument, NULL, 0 },
{ "recon-y4m-exec", required_argument, NULL, 0 },
{ "analyze-src-pics", no_argument, NULL, 0 },
--
2.28.0.windows.1
>From f2f87c7bd0eb6823574ce7d7593fa1da1d8579e3 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 16 Dec 2022 18:50:07 +0530
Subject: [PATCH] Configure temporal layers and add the temporal layer column
in CSV
---
doc/reST/cli.rst | 31 +++--
source/common/frame.cpp | 1 +
source/common/frame.h | 2 +
source/common/param.cpp | 4 +-
source/encoder/api.cpp | 4 +
source/encoder/encoder.cpp | 27 +++-
source/x265.h | 263 +++++++++++++++++++++++++++++++++++++
source/x265cli.cpp | 4 +-
source/x265cli.h | 3 +-
9 files changed, 321 insertions(+), 18 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index c7ff17ff8..492b8c1f4 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2630,17 +2630,26 @@ Bitstream options
2. CRC
3. Checksum
-.. option:: --temporal-layers,--no-temporal-layers
-
- Enable a temporal sub layer. All referenced I/P/B frames are in the
- base layer and all unreferenced B frames are placed in a temporal
- enhancement layer. A decoder may choose to drop the enhancement layer
- and only decode and display the base layer slices.
-
- If used with a fixed GOP (:option:`--b-adapt` 0) and :option:`--bframes`
- 3 then the two layers evenly split the frame rate, with a cadence of
- PbBbP. You probably also want :option:`--no-scenecut` and a keyframe
- interval that is a multiple of 4.
+.. option:: --temporal-layers <integer>
+
+ Enable specified number of temporal sub layers. For any frame in layer N,
+ all referenced frames are in the layer N or N-1.A decoder may choose to
drop the enhancement layer
+ and only decode and display the base layer slices.Allowed number of
temporal sub-layers
+ are 2 to 5.(2 and 5 inclusive)
+
+ When enabled,temporal layers 3 through 5 configures a fixed miniGOP with
the number of bframes as shown below
+ unless miniGOP size is modified due to lookahead decisions.Temporal layer
2 is a special case that has
+ all reference frames in base layer and non-reference frames in
enhancement layer without any constraint on the
+ number of bframes.Default disabled.
+ +----------------+--------+
+ | temporal layer | bframes|
+ +================+========+
+ | 3 | 3 |
+ +----------------+--------+
+ | 4 | 7 |
+ +----------------+--------+
+ | 5 | 15 |
+ +----------------+--------+
.. option:: --log2-max-poc-lsb <integer>
diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index 019a5cb76..48c538714 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -74,6 +74,7 @@ Frame::Frame()
m_nextMCSTF = NULL;
m_prevMCSTF = NULL;
+ m_tempLayer = 0;
}
bool Frame::create(x265_param *param, float* quantOffsets)
diff --git a/source/common/frame.h b/source/common/frame.h
index d7bbc42b8..1ef0547bd 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -159,6 +159,8 @@ public:
int m_isInsideWindow;
+ /*Frame's temporal layer info*/
+ uint8_t m_tempLayer;
Frame();
bool create(x265_param *param, float* quantOffsets);
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 03c3beb70..58bc65494 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1152,7 +1152,7 @@ int x265_param_parse(x265_param* p, const char* name,
const char* value)
p->scenecutThreshold = atoi(value);
}
}
- OPT("temporal-layers") p->bEnableTemporalSubLayers = atobool(value);
+ OPT("temporal-layers") p->bEnableTemporalSubLayers = atoi(value);
OPT("keyint") p->keyframeMax = atoi(value);
OPT("min-keyint") p->keyframeMin = atoi(value);
OPT("rc-lookahead") p->lookaheadDepth = atoi(value);
@@ -2270,7 +2270,7 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
BOOL(p->bEmitHRDSEI, "hrd");
BOOL(p->bEmitInfoSEI, "info");
s += sprintf(s, " hash=%d", p->decodedPictureHashSEI);
- BOOL(p->bEnableTemporalSubLayers, "temporal-layers");
+ s += sprintf(s, " temporal-layers=%d", p->bEnableTemporalSubLayers);
BOOL(p->bOpenGOP, "open-gop");
s += sprintf(s, " min-keyint=%d", p->keyframeMin);
s += sprintf(s, " keyint=%d", p->keyframeMax);
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 482ab9b8e..5f1bba67b 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -1297,6 +1297,8 @@ FILE* x265_csvlog_open(const x265_param* param)
if (param->csvLogLevel)
{
fprintf(csvfp, "Encode Order, Type, POC, QP, Bits,
Scenecut, ");
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(csvfp, "Temporal Sub Layer ID, ");
if (param->csvLogLevel >= 2)
fprintf(csvfp, "I/P cost ratio, ");
if (param->rc.rateControlMode == X265_RC_CRF)
@@ -1410,6 +1412,8 @@ void x265_csvlog_frame(const x265_param* param, const
x265_picture* pic)
const x265_frame_stats* frameStats = &pic->frameData;
fprintf(param->csvfpt, "%d, %c-SLICE, %4d, %2.2lf, %10d, %d,",
frameStats->encoderOrder, frameStats->sliceType, frameStats->poc,
frameStats->qp, (int)frameStats->bits, frameStats->bScenecut);
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(param->csvfpt, "%d,", frameStats->tLayer);
if (param->csvLogLevel >= 2)
fprintf(param->csvfpt, "%.2f,", frameStats->ipCostRatio);
if (param->rc.rateControlMode == X265_RC_CRF)
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 38e1e56eb..b2a8ab838 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1899,6 +1899,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
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;
@@ -3880,12 +3881,36 @@ void Encoder::configure(x265_param *p)
p->limitReferences = 0;
}
- if (p->bEnableTemporalSubLayers && !p->bframes)
+ if ((p->bEnableTemporalSubLayers > 2) && !p->bframes)
{
x265_log(p, X265_LOG_WARNING, "B frames not enabled, temporal
sublayer disabled\n");
p->bEnableTemporalSubLayers = 0;
}
+ if (!!p->bEnableTemporalSubLayers && p->bEnableTemporalSubLayers < 2)
+ {
+ p->bEnableTemporalSubLayers = 0;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
less than 2; Disabling temporal layers\n");
+ }
+
+ if (p->bEnableTemporalSubLayers > 5)
+ {
+ p->bEnableTemporalSubLayers = 5;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
more than 5; Reducing the temporal sublayers to 5\n");
+ }
+
+ // Assign number of B frames for temporal layers
+ if (p->bEnableTemporalSubLayers > 2)
+ p->bframes =
x265_temporal_layer_bframes[p->bEnableTemporalSubLayers - 1];
+
+ if (p->bEnableTemporalSubLayers > 2)
+ {
+ if (!p->bFrameAdaptive)
+ x265_log(p, X265_LOG_WARNING, "Disabling adaptive B-frame
placement to support temporal sub-layers\n");
+
+ p->bFrameAdaptive = 0;
+ }
+
m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
diff --git a/source/x265.h b/source/x265.h
index 6fb87a62a..86d324d10 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -312,6 +312,7 @@ typedef struct x265_frame_stats
double vmafFrameScore;
double bufferFillFinal;
double unclippedBufferFillFinal;
+ uint8_t tLayer;
} x265_frame_stats;
typedef struct x265_ctu_info_t
@@ -616,6 +617,10 @@ typedef enum
#define FORWARD_WINDOW 2 /* Scenecut window after a scenecut */
#define BWD_WINDOW_DELTA 0.4
+#define X265_MAX_GOP_CONFIG 3
+#define X265_MAX_GOP_LENGTH 16
+#define MAX_T_LAYERS 7
+
typedef struct x265_cli_csp
{
int planes;
@@ -749,6 +754,264 @@ typedef struct x265_vmaf_commondata
static const x265_vmaf_commondata vcd[] = { { NULL, (char
*)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0,
0, NULL, 0, 1, 0 } };
+typedef struct x265_temporal_layer {
+ int poc_offset; /* POC offset */
+ int8_t layer; /* Current layer */
+ int8_t qp_offset; /* QP offset */
+} x265_temporal_layer;
+
+static const int8_t x265_temporal_layer_bframes[MAX_T_LAYERS] = {-1, -1,
3, 7, 15, -1, -1};
+
+static const int8_t x265_gop_ra_length[X265_MAX_GOP_CONFIG] = { 4, 8, 16};
+static const x265_temporal_layer
x265_gop_ra[X265_MAX_GOP_CONFIG][X265_MAX_GOP_LENGTH] = {
+ {
+ {
+ 4,
+ 0,
+ 1,
+ },
+ {
+ 2,
+ 1,
+ 5,
+ },
+ {
+ 1,
+ 2,
+ 3,
+ },
+ {
+ 3,
+ 2,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ }
+ },
+
+ {
+ {
+ 8,
+ 0,
+ 1,
+ },
+ {
+ 4,
+ 1,
+ 5,
+ },
+ {
+ 2,
+ 2,
+ 4,
+ },
+ {
+ 1,
+ 3,
+ 5,
+ },
+ {
+ 3,
+ 3,
+ 2,
+ },
+ {
+ 6,
+ 2,
+ 5,
+ },
+ {
+ 5,
+ 3,
+ 4,
+ },
+ {
+ 7,
+ 3,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ },
+ {
+ {
+ 16,
+ 0,
+ 1,
+ },
+ {
+ 8,
+ 1,
+ 6,
+ },
+ {
+ 4,
+ 2,
+ 5,
+ },
+ {
+ 2,
+ 3,
+ 6,
+ },
+ {
+ 1,
+ 4,
+ 4,
+ },
+ {
+ 3,
+ 4,
+ 6,
+ },
+ {
+ 6,
+ 3,
+ 5,
+ },
+ {
+ 5,
+ 4,
+ 6,
+ },
+ {
+ 7,
+ 4,
+ 1,
+ },
+ {
+ 12,
+ 2,
+ 6,
+ },
+ {
+ 10,
+ 3,
+ 5,
+ },
+ {
+ 9,
+ 4,
+ 6,
+ },
+ {
+ 11,
+ 4,
+ 4,
+ },
+ {
+ 14,
+ 3,
+ 6,
+ },
+ {
+ 13,
+ 4,
+ 5,
+ },
+ {
+ 15,
+ 4,
+ 6,
+ }
+ }
+};
typedef enum
{
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 53e04fa6b..79e4c2d8e 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -349,8 +349,8 @@ namespace X265_NS {
H0(" --[no-]repeat-headers Emit SPS and PPS headers at
each keyframe. Default %s\n", OPT(param->bRepeatHeaders));
H0(" --[no-]info Emit SEI identifying encoder
and parameters. Default %s\n", OPT(param->bEmitInfoSEI));
H0(" --[no-]hrd Enable HRD parameters
signaling. Default %s\n", OPT(param->bEmitHRDSEI));
- H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
- H0(" --[no-]temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
+ H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
+ H0(" --temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
H0(" --[no-]aud Emit access unit delimiters
at the start of each access unit. Default %s\n",
OPT(param->bEnableAccessUnitDelimiters));
H0(" --[no-]eob Emit end of bitstream nal
unit at the end of the bitstream. Default %s\n",
OPT(param->bEnableEndOfBitstream));
H0(" --[no-]eos Emit end of sequence nal unit
at the end of every coded video sequence. Default %s\n",
OPT(param->bEnableEndOfSequence));
diff --git a/source/x265cli.h b/source/x265cli.h
index f4e748787..d5b816e80 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -304,8 +304,7 @@ static const struct option long_options[] =
{ "dynamic-refine", no_argument, NULL, 0 },
{ "no-dynamic-refine", no_argument, NULL, 0 },
{ "strict-cbr", no_argument, NULL, 0 },
- { "temporal-layers", no_argument, NULL, 0 },
- { "no-temporal-layers", no_argument, NULL, 0 },
+ { "temporal-layers", required_argument, NULL, 0 },
{ "qg-size", required_argument, NULL, 0 },
{ "recon-y4m-exec", required_argument, NULL, 0 },
{ "analyze-src-pics", no_argument, NULL, 0 },
--
2.28.0.windows.1
3574ce7d7593fa1da1d8579e3 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 16 Dec 2022 18:50:07 +0530
Subject: [PATCH] Configure temporal layers and add the temporal layer column
in CSV
---
doc/reST/cli.rst | 31 +++--
source/common/frame.cpp | 1 +
source/common/frame.h | 2 +
source/common/param.cpp | 4 +-
source/encoder/api.cpp | 4 +
source/encoder/encoder.cpp | 27 +++-
source/x265.h | 263 +++++++++++++++++++++++++++++++++++++
source/x265cli.cpp | 4 +-
source/x265cli.h | 3 +-
9 files changed, 321 insertions(+), 18 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index c7ff17ff8..492b8c1f4 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2630,17 +2630,26 @@ Bitstream options
2. CRC
3. Checksum
-.. option:: --temporal-layers,--no-temporal-layers
-
- Enable a temporal sub layer. All referenced I/P/B frames are in the
- base layer and all unreferenced B frames are placed in a temporal
- enhancement layer. A decoder may choose to drop the enhancement layer
- and only decode and display the base layer slices.
-
- If used with a fixed GOP (:option:`--b-adapt` 0) and :option:`--bframes`
- 3 then the two layers evenly split the frame rate, with a cadence of
- PbBbP. You probably also want :option:`--no-scenecut` and a keyframe
- interval that is a multiple of 4.
+.. option:: --temporal-layers <integer>
+
+ Enable specified number of temporal sub layers. For any frame in layer N,
+ all referenced frames are in the layer N or N-1.A decoder may choose to
drop the enhancement layer
+ and only decode and display the base layer slices.Allowed number of
temporal sub-layers
+ are 2 to 5.(2 and 5 inclusive)
+
+ When enabled,temporal layers 3 through 5 configures a fixed miniGOP with
the number of bframes as shown below
+ unless miniGOP size is modified due to lookahead decisions.Temporal layer
2 is a special case that has
+ all reference frames in base layer and non-reference frames in
enhancement layer without any constraint on the
+ number of bframes.Default disabled.
+ +----------------+--------+
+ | temporal layer | bframes|
+ +================+========+
+ | 3 | 3 |
+ +----------------+--------+
+ | 4 | 7 |
+ +----------------+--------+
+ | 5 | 15 |
+ +----------------+--------+
.. option:: --log2-max-poc-lsb <integer>
diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index 019a5cb76..48c538714 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -74,6 +74,7 @@ Frame::Frame()
m_nextMCSTF = NULL;
m_prevMCSTF = NULL;
+ m_tempLayer = 0;
}
bool Frame::create(x265_param *param, float* quantOffsets)
diff --git a/source/common/frame.h b/source/common/frame.h
index d7bbc42b8..1ef0547bd 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -159,6 +159,8 @@ public:
int m_isInsideWindow;
+ /*Frame's temporal layer info*/
+ uint8_t m_tempLayer;
Frame();
bool create(x265_param *param, float* quantOffsets);
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 03c3beb70..58bc65494 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1152,7 +1152,7 @@ int x265_param_parse(x265_param* p, const char* name,
const char* value)
p->scenecutThreshold = atoi(value);
}
}
- OPT("temporal-layers") p->bEnableTemporalSubLayers = atobool(value);
+ OPT("temporal-layers") p->bEnableTemporalSubLayers = atoi(value);
OPT("keyint") p->keyframeMax = atoi(value);
OPT("min-keyint") p->keyframeMin = atoi(value);
OPT("rc-lookahead") p->lookaheadDepth = atoi(value);
@@ -2270,7 +2270,7 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
BOOL(p->bEmitHRDSEI, "hrd");
BOOL(p->bEmitInfoSEI, "info");
s += sprintf(s, " hash=%d", p->decodedPictureHashSEI);
- BOOL(p->bEnableTemporalSubLayers, "temporal-layers");
+ s += sprintf(s, " temporal-layers=%d", p->bEnableTemporalSubLayers);
BOOL(p->bOpenGOP, "open-gop");
s += sprintf(s, " min-keyint=%d", p->keyframeMin);
s += sprintf(s, " keyint=%d", p->keyframeMax);
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 482ab9b8e..5f1bba67b 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -1297,6 +1297,8 @@ FILE* x265_csvlog_open(const x265_param* param)
if (param->csvLogLevel)
{
fprintf(csvfp, "Encode Order, Type, POC, QP, Bits,
Scenecut, ");
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(csvfp, "Temporal Sub Layer ID, ");
if (param->csvLogLevel >= 2)
fprintf(csvfp, "I/P cost ratio, ");
if (param->rc.rateControlMode == X265_RC_CRF)
@@ -1410,6 +1412,8 @@ void x265_csvlog_frame(const x265_param* param, const
x265_picture* pic)
const x265_frame_stats* frameStats = &pic->frameData;
fprintf(param->csvfpt, "%d, %c-SLICE, %4d, %2.2lf, %10d, %d,",
frameStats->encoderOrder, frameStats->sliceType, frameStats->poc,
frameStats->qp, (int)frameStats->bits, frameStats->bScenecut);
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(param->csvfpt, "%d,", frameStats->tLayer);
if (param->csvLogLevel >= 2)
fprintf(param->csvfpt, "%.2f,", frameStats->ipCostRatio);
if (param->rc.rateControlMode == X265_RC_CRF)
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 38e1e56eb..b2a8ab838 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1899,6 +1899,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
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;
@@ -3880,12 +3881,36 @@ void Encoder::configure(x265_param *p)
p->limitReferences = 0;
}
- if (p->bEnableTemporalSubLayers && !p->bframes)
+ if ((p->bEnableTemporalSubLayers > 2) && !p->bframes)
{
x265_log(p, X265_LOG_WARNING, "B frames not enabled, temporal
sublayer disabled\n");
p->bEnableTemporalSubLayers = 0;
}
+ if (!!p->bEnableTemporalSubLayers && p->bEnableTemporalSubLayers < 2)
+ {
+ p->bEnableTemporalSubLayers = 0;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
less than 2; Disabling temporal layers\n");
+ }
+
+ if (p->bEnableTemporalSubLayers > 5)
+ {
+ p->bEnableTemporalSubLayers = 5;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
more than 5; Reducing the temporal sublayers to 5\n");
+ }
+
+ // Assign number of B frames for temporal layers
+ if (p->bEnableTemporalSubLayers > 2)
+ p->bframes =
x265_temporal_layer_bframes[p->bEnableTemporalSubLayers - 1];
+
+ if (p->bEnableTemporalSubLayers > 2)
+ {
+ if (!p->bFrameAdaptive)
+ x265_log(p, X265_LOG_WARNING, "Disabling adaptive B-frame
placement to support temporal sub-layers\n");
+
+ p->bFrameAdaptive = 0;
+ }
+
m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
diff --git a/source/x265.h b/source/x265.h
index 6fb87a62a..86d324d10 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -312,6 +312,7 @@ typedef struct x265_frame_stats
double vmafFrameScore;
double bufferFillFinal;
double unclippedBufferFillFinal;
+ uint8_t tLayer;
} x265_frame_stats;
typedef struct x265_ctu_info_t
@@ -616,6 +617,10 @@ typedef enum
#define FORWARD_WINDOW 2 /* Scenecut window after a scenecut */
#define BWD_WINDOW_DELTA 0.4
+#define X265_MAX_GOP_CONFIG 3
+#define X265_MAX_GOP_LENGTH 16
+#define MAX_T_LAYERS 7
+
typedef struct x265_cli_csp
{
int planes;
@@ -749,6 +754,264 @@ typedef struct x265_vmaf_commondata
static const x265_vmaf_commondata vcd[] = { { NULL, (char
*)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0,
0, NULL, 0, 1, 0 } };
+typedef struct x265_temporal_layer {
+ int poc_offset; /* POC offset */
+ int8_t layer; /* Current layer */
+ int8_t qp_offset; /* QP offset */
+} x265_temporal_layer;
+
+static const int8_t x265_temporal_layer_bframes[MAX_T_LAYERS] = {-1, -1,
3, 7, 15, -1, -1};
+
+static const int8_t x265_gop_ra_length[X265_MAX_GOP_CONFIG] = { 4, 8, 16};
+static const x265_temporal_layer
x265_gop_ra[X265_MAX_GOP_CONFIG][X265_MAX_GOP_LENGTH] = {
+ {
+ {
+ 4,
+ 0,
+ 1,
+ },
+ {
+ 2,
+ 1,
+ 5,
+ },
+ {
+ 1,
+ 2,
+ 3,
+ },
+ {
+ 3,
+ 2,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ }
+ },
+
+ {
+ {
+ 8,
+ 0,
+ 1,
+ },
+ {
+ 4,
+ 1,
+ 5,
+ },
+ {
+ 2,
+ 2,
+ 4,
+ },
+ {
+ 1,
+ 3,
+ 5,
+ },
+ {
+ 3,
+ 3,
+ 2,
+ },
+ {
+ 6,
+ 2,
+ 5,
+ },
+ {
+ 5,
+ 3,
+ 4,
+ },
+ {
+ 7,
+ 3,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ },
+ {
+ {
+ 16,
+ 0,
+ 1,
+ },
+ {
+ 8,
+ 1,
+ 6,
+ },
+ {
+ 4,
+ 2,
+ 5,
+ },
+ {
+ 2,
+ 3,
+ 6,
+ },
+ {
+ 1,
+ 4,
+ 4,
+ },
+ {
+ 3,
+ 4,
+ 6,
+ },
+ {
+ 6,
+ 3,
+ 5,
+ },
+ {
+ 5,
+ 4,
+ 6,
+ },
+ {
+ 7,
+ 4,
+ 1,
+ },
+ {
+ 12,
+ 2,
+ 6,
+ },
+ {
+ 10,
+ 3,
+ 5,
+ },
+ {
+ 9,
+ 4,
+ 6,
+ },
+ {
+ 11,
+ 4,
+ 4,
+ },
+ {
+ 14,
+ 3,
+ 6,
+ },
+ {
+ 13,
+ 4,
+ 5,
+ },
+ {
+ 15,
+ 4,
+ 6,
+ }
+ }
+};
typedef enum
{
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 53e04fa6b..79e4c2d8e 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -349,8 +349,8 @@ namespace X265_NS {
H0(" --[no-]repeat-headers Emit SPS and PPS headers at
each keyframe. Default %s\n", OPT(param->bRepeatHeaders));
H0(" --[no-]info Emit SEI identifying encoder
and parameters. Default %s\n", OPT(param->bEmitInfoSEI));
H0(" --[no-]hrd Enable HRD parameters
signaling. Default %s\n", OPT(param->bEmitHRDSEI));
- H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
- H0(" --[no-]temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
+ H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
+ H0(" --temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
H0(" --[no-]aud Emit access unit delimiters
at the start of each access unit. Default %s\n",
OPT(param->bEnableAccessUnitDelimiters));
H0(" --[no-]eob Emit end of bitstream nal
unit at the end of the bitstream. Default %s\n",
OPT(param->bEnableEndOfBitstream));
H0(" --[no-]eos Emit end of sequence nal unit
at the end of every coded video sequence. Default %s\n",
OPT(param->bEnableEndOfSequence));
diff --git a/source/x265cli.h b/source/x265cli.h
index f4e748787..d5b816e80 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -304,8 +304,7 @@ static const struct option long_options[] =
{ "dynamic-refine", no_argument, NULL, 0 },
{ "no-dynamic-refine", no_argument, NULL, 0 },
{ "strict-cbr", no_argument, NULL, 0 },
- { "temporal-layers", no_argument, NULL, 0 },
- { "no-temporal-layers", no_argument, NULL, 0 },
+ { "temporal-layers", required_argument, NULL, 0 },
{ "qg-size", required_argument, NULL, 0 },
{ "recon-y4m-exec", required_argument, NULL, 0 },
{ "analyze-src-pics", no_argument, NULL, 0 },
--
2.28.0.windows.1
>From f2f87c7bd0eb6823574ce7d7593fa1da1d8579e3 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 16 Dec 2022 18:50:07 +0530
Subject: [PATCH] Configure temporal layers and add the temporal layer column
in CSV
---
doc/reST/cli.rst | 31 +++--
source/common/frame.cpp | 1 +
source/common/frame.h | 2 +
source/common/param.cpp | 4 +-
source/encoder/api.cpp | 4 +
source/encoder/encoder.cpp | 27 +++-
source/x265.h | 263 +++++++++++++++++++++++++++++++++++++
source/x265cli.cpp | 4 +-
source/x265cli.h | 3 +-
9 files changed, 321 insertions(+), 18 deletions(-)
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index c7ff17ff8..492b8c1f4 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2630,17 +2630,26 @@ Bitstream options
2. CRC
3. Checksum
-.. option:: --temporal-layers,--no-temporal-layers
-
- Enable a temporal sub layer. All referenced I/P/B frames are in the
- base layer and all unreferenced B frames are placed in a temporal
- enhancement layer. A decoder may choose to drop the enhancement layer
- and only decode and display the base layer slices.
-
- If used with a fixed GOP (:option:`--b-adapt` 0) and :option:`--bframes`
- 3 then the two layers evenly split the frame rate, with a cadence of
- PbBbP. You probably also want :option:`--no-scenecut` and a keyframe
- interval that is a multiple of 4.
+.. option:: --temporal-layers <integer>
+
+ Enable specified number of temporal sub layers. For any frame in layer N,
+ all referenced frames are in the layer N or N-1.A decoder may choose to
drop the enhancement layer
+ and only decode and display the base layer slices.Allowed number of
temporal sub-layers
+ are 2 to 5.(2 and 5 inclusive)
+
+ When enabled,temporal layers 3 through 5 configures a fixed miniGOP with
the number of bframes as shown below
+ unless miniGOP size is modified due to lookahead decisions.Temporal layer
2 is a special case that has
+ all reference frames in base layer and non-reference frames in
enhancement layer without any constraint on the
+ number of bframes.Default disabled.
+ +----------------+--------+
+ | temporal layer | bframes|
+ +================+========+
+ | 3 | 3 |
+ +----------------+--------+
+ | 4 | 7 |
+ +----------------+--------+
+ | 5 | 15 |
+ +----------------+--------+
.. option:: --log2-max-poc-lsb <integer>
diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index 019a5cb76..48c538714 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -74,6 +74,7 @@ Frame::Frame()
m_nextMCSTF = NULL;
m_prevMCSTF = NULL;
+ m_tempLayer = 0;
}
bool Frame::create(x265_param *param, float* quantOffsets)
diff --git a/source/common/frame.h b/source/common/frame.h
index d7bbc42b8..1ef0547bd 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -159,6 +159,8 @@ public:
int m_isInsideWindow;
+ /*Frame's temporal layer info*/
+ uint8_t m_tempLayer;
Frame();
bool create(x265_param *param, float* quantOffsets);
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 03c3beb70..58bc65494 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1152,7 +1152,7 @@ int x265_param_parse(x265_param* p, const char* name,
const char* value)
p->scenecutThreshold = atoi(value);
}
}
- OPT("temporal-layers") p->bEnableTemporalSubLayers = atobool(value);
+ OPT("temporal-layers") p->bEnableTemporalSubLayers = atoi(value);
OPT("keyint") p->keyframeMax = atoi(value);
OPT("min-keyint") p->keyframeMin = atoi(value);
OPT("rc-lookahead") p->lookaheadDepth = atoi(value);
@@ -2270,7 +2270,7 @@ char *x265_param2string(x265_param* p, int padx, int
pady)
BOOL(p->bEmitHRDSEI, "hrd");
BOOL(p->bEmitInfoSEI, "info");
s += sprintf(s, " hash=%d", p->decodedPictureHashSEI);
- BOOL(p->bEnableTemporalSubLayers, "temporal-layers");
+ s += sprintf(s, " temporal-layers=%d", p->bEnableTemporalSubLayers);
BOOL(p->bOpenGOP, "open-gop");
s += sprintf(s, " min-keyint=%d", p->keyframeMin);
s += sprintf(s, " keyint=%d", p->keyframeMax);
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 482ab9b8e..5f1bba67b 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -1297,6 +1297,8 @@ FILE* x265_csvlog_open(const x265_param* param)
if (param->csvLogLevel)
{
fprintf(csvfp, "Encode Order, Type, POC, QP, Bits,
Scenecut, ");
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(csvfp, "Temporal Sub Layer ID, ");
if (param->csvLogLevel >= 2)
fprintf(csvfp, "I/P cost ratio, ");
if (param->rc.rateControlMode == X265_RC_CRF)
@@ -1410,6 +1412,8 @@ void x265_csvlog_frame(const x265_param* param, const
x265_picture* pic)
const x265_frame_stats* frameStats = &pic->frameData;
fprintf(param->csvfpt, "%d, %c-SLICE, %4d, %2.2lf, %10d, %d,",
frameStats->encoderOrder, frameStats->sliceType, frameStats->poc,
frameStats->qp, (int)frameStats->bits, frameStats->bScenecut);
+ if (param->bEnableTemporalSubLayers > 2)
+ fprintf(param->csvfpt, "%d,", frameStats->tLayer);
if (param->csvLogLevel >= 2)
fprintf(param->csvfpt, "%.2f,", frameStats->ipCostRatio);
if (param->rc.rateControlMode == X265_RC_CRF)
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 38e1e56eb..b2a8ab838 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1899,6 +1899,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
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;
@@ -3880,12 +3881,36 @@ void Encoder::configure(x265_param *p)
p->limitReferences = 0;
}
- if (p->bEnableTemporalSubLayers && !p->bframes)
+ if ((p->bEnableTemporalSubLayers > 2) && !p->bframes)
{
x265_log(p, X265_LOG_WARNING, "B frames not enabled, temporal
sublayer disabled\n");
p->bEnableTemporalSubLayers = 0;
}
+ if (!!p->bEnableTemporalSubLayers && p->bEnableTemporalSubLayers < 2)
+ {
+ p->bEnableTemporalSubLayers = 0;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
less than 2; Disabling temporal layers\n");
+ }
+
+ if (p->bEnableTemporalSubLayers > 5)
+ {
+ p->bEnableTemporalSubLayers = 5;
+ x265_log(p, X265_LOG_WARNING, "No support for temporal sublayers
more than 5; Reducing the temporal sublayers to 5\n");
+ }
+
+ // Assign number of B frames for temporal layers
+ if (p->bEnableTemporalSubLayers > 2)
+ p->bframes =
x265_temporal_layer_bframes[p->bEnableTemporalSubLayers - 1];
+
+ if (p->bEnableTemporalSubLayers > 2)
+ {
+ if (!p->bFrameAdaptive)
+ x265_log(p, X265_LOG_WARNING, "Disabling adaptive B-frame
placement to support temporal sub-layers\n");
+
+ p->bFrameAdaptive = 0;
+ }
+
m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
diff --git a/source/x265.h b/source/x265.h
index 6fb87a62a..86d324d10 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -312,6 +312,7 @@ typedef struct x265_frame_stats
double vmafFrameScore;
double bufferFillFinal;
double unclippedBufferFillFinal;
+ uint8_t tLayer;
} x265_frame_stats;
typedef struct x265_ctu_info_t
@@ -616,6 +617,10 @@ typedef enum
#define FORWARD_WINDOW 2 /* Scenecut window after a scenecut */
#define BWD_WINDOW_DELTA 0.4
+#define X265_MAX_GOP_CONFIG 3
+#define X265_MAX_GOP_LENGTH 16
+#define MAX_T_LAYERS 7
+
typedef struct x265_cli_csp
{
int planes;
@@ -749,6 +754,264 @@ typedef struct x265_vmaf_commondata
static const x265_vmaf_commondata vcd[] = { { NULL, (char
*)"/usr/local/share/model/vmaf_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0,
0, NULL, 0, 1, 0 } };
+typedef struct x265_temporal_layer {
+ int poc_offset; /* POC offset */
+ int8_t layer; /* Current layer */
+ int8_t qp_offset; /* QP offset */
+} x265_temporal_layer;
+
+static const int8_t x265_temporal_layer_bframes[MAX_T_LAYERS] = {-1, -1,
3, 7, 15, -1, -1};
+
+static const int8_t x265_gop_ra_length[X265_MAX_GOP_CONFIG] = { 4, 8, 16};
+static const x265_temporal_layer
x265_gop_ra[X265_MAX_GOP_CONFIG][X265_MAX_GOP_LENGTH] = {
+ {
+ {
+ 4,
+ 0,
+ 1,
+ },
+ {
+ 2,
+ 1,
+ 5,
+ },
+ {
+ 1,
+ 2,
+ 3,
+ },
+ {
+ 3,
+ 2,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ }
+ },
+
+ {
+ {
+ 8,
+ 0,
+ 1,
+ },
+ {
+ 4,
+ 1,
+ 5,
+ },
+ {
+ 2,
+ 2,
+ 4,
+ },
+ {
+ 1,
+ 3,
+ 5,
+ },
+ {
+ 3,
+ 3,
+ 2,
+ },
+ {
+ 6,
+ 2,
+ 5,
+ },
+ {
+ 5,
+ 3,
+ 4,
+ },
+ {
+ 7,
+ 3,
+ 5,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ {
+ -1,
+ -1,
+ -1,
+ },
+ },
+ {
+ {
+ 16,
+ 0,
+ 1,
+ },
+ {
+ 8,
+ 1,
+ 6,
+ },
+ {
+ 4,
+ 2,
+ 5,
+ },
+ {
+ 2,
+ 3,
+ 6,
+ },
+ {
+ 1,
+ 4,
+ 4,
+ },
+ {
+ 3,
+ 4,
+ 6,
+ },
+ {
+ 6,
+ 3,
+ 5,
+ },
+ {
+ 5,
+ 4,
+ 6,
+ },
+ {
+ 7,
+ 4,
+ 1,
+ },
+ {
+ 12,
+ 2,
+ 6,
+ },
+ {
+ 10,
+ 3,
+ 5,
+ },
+ {
+ 9,
+ 4,
+ 6,
+ },
+ {
+ 11,
+ 4,
+ 4,
+ },
+ {
+ 14,
+ 3,
+ 6,
+ },
+ {
+ 13,
+ 4,
+ 5,
+ },
+ {
+ 15,
+ 4,
+ 6,
+ }
+ }
+};
typedef enum
{
diff --git a/source/x265cli.cpp b/source/x265cli.cpp
index 53e04fa6b..79e4c2d8e 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -349,8 +349,8 @@ namespace X265_NS {
H0(" --[no-]repeat-headers Emit SPS and PPS headers at
each keyframe. Default %s\n", OPT(param->bRepeatHeaders));
H0(" --[no-]info Emit SEI identifying encoder
and parameters. Default %s\n", OPT(param->bEmitInfoSEI));
H0(" --[no-]hrd Enable HRD parameters
signaling. Default %s\n", OPT(param->bEmitHRDSEI));
- H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
- H0(" --[no-]temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
+ H0(" --[no-]idr-recovery-sei Emit recovery point infor SEI
at each IDR frame \n");
+ H0(" --temporal-layers Enable a temporal sublayer
for unreferenced B frames. Default %s\n",
OPT(param->bEnableTemporalSubLayers));
H0(" --[no-]aud Emit access unit delimiters
at the start of each access unit. Default %s\n",
OPT(param->bEnableAccessUnitDelimiters));
H0(" --[no-]eob Emit end of bitstream nal
unit at the end of the bitstream. Default %s\n",
OPT(param->bEnableEndOfBitstream));
H0(" --[no-]eos Emit end of sequence nal unit
at the end of every coded video sequence. Default %s\n",
OPT(param->bEnableEndOfSequence));
diff --git a/source/x265cli.h b/source/x265cli.h
index f4e748787..d5b816e80 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -304,8 +304,7 @@ static const struct option long_options[] =
{ "dynamic-refine", no_argument, NULL, 0 },
{ "no-dynamic-refine", no_argument, NULL, 0 },
{ "strict-cbr", no_argument, NULL, 0 },
- { "temporal-layers", no_argument, NULL, 0 },
- { "no-temporal-layers", no_argument, NULL, 0 },
+ { "temporal-layers", required_argument, NULL, 0 },
{ "qg-size", required_argument, NULL, 0 },
{ "recon-y4m-exec", required_argument, NULL, 0 },
{ "analyze-src-pics", no_argument, NULL, 0 },
--
2.28.0.windows.1
*Thanks,*
*Kirithika*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20221226/9a66cb4a/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-2.diff
Type: application/octet-stream
Size: 14776 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20221226/9a66cb4a/attachment-0001.obj>
More information about the x265-devel
mailing list