# HG changeset patch
# User Aarthi Thirumalai
# Date 1422960681 -19800
#      Tue Feb 03 16:21:21 2015 +0530
# Node ID 830d29c97117c609585b7c18cc75f120a89ce79e
# Parent  4583eda4cf55e9a7f5c11d1ea660367f3822af53
encoder: Add support for Temporal Layering of the encoded bitstream.

Implements Temporal Sub Layers while encoding, signals NAL units of coded slices
with their temporalId. Output bitstreams can be extracted either at the base 
temporal layer
(layer 0) with roughly half the frame rate or at a higher temporal layer (layer 
1)
that decodes all the frames in the sequence.

diff -r 4583eda4cf55 -r 830d29c97117 source/common/param.cpp
--- a/source/common/param.cpp   Mon Feb 02 17:03:40 2015 +0530
+++ b/source/common/param.cpp   Tue Feb 03 16:21:21 2015 +0530
@@ -181,6 +181,7 @@
     param->bIntraInBFrames = 0;
     param->bLossless = 0;
     param->bCULossless = 0;
+    param->bEnableTemporalSubLayers = 0;
 
     /* Rate control options */
     param->rc.vbvMaxBitrate = 0;
diff -r 4583eda4cf55 -r 830d29c97117 source/common/slice.h
--- a/source/common/slice.h     Mon Feb 02 17:03:40 2015 +0530
+++ b/source/common/slice.h     Tue Feb 03 16:21:21 2015 +0530
@@ -149,6 +149,7 @@
 
 struct VPS
 {
+    uint32_t         maxTempSubLayers;
     uint32_t         numReorderPics;
     uint32_t         maxDecPicBuffering;
     HRDInfo          hrdParameters;
@@ -228,6 +229,7 @@
     bool     bUseAMP; // use param
     uint32_t maxAMPDepth;
 
+    uint32_t maxTempSubLayers; // max number of Temporal Sub layers
     uint32_t maxDecPicBuffering; // these are dups of VPS values
     int      numReorderPics;
     int      maxLatencyIncrease;
diff -r 4583eda4cf55 -r 830d29c97117 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp        Mon Feb 02 17:03:40 2015 +0530
+++ b/source/encoder/encoder.cpp        Tue Feb 03 16:21:21 2015 +0530
@@ -669,6 +669,14 @@
             /* determine references, setup RPS, etc */
             m_dpb->prepareEncode(frameEnc);
 
+            /* If temporal Layers are enabled, set tempLayer and NAL Unit Type.
+             * For now, there are a max of 2 layers, with the non Referenced B 
frames
+             * forming the temporal sublayer and other referenced frames are 
on the base layer */
+            if (!frameEnc->m_encData->m_bHasReferences && 
m_param->bEnableTemporalSubLayers)
+            {
+                frameEnc->m_encData->m_slice->m_nalUnitType = 
NAL_UNIT_CODED_SLICE_TSA_N;
+            }
+
             if (m_param->rc.rateControlMode != X265_RC_CQP)
                 m_lookahead->getEstimatedPictureCost(frameEnc);
 
@@ -1413,6 +1421,7 @@
     sps->bUseAMP = m_param->bEnableAMP;
     sps->maxAMPDepth = m_param->bEnableAMP ? g_maxCUDepth : 0;
 
+    sps->maxTempSubLayers = m_param->bEnableTemporalSubLayers ? 2 : 1;
     sps->maxDecPicBuffering = m_vps.maxDecPicBuffering;
     sps->numReorderPics = m_vps.numReorderPics;
     sps->maxLatencyIncrease = m_param->bframes;
@@ -1622,6 +1631,19 @@
         p->bDistributeMotionEstimation = p->bDistributeModeAnalysis = 0;
     }
 
+    if (p->bEnableTemporalSubLayers)
+    {
+        if (p->bFrameAdaptive)
+            x265_log(p, X265_LOG_WARNING, "Scalable Video Coding needs fixed 
GOP structure, requires --b-adapt 0\n");
+        p->bFrameAdaptive = 0;
+        if (p->scenecutThreshold)
+            x265_log(p, X265_LOG_WARNING, "Scalable Video Coding needs fixed 
GOP structure, requires --no -scenecut\n");
+        p->scenecutThreshold = 0;
+        if (p->bframes != 3)
+            x265_log(p, X265_LOG_WARNING, "Ideally 3 bframes are needed to 
generate a base temporal layer bitstream with half the fps, requires --bframes 
3\n");
+        p->bframes = 3;
+    }
+
     m_bframeDelay = p->bframes ? (p->bBPyramid ? 2 : 1) : 0;
 
     p->bFrameBias = X265_MIN(X265_MAX(-90, p->bFrameBias), 100);
diff -r 4583eda4cf55 -r 830d29c97117 source/encoder/entropy.cpp
--- a/source/encoder/entropy.cpp        Mon Feb 02 17:03:40 2015 +0530
+++ b/source/encoder/entropy.cpp        Tue Feb 03 16:21:21 2015 +0530
@@ -51,17 +51,22 @@
     WRITE_CODE(0,       4, "vps_video_parameter_set_id");
     WRITE_CODE(3,       2, "vps_reserved_three_2bits");
     WRITE_CODE(0,       6, "vps_reserved_zero_6bits");
-    WRITE_CODE(0,       3, "vps_max_sub_layers_minus1");
-    WRITE_FLAG(1,          "vps_temporal_id_nesting_flag");
+    WRITE_CODE(vps.maxTempSubLayers - 1,       3, "vps_max_sub_layers_minus1");
+    // Temporal Id Nesting is disabled only when maxTemporalLayers > 1
+    WRITE_FLAG(!(vps.maxTempSubLayers - 1),       
"vps_temporal_id_nesting_flag");
     WRITE_CODE(0xffff, 16, "vps_reserved_ffff_16bits");
 
-    codeProfileTier(vps.ptl);
+    codeProfileTier(vps.ptl ,vps.maxTempSubLayers - 1);
 
     WRITE_FLAG(true, "vps_sub_layer_ordering_info_present_flag");
-    WRITE_UVLC(vps.maxDecPicBuffering - 1, 
"vps_max_dec_pic_buffering_minus1[i]");
-    WRITE_UVLC(vps.numReorderPics,         "vps_num_reorder_pics[i]");
 
-    WRITE_UVLC(0,    "vps_max_latency_increase_plus1[i]");
+    for (uint32_t i = 0; i <= vps.maxTempSubLayers - 1; i++)
+    {
+        WRITE_UVLC(vps.maxDecPicBuffering - 1, 
"vps_max_dec_pic_buffering_minus1[i]");
+        WRITE_UVLC(vps.numReorderPics,         "vps_num_reorder_pics[i]");
+        WRITE_UVLC(0,    "vps_max_latency_increase_plus1[i]");
+    }
+
     WRITE_CODE(0, 6, "vps_max_nuh_reserved_zero_layer_id");
     WRITE_UVLC(0,    "vps_max_op_sets_minus1");
     WRITE_FLAG(0,    "vps_timing_info_present_flag"); /* we signal timing info 
in SPS-VUI */
@@ -71,10 +76,11 @@
 void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList, const 
ProfileTierLevel& ptl)
 {
     WRITE_CODE(0, 4, "sps_video_parameter_set_id");
-    WRITE_CODE(0, 3, "sps_max_sub_layers_minus1");
-    WRITE_FLAG(1,    "sps_temporal_id_nesting_flag");
+    WRITE_CODE(sps.maxTempSubLayers - 1, 3, "sps_max_sub_layers_minus1");
+    // Temporal Id Nesting is disabled only when maxTemporalLayers > 1
+    WRITE_FLAG(!(sps.maxTempSubLayers - 1), "sps_temporal_id_nesting_flag");
 
-    codeProfileTier(ptl);
+    codeProfileTier(ptl, sps.maxTempSubLayers - 1);
 
     WRITE_UVLC(0, "sps_seq_parameter_set_id");
     WRITE_UVLC(sps.chromaFormatIdc, "chroma_format_idc");
@@ -101,9 +107,12 @@
     WRITE_UVLC(BITS_FOR_POC - 4, "log2_max_pic_order_cnt_lsb_minus4");
     WRITE_FLAG(true,             "sps_sub_layer_ordering_info_present_flag");
 
-    WRITE_UVLC(sps.maxDecPicBuffering - 1, 
"sps_max_dec_pic_buffering_minus1[i]");
-    WRITE_UVLC(sps.numReorderPics,         "sps_num_reorder_pics[i]");
-    WRITE_UVLC(sps.maxLatencyIncrease + 1, 
"sps_max_latency_increase_plus1[i]");
+    for (uint32_t i = 0; i <= sps.maxTempSubLayers - 1; i++)
+    {
+        WRITE_UVLC(sps.maxDecPicBuffering - 1, 
"sps_max_dec_pic_buffering_minus1[i]");
+        WRITE_UVLC(sps.numReorderPics,         "sps_num_reorder_pics[i]");
+        WRITE_UVLC(sps.maxLatencyIncrease + 1, 
"sps_max_latency_increase_plus1[i]");
+    }
 
     WRITE_UVLC(sps.log2MinCodingBlockSize - 3,    
"log2_min_coding_block_size_minus3");
     WRITE_UVLC(sps.log2DiffMaxMinCodingBlockSize, 
"log2_diff_max_min_coding_block_size");
@@ -184,7 +193,7 @@
     WRITE_FLAG(0, "pps_extension_flag");
 }
 
-void Entropy::codeProfileTier(const ProfileTierLevel& ptl)
+void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int 
maxTempSubLayerMinus1)
 {
     WRITE_CODE(0, 2,                "XXX_profile_space[]");
     WRITE_FLAG(ptl.tierFlag,        "XXX_tier_flag[]");
@@ -222,6 +231,14 @@
     }
 
     WRITE_CODE(ptl.levelIdc, 8, "general_level_idc");
+
+    if (maxTempSubLayerMinus1)
+    {
+         WRITE_FLAG(0, "sub_layer_profile_present_flag[i]");
+         WRITE_FLAG(0, "sub_layer_level_present_flag[i]");
+         for (int i = maxTempSubLayerMinus1; i < 8 ; i++)
+             WRITE_CODE(0, 2, "reserved_zero_2bits");
+    }
 }
 
 void Entropy::codeVUI(const VUI& vui)
@@ -331,24 +348,27 @@
 
 void Entropy::codeHrdParameters(const HRDInfo& hrd)
 {
-    WRITE_FLAG(1, "nal_hrd_parameters_present_flag");
-    WRITE_FLAG(0, "vcl_hrd_parameters_present_flag");
-    WRITE_FLAG(0, "sub_pic_hrd_params_present_flag");
+    for(int i = 0; i <= 1; i++)
+    {
+        WRITE_FLAG(1, "nal_hrd_parameters_present_flag");
+        WRITE_FLAG(0, "vcl_hrd_parameters_present_flag");
+        WRITE_FLAG(0, "sub_pic_hrd_params_present_flag");
 
-    WRITE_CODE(hrd.bitRateScale, 4, "bit_rate_scale");
-    WRITE_CODE(hrd.cpbSizeScale, 4, "cpb_size_scale");
+        WRITE_CODE(hrd.bitRateScale, 4, "bit_rate_scale");
+        WRITE_CODE(hrd.cpbSizeScale, 4, "cpb_size_scale");
 
-    WRITE_CODE(hrd.initialCpbRemovalDelayLength - 1, 5, 
"initial_cpb_removal_delay_length_minus1");
-    WRITE_CODE(hrd.cpbRemovalDelayLength - 1,        5, 
"au_cpb_removal_delay_length_minus1");
-    WRITE_CODE(hrd.dpbOutputDelayLength - 1,         5, 
"dpb_output_delay_length_minus1");
+        WRITE_CODE(hrd.initialCpbRemovalDelayLength - 1, 5, 
"initial_cpb_removal_delay_length_minus1");
+        WRITE_CODE(hrd.cpbRemovalDelayLength - 1,        5, 
"au_cpb_removal_delay_length_minus1");
+        WRITE_CODE(hrd.dpbOutputDelayLength - 1,         5, 
"dpb_output_delay_length_minus1");
 
-    WRITE_FLAG(1, "fixed_pic_rate_general_flag");
-    WRITE_UVLC(0, "elemental_duration_in_tc_minus1");
-    WRITE_UVLC(0, "cpb_cnt_minus1");
+        WRITE_FLAG(1, "fixed_pic_rate_general_flag");
+        WRITE_UVLC(0, "elemental_duration_in_tc_minus1");
+        WRITE_UVLC(0, "cpb_cnt_minus1");
 
-    WRITE_UVLC(hrd.bitRateValue - 1, "bit_rate_value_minus1");
-    WRITE_UVLC(hrd.cpbSizeValue - 1, "cpb_size_value_minus1");
-    WRITE_FLAG(hrd.cbrFlag, "cbr_flag");
+        WRITE_UVLC(hrd.bitRateValue - 1, "bit_rate_value_minus1");
+        WRITE_UVLC(hrd.cpbSizeValue - 1, "cpb_size_value_minus1");
+        WRITE_FLAG(hrd.cbrFlag, "cbr_flag");
+    }
 }
 
 void Entropy::codeAUD(const Slice& slice)
diff -r 4583eda4cf55 -r 830d29c97117 source/encoder/entropy.h
--- a/source/encoder/entropy.h  Mon Feb 02 17:03:40 2015 +0530
+++ b/source/encoder/entropy.h  Tue Feb 03 16:21:21 2015 +0530
@@ -230,7 +230,7 @@
     void writeEpExGolomb(uint32_t symbol, uint32_t count);
     void writeCoefRemainExGolomb(uint32_t symbol, const uint32_t absGoRice);
 
-    void codeProfileTier(const ProfileTierLevel& ptl);
+    void codeProfileTier(const ProfileTierLevel& ptl, int 
maxTempSubLayerMinus1);
     void codeScalingList(const ScalingList&);
     void codeScalingList(const ScalingList& scalingList, uint32_t sizeId, 
uint32_t listId);
 
diff -r 4583eda4cf55 -r 830d29c97117 source/encoder/level.cpp
--- a/source/encoder/level.cpp  Mon Feb 02 17:03:40 2015 +0530
+++ b/source/encoder/level.cpp  Tue Feb 03 16:21:21 2015 +0530
@@ -60,6 +60,7 @@
 /* determine minimum decoder level required to decode the described video */
 void determineLevel(const x265_param &param, VPS& vps)
 {
+    vps.maxTempSubLayers = param.bEnableTemporalSubLayers ? 2 : 1;
     if (param.bLossless)
         vps.ptl.profileIdc = Profile::NONE;
     else if (param.internalCsp == X265_CSP_I420)
diff -r 4583eda4cf55 -r 830d29c97117 source/encoder/nal.cpp
--- a/source/encoder/nal.cpp    Mon Feb 02 17:03:40 2015 +0530
+++ b/source/encoder/nal.cpp    Tue Feb 03 16:21:21 2015 +0530
@@ -107,7 +107,7 @@
      * nuh_reserved_zero_6bits  6-bits
      * nuh_temporal_id_plus1    3-bits */
     out[bytes++] = (uint8_t)nalUnitType << 1;
-    out[bytes++] = 1;
+    out[bytes++] = 1 + (nalUnitType == NAL_UNIT_CODED_SLICE_TSA_N);
 
     /* 7.4.1 ...
      * Within the NAL unit, the following three-byte sequences shall not occur 
at
diff -r 4583eda4cf55 -r 830d29c97117 source/x265.h
--- a/source/x265.h     Mon Feb 02 17:03:40 2015 +0530
+++ b/source/x265.h     Tue Feb 03 16:21:21 2015 +0530
@@ -791,6 +791,12 @@
      * CU. */
     int       bCULossless;
 
+    /* Enable Temporal Sub Layers while encoding, signals NAL units of coded 
slices
+     * with their temporalId. Output bitstreams can be extracted either at the 
base temporal layer
+     * (layer 0) with roughly half the frame rate or at a higher temporal 
layer (layer 1)
+     * that decodes all the frames in the sequence. */
+    int       bEnableTemporalSubLayers;
+
     /*== Rate Control ==*/
 
     struct
_______________________________________________
x265-devel mailing list
[email protected]
https://mailman.videolan.org/listinfo/x265-devel

Reply via email to