[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