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