[x265] [PATCH MV-HEVC 03/10] Add support for MV-HEVC in HLS

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Tue Aug 6 10:42:49 UTC 2024


>From 6a325e53a2243244486250088f22de1517158a58 Mon Sep 17 00:00:00 2001
From: AnusuyaKumarasamy <anusuya.kumarasamy at multicorewareinc.com>
Date: Thu, 11 Jul 2024 16:22:15 +0530
Subject: [PATCH] Add support for MV-HEVC in HLS

---
 source/common/slice.h      |  26 ++-
 source/encoder/encoder.cpp |  77 ++++++-
 source/encoder/entropy.cpp | 426 +++++++++++++++++++++++++++----------
 source/encoder/level.cpp   |   5 +
 source/x265.h              |   3 +
 5 files changed, 417 insertions(+), 120 deletions(-)

diff --git a/source/common/slice.h b/source/common/slice.h
index 2a78c9338..9a05840a0 100644
--- a/source/common/slice.h
+++ b/source/common/slice.h
@@ -74,6 +74,7 @@ namespace Profile {
         MAINSTILLPICTURE = 3,
         MAINREXT = 4,
         HIGHTHROUGHPUTREXT = 5,
+        MULTIVIEWMAIN = 6,
         SCALABLEMAIN = 7,
         SCALABLEMAIN10 = 8
     };
@@ -108,7 +109,11 @@ namespace Level {

 struct ProfileTierLevel
 {
+#if ENABLE_MULTIVIEW
+    int      profileIdc[MAX_VIEWS];
+#else
     int      profileIdc[MAX_SCALABLE_LAYERS];
+#endif
     int      levelIdc;
     uint32_t minCrForLevel;
     uint32_t maxLumaSrForLevel;
@@ -162,8 +167,9 @@ struct VPS
     uint32_t         maxDecPicBuffering[MAX_T_LAYERS];
     uint32_t         maxLatencyIncrease[MAX_T_LAYERS];
     int              m_numLayers;
+    int              m_numViews;

-#if ENABLE_ALPHA
+#if (ENABLE_ALPHA || ENABLE_MULTIVIEW)
     bool             splitting_flag;
     int              m_scalabilityMask[MAX_VPS_NUM_SCALABILITY_TYPES];
     int              scalabilityTypes;
@@ -176,6 +182,11 @@ struct VPS
     int              m_vpsNumLayerSetsMinus1;
     bool             vps_extension_flag;
 #endif
+
+#if ENABLE_MULTIVIEW
+    int              m_viewId[MAX_VIEWS];
+    int              m_layerIdIncludedFlag;
+#endif
 };

 struct Window
@@ -270,6 +281,13 @@ struct SPS
     Window   conformanceWindow;
     VUI      vuiParameters;

+#if ENABLE_MULTIVIEW
+    bool     sps_extension_flag;
+    int      setSpsExtOrMaxSubLayersMinus1;
+    int      maxViews;
+    bool     vui_parameters_present_flag;
+#endif
+
     SPS()
     {
         memset(this, 0, sizeof(*this));
@@ -307,6 +325,12 @@ struct PPS

     int      numRefIdxDefault[2];
     bool     pps_slice_chroma_qp_offsets_present_flag;
+
+#if ENABLE_MULTIVIEW
+    bool     pps_extension_flag;
+    int      maxViews;
+#endif
+
 };

 struct WeightParam
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 55248ff2a..a79ad6dab 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -3300,7 +3300,11 @@ void Encoder::getStreamHeaders(NALList& list,
Entropy& sbacCoder, Bitstream& bs)
     bs.writeByteAlignment();
     list.serialize(NAL_UNIT_VPS, bs);

+#if ENABLE_MULTIVIEW
+    for (int layer = 0; layer < m_param->numViews; layer++)
+#else
     for (int layer = 0; layer < m_param->numScalableLayers; layer++)
+#endif
     {
         bs.resetBits();
         sbacCoder.codeSPS(m_sps, m_scalingList, m_vps.ptl, layer);
@@ -3308,7 +3312,11 @@ void Encoder::getStreamHeaders(NALList& list,
Entropy& sbacCoder, Bitstream& bs)
         list.serialize(NAL_UNIT_SPS, bs, layer);
     }

+#if ENABLE_MULTIVIEW
+    for (int layer = 0; layer < m_param->numViews; layer++)
+#else
     for (int layer = 0; layer < m_param->numScalableLayers; layer++)
+#endif
     {
         bs.resetBits();
         sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1),
m_iPPSQpMinus26, layer);
@@ -3405,10 +3413,10 @@ void Encoder::initVPS(VPS *vps)
     vps->ptl.nonPackedConstraintFlag = false;
     vps->ptl.frameOnlyConstraintFlag = !m_param->interlaceMode;
     vps->m_numLayers = m_param->numScalableLayers;
-
-#if ENABLE_ALPHA
+    vps->m_numViews = m_param->numViews;
     vps->vps_extension_flag = false;

+#if ENABLE_ALPHA
     if (m_param->numScalableLayers > 1)
     {
         vps->vps_extension_flag = true;
@@ -3452,6 +3460,53 @@ void Encoder::initVPS(VPS *vps)
         vps->m_vpsNumLayerSetsMinus1 = 1;
     }
 #endif
+
+#if ENABLE_MULTIVIEW
+    if (m_param->numViews > 1)
+    {
+        vps->vps_extension_flag = true;
+        uint8_t dimIdLen = 0, auxDimIdLen = 0, maxAuxId = 1, auxId[2] = {
0,1 };
+        vps->splitting_flag = false;
+        memset(vps->m_scalabilityMask, 0, sizeof(vps->m_scalabilityMask));
+        memset(vps->m_layerIdInNuh, 0, sizeof(vps->m_layerIdInNuh));
+        memset(vps->m_layerIdInVps, 0, sizeof(vps->m_layerIdInVps));
+        memset(vps->m_dimensionIdLen, 0, sizeof(vps->m_dimensionIdLen));
+        vps->scalabilityTypes = 0;
+
+        vps->m_scalabilityMask[MULTIVIEW_SCALABILITY_IDX] = 1;
+        for (int i = 0; i < MAX_VPS_NUM_SCALABILITY_TYPES; i++)
+        {
+            vps->scalabilityTypes += vps->m_scalabilityMask[i];
+        }
+        while ((1 << dimIdLen) <= m_param->numViews)
+        {
+            dimIdLen++;
+        }
+        vps->m_dimensionIdLen[0] = dimIdLen;
+
+        for (uint8_t i = 1; i < m_param->numViews; i++)
+        {
+            vps->m_layerIdInNuh[i] = i;
+            vps->m_dimensionId[i][0] = i;
+            vps->m_layerIdInVps[vps->m_layerIdInNuh[i]] = i;
+            vps->m_dimensionId[i][1] = auxId[i];
+        }
+
+        while ((1 << auxDimIdLen) < (maxAuxId + 1))
+        {
+            auxDimIdLen++;
+        }
+        vps->m_dimensionIdLen[1] = auxDimIdLen;
+
+        vps->m_nuhLayerIdPresentFlag = 0;
+        vps->m_viewIdLen = 1;
+
+        vps->m_viewId[0] = 1;
+        vps->m_viewId[1] = 0;
+
+        vps->m_vpsNumLayerSetsMinus1 = 1;
+    }
+#endif
 }

 void Encoder::initSPS(SPS *sps)
@@ -3535,6 +3590,16 @@ void Encoder::initSPS(SPS *sps)

     vui.timingInfo.numUnitsInTick = m_param->fpsDenom;
     vui.timingInfo.timeScale = m_param->fpsNum;
+
+#if ENABLE_MULTIVIEW
+    if (m_param->numViews > 1)
+    {
+        sps->sps_extension_flag = true;
+        sps->setSpsExtOrMaxSubLayersMinus1 = 7;
+        sps->maxViews = m_param->numViews;
+    }
+#endif
+
 }

 void Encoder::initPPS(PPS *pps)
@@ -3579,6 +3644,14 @@ void Encoder::initPPS(PPS *pps)

     pps->numRefIdxDefault[0] = 1;
     pps->numRefIdxDefault[1] = 1;
+
+#if ENABLE_MULTIVIEW
+    if (m_param->numViews > 1)
+    {
+        pps->pps_extension_flag = true;
+        pps->maxViews = m_param->numViews;
+    }
+#endif
 }

 void Encoder::configureZone(x265_param *p, x265_param *zone)
diff --git a/source/encoder/entropy.cpp b/source/encoder/entropy.cpp
index 8a99ba4e5..1fe3d5895 100644
--- a/source/encoder/entropy.cpp
+++ b/source/encoder/entropy.cpp
@@ -232,9 +232,10 @@ Entropy::Entropy()

 void Entropy::codeVPS(const VPS& vps, const SPS& sps)
 {
+    int maxLayers = (vps.m_numLayers > 1 || vps.m_numViews > 1) + 1;
     WRITE_CODE(0,       4, "vps_video_parameter_set_id");
     WRITE_CODE(3,       2, "vps_reserved_three_2bits");
-    WRITE_CODE(vps.m_numLayers - 1, 6, "vps_reserved_zero_6bits");
+    WRITE_CODE(maxLayers - 1, 6, "vps_reserved_zero_6bits");
     WRITE_CODE(vps.maxTempSubLayers - 1, 3, "vps_max_sub_layers_minus1");
     WRITE_FLAG(vps.maxTempSubLayers == 1,
"vps_temporal_id_nesting_flag");
     WRITE_CODE(0xffff, 16, "vps_reserved_ffff_16bits");
@@ -250,17 +251,31 @@ void Entropy::codeVPS(const VPS& vps, const SPS& sps)
         WRITE_UVLC(vps.maxLatencyIncrease[i] + 1,
"vps_max_latency_increase_plus1[i]");
     }

-#if ENABLE_ALPHA
-    if (vps.m_numLayers > 1)
+#if ENABLE_ALPHA || ENABLE_MULTIVIEW
+    if (vps.m_numLayers > 1 || vps.m_numViews > 1)
     {
-        WRITE_CODE(vps.m_numLayers - 1, 6,
"vps_max_nuh_reserved_zero_layer_id");
+        WRITE_CODE(maxLayers - 1, 6, "vps_max_nuh_reserved_zero_layer_id");
         WRITE_UVLC(vps.m_vpsNumLayerSetsMinus1, "vps_max_op_sets_minus1");
         for (int i = 1; i <= vps.m_vpsNumLayerSetsMinus1; i++)
         {
-            for (int j = 0; j < vps.m_numLayers; j++)
+#if ENABLE_MULTIVIEW
+            if (vps.m_numViews > 1)
             {
-                WRITE_FLAG(1, "layer_id_included_flag[opsIdx][i]");
+                for (int j = 0; j < vps.m_numViews; j++)
+                {
+                    WRITE_FLAG(1, "layer_id_included_flag[opsIdx][i]");
+                }
+            }
+#endif
+#if ENABLE_ALPHA
+            if (vps.m_numLayers > 1)
+            {
+                for (int j = 0; j < vps.m_numLayers; j++)
+                {
+                    WRITE_FLAG(1, "layer_id_included_flag[opsIdx][i]");
+                }
             }
+#endif
         }
     }
     else
@@ -275,106 +290,195 @@ void Entropy::codeVPS(const VPS& vps, const SPS&
sps)

     WRITE_FLAG(0,    "vps_timing_info_present_flag"); /* we signal timing
info in SPS-VUI */

-#if ENABLE_ALPHA
-    WRITE_FLAG(vps.vps_extension_flag, "vps_extension_flag");
-
-    if (vps.vps_extension_flag)
+#if ENABLE_ALPHA || ENABLE_MULTIVIEW
+    if (vps.m_numLayers > 1 || vps.m_numViews > 1)
     {
-        while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
+        if (vps.vps_extension_flag)
         {
-            WRITE_FLAG(1, "vps_extension_alignment_bit_equal_to_one");
-        }
+            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
+            {
+                WRITE_FLAG(1, "vps_extension_alignment_bit_equal_to_one");
+            }

-        WRITE_CODE(vps.ptl.levelIdc, 8, "general_level_idc");
+            WRITE_CODE(vps.ptl.levelIdc, 8, "general_level_idc");

-        WRITE_FLAG(vps.splitting_flag, "splitting flag");
-        for (int i = 0; i < MAX_VPS_NUM_SCALABILITY_TYPES; i++)
-        {
-            WRITE_FLAG(vps.m_scalabilityMask[i], "scalability_mask[i]");
-        }
-        for (int i = 0; i < vps.scalabilityTypes - vps.splitting_flag; i++)
-        {
-            WRITE_CODE(vps.m_dimensionIdLen[i] - 1, 3,
"dimension_id_len_minus1[i]");
-        }
-        WRITE_FLAG(vps.m_nuhLayerIdPresentFlag,
"vps_nuh_layer_id_present_flag");
-        for (int i = 1; i < vps.m_numLayers; i++)
-        {
-            if (vps.m_nuhLayerIdPresentFlag)
-                WRITE_CODE(vps.m_layerIdInNuh[i], 6, "layer_id_in_nuh[i]");
-
-            if (!vps.splitting_flag)
+            WRITE_FLAG(vps.splitting_flag, "splitting flag");
+            for (int i = 0; i < MAX_VPS_NUM_SCALABILITY_TYPES; i++)
+            {
+                WRITE_FLAG(vps.m_scalabilityMask[i],
"scalability_mask[i]");
+            }
+            for (int i = 0; i < vps.scalabilityTypes - vps.splitting_flag;
i++)
+            {
+                WRITE_CODE(vps.m_dimensionIdLen[i] - 1, 3,
"dimension_id_len_minus1[i]");
+            }
+            WRITE_FLAG(vps.m_nuhLayerIdPresentFlag,
"vps_nuh_layer_id_present_flag");
+            for (int i = 1; i < maxLayers; i++)
             {
-                for (int j = 0; j < vps.scalabilityTypes; j++)
+                if (vps.m_nuhLayerIdPresentFlag)
+                    WRITE_CODE(vps.m_layerIdInNuh[i], 6,
"layer_id_in_nuh[i]");
+
+                if (!vps.splitting_flag)
                 {
-                    uint8_t bits = vps.m_dimensionIdLen[j];
-                    WRITE_CODE(vps.m_dimensionId[i][j], bits,
"dimension_id[i][j]");
+                    for (int j = 0; j < vps.scalabilityTypes; j++)
+                    {
+                        uint8_t bits = vps.m_dimensionIdLen[j];
+                        WRITE_CODE(vps.m_dimensionId[i][j], bits,
"dimension_id[i][j]");
+                    }
                 }
             }
-        }
-        WRITE_CODE(vps.m_viewIdLen, 4, "view_id_len");
+            WRITE_CODE(vps.m_viewIdLen, 4, "view_id_len");

-        WRITE_FLAG(0, "direct_dependency_flag[1][0]");
-        WRITE_UVLC(0, "num_add_layer_sets");
-        WRITE_FLAG(0, "vps_sub_layers_max_minus1_present_flag");
-        WRITE_FLAG(0, "max_tid_ref_present_flag");
-        WRITE_FLAG(0, "default_ref_layers_active_flag");
-        WRITE_UVLC(2, "vps_num_profile_tier_level_minus1");
-        WRITE_FLAG(1, "vps_profile_present_flag");
-        codeProfileTier(vps.ptl, vps.maxTempSubLayers, 1);
+#if ENABLE_ALPHA
+            if (vps.m_numLayers > 1)
+            {
+                WRITE_FLAG(0, "direct_dependency_flag[1][0]");
+                WRITE_UVLC(0, "num_add_layer_sets");
+                WRITE_FLAG(0, "vps_sub_layers_max_minus1_present_flag");
+                WRITE_FLAG(0, "max_tid_ref_present_flag");
+                WRITE_FLAG(0, "default_ref_layers_active_flag");
+                WRITE_UVLC(2, "vps_num_profile_tier_level_minus1");
+                WRITE_FLAG(1, "vps_profile_present_flag");
+                codeProfileTier(vps.ptl, vps.maxTempSubLayers, 1);

-        WRITE_UVLC(0, "num_add_olss");
-        WRITE_CODE(0, 2, "default_output_layer_idc");
-        WRITE_CODE(1, 2, "profile_tier_level_idx[ i ][ j ]");
-        WRITE_CODE(2, 2, "profile_tier_level_idx[ i ][ j ]");
+                WRITE_UVLC(0, "num_add_olss");
+                WRITE_CODE(0, 2, "default_output_layer_idc");
+                WRITE_CODE(1, 2, "profile_tier_level_idx[ i ][ j ]");
+                WRITE_CODE(2, 2, "profile_tier_level_idx[ i ][ j ]");

-        WRITE_UVLC(0, "vps_num_rep_formats_minus1");
+                WRITE_UVLC(0, "vps_num_rep_formats_minus1");

-        WRITE_CODE(sps.picWidthInLumaSamples, 16,
"pic_width_vps_in_luma_samples");
-        WRITE_CODE(sps.picHeightInLumaSamples, 16,
"pic_height_vps_in_luma_samples");
-        WRITE_FLAG(1, "chroma_and_bit_depth_vps_present_flag");
+                WRITE_CODE(sps.picWidthInLumaSamples, 16,
"pic_width_vps_in_luma_samples");
+                WRITE_CODE(sps.picHeightInLumaSamples, 16,
"pic_height_vps_in_luma_samples");
+                WRITE_FLAG(1, "chroma_and_bit_depth_vps_present_flag");

-        WRITE_CODE(sps.chromaFormatIdc, 2, "chroma_format_vps_idc");
+                WRITE_CODE(sps.chromaFormatIdc, 2,
"chroma_format_vps_idc");

-        if (sps.chromaFormatIdc == X265_CSP_I444)
-            WRITE_FLAG(0, "separate_colour_plane_vps_flag");
+                if (sps.chromaFormatIdc == X265_CSP_I444)
+                    WRITE_FLAG(0, "separate_colour_plane_vps_flag");

-        WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_luma_minus8");
-        WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_chroma_minus8");
+                WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_luma_minus8");
+                WRITE_CODE(X265_DEPTH - 8, 4,
"bit_depth_vps_chroma_minus8");

-        const Window& conf = sps.conformanceWindow;
-        WRITE_FLAG(conf.bEnabled, "conformance_window_vps_flag");
-        if (conf.bEnabled)
-        {
-            int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift =
CHROMA_V_SHIFT(sps.chromaFormatIdc);
-            WRITE_UVLC(conf.leftOffset >> hShift,
"conf_win_vps_left_offset");
-            WRITE_UVLC(conf.rightOffset >> hShift,
"conf_win_vps_right_offset");
-            WRITE_UVLC(conf.topOffset >> vShift,
"conf_win_vps_top_offset");
-            WRITE_UVLC(conf.bottomOffset >> vShift,
"conf_win_vps_bottom_offset");
-        }
+                const Window& conf = sps.conformanceWindow;
+                WRITE_FLAG(conf.bEnabled, "conformance_window_vps_flag");
+                if (conf.bEnabled)
+                {
+                    int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc),
vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);
+                    WRITE_UVLC(conf.leftOffset >> hShift,
"conf_win_vps_left_offset");
+                    WRITE_UVLC(conf.rightOffset >> hShift,
"conf_win_vps_right_offset");
+                    WRITE_UVLC(conf.topOffset >> vShift,
"conf_win_vps_top_offset");
+                    WRITE_UVLC(conf.bottomOffset >> vShift,
"conf_win_vps_bottom_offset");
+                }

-        WRITE_FLAG(1, "max_one_active_ref_layer_flag");
-        WRITE_FLAG(0, "vps_poc_lsb_aligned_flag");
-        WRITE_FLAG(1, "poc_lsb_not_present_flag[");
-        WRITE_FLAG(0, "sub_layer_flag_info_present_flag");
+                WRITE_FLAG(1, "max_one_active_ref_layer_flag");
+                WRITE_FLAG(0, "vps_poc_lsb_aligned_flag");
+                WRITE_FLAG(1, "poc_lsb_not_present_flag[");
+                WRITE_FLAG(0, "sub_layer_flag_info_present_flag");

-        for (int i = 1; i <= 1; i++)
-        {
-            for (int j = 0; j < vps.m_numLayers; j++)
-            {
-                WRITE_UVLC(vps.maxDecPicBuffering[0] - 1,
"vps_max_dec_pic_buffering_minus1[i]");
-            }
+                for (int i = 1; i <= 1; i++)
+                {
+                    for (int j = 0; j < vps.m_numLayers; j++)
+                    {
+                        WRITE_UVLC(vps.maxDecPicBuffering[0] - 1,
"vps_max_dec_pic_buffering_minus1[i]");
+                    }
+                }
+
+                WRITE_UVLC(vps.numReorderPics[0],
"vps_num_reorder_pics[i]");
+                WRITE_UVLC(vps.maxLatencyIncrease[0] + 1,
"vps_max_latency_increase_plus1[i]");
+
+                WRITE_UVLC(0, "direct_dep_type_len_minus2");
+
+                WRITE_FLAG(0, "default_direct_dependency_flag");
+                WRITE_UVLC(0, "vps_non_vui_extension_length");
+                WRITE_FLAG(0, "vps_vui_present_flag");
+                WRITE_FLAG(0, "vps_extension2_flag");
         }
+#endif

-        WRITE_UVLC(vps.numReorderPics[0], "vps_num_reorder_pics[i]");
-        WRITE_UVLC(vps.maxLatencyIncrease[0] + 1,
"vps_max_latency_increase_plus1[i]");
+#if ENABLE_MULTIVIEW
+            if (vps.m_numViews > 1)
+            {
+                for (uint8_t i = 0; i < vps.m_numViews; i++)
+                    WRITE_CODE(vps.m_viewId[i], vps.m_viewIdLen,
"view_id_val[i]");
+
+                for (int i = 1; i < vps.m_numViews; i++)
+                {
+                    for (int j = 0; j < i; j++)
+                    {
+                        if (j == 0)
+                            WRITE_FLAG(1, "direct_dependency_flag[1][0]");
+                        else
+                            WRITE_FLAG(0, "direct_dependency_flag[1][0]");
+                    }
+                }
+                WRITE_FLAG(0, "vps_sub_layers_max_minus1_present_flag");
+                WRITE_FLAG(0, "max_tid_ref_present_flag");
+                WRITE_FLAG(1, "default_ref_layers_active_flag");
+                WRITE_UVLC(2, "vps_num_profile_tier_level_minus1");
+                WRITE_FLAG(1, "vps_profile_present_flag[i]");
+                codeProfileTier(vps.ptl, vps.maxTempSubLayers, 1);
+                WRITE_UVLC(0, "num_add_olss");
+                WRITE_CODE(0, 2, "default_output_layer_idc");
+
+                for (int i = 1; i <= vps.m_vpsNumLayerSetsMinus1; i++)
+                {
+                    for (int j = 0; j < vps.m_numViews; j++)
+                    {
+                        WRITE_CODE((j == 0) ? 1 : 2, 2,
"profile_tier_level_idx[ i ][ j ]");
+                    }
+                }
+                WRITE_UVLC(0, "vps_num_rep_formats_minus1");
+
+                WRITE_CODE(sps.picWidthInLumaSamples, 16,
"pic_width_vps_in_luma_samples");
+                WRITE_CODE(sps.picHeightInLumaSamples, 16,
"pic_height_vps_in_luma_samples");
+                WRITE_FLAG(1, "chroma_and_bit_depth_vps_present_flag");
+
+                WRITE_CODE(sps.chromaFormatIdc, 2,
"chroma_format_vps_idc");

-        WRITE_UVLC(0, "direct_dep_type_len_minus2");
+                if (sps.chromaFormatIdc == X265_CSP_I444)
+                    WRITE_FLAG(0, "separate_colour_plane_vps_flag");
+
+                WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_luma_minus8");
+                WRITE_CODE(X265_DEPTH - 8, 4,
"bit_depth_vps_chroma_minus8");
+
+                const Window& conf = sps.conformanceWindow;
+                WRITE_FLAG(conf.bEnabled, "conformance_window_vps_flag");
+                if (conf.bEnabled)
+                {
+                    int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc),
vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);
+                    WRITE_UVLC(conf.leftOffset >> hShift,
"conf_win_vps_left_offset");
+                    WRITE_UVLC(conf.rightOffset >> hShift,
"conf_win_vps_right_offset");
+                    WRITE_UVLC(conf.topOffset >> vShift,
"conf_win_vps_top_offset");
+                    WRITE_UVLC(conf.bottomOffset >> vShift,
"conf_win_vps_bottom_offset");
+                }

-        WRITE_FLAG(0, "default_direct_dependency_flag");
-        WRITE_UVLC(0, "vps_non_vui_extension_length");
-        WRITE_FLAG(0, "vps_vui_present_flag");
-        WRITE_FLAG(0, "vps_extension2_flag");
+                WRITE_FLAG(1, "max_one_active_ref_layer_flag");
+                WRITE_FLAG(0, "vps_poc_lsb_aligned_flag");
+                WRITE_FLAG(0, "sub_layer_flag_info_present_flag");
+
+                for (int i = 1; i <= vps.m_vpsNumLayerSetsMinus1; i++)
+                {
+                    for (int j = 0; j < vps.m_numViews; j++)
+                    {
+                        WRITE_UVLC(vps.maxDecPicBuffering[0] - 1,
"vps_max_dec_pic_buffering_minus1[i]");
+                    }
+                }
+                WRITE_UVLC(vps.numReorderPics[0],
"vps_num_reorder_pics[i]");
+                WRITE_UVLC(vps.maxLatencyIncrease[0] + 1,
"vps_max_latency_increase_plus1[i]");
+
+                WRITE_UVLC(0, "direct_dep_type_len_minus2");
+
+                WRITE_FLAG(1, "default_direct_dependency_flag");
+                WRITE_CODE(2, 2, "default_direct_dependency_type");
+                WRITE_UVLC(0, "vps_non_vui_extension_length");
+                WRITE_FLAG(0, "vps_vui_present_flag");
+                WRITE_FLAG(0, "vps_extension2_flag");
+            }
+#endif
+        }
     }
+    else
+        WRITE_FLAG(0, "vps_extension_flag");
 #else
     WRITE_FLAG(0, "vps_extension_flag");
 #endif
@@ -383,41 +487,58 @@ void Entropy::codeVPS(const VPS& vps, const SPS& sps)
 void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList,
const ProfileTierLevel& ptl, int layer)
 {
     WRITE_CODE(0, 4, "sps_video_parameter_set_id");
-    WRITE_CODE(sps.maxTempSubLayers - 1, 3, "sps_max_sub_layers_minus1");
-    WRITE_FLAG(sps.maxTempSubLayers == 1,
"sps_temporal_id_nesting_flag");
-
-    codeProfileTier(ptl, sps.maxTempSubLayers);
+    WRITE_CODE(!layer ? sps.maxTempSubLayers - 1 :
sps.setSpsExtOrMaxSubLayersMinus1, 3, "sps_ext_or_max_sub_layers_minus1");
+#if ENABLE_MULTIVIEW
+    if (!(layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7))
+#endif
+    {
+        WRITE_FLAG(sps.maxTempSubLayers == 1,
"sps_temporal_id_nesting_flag");
+        codeProfileTier(ptl, sps.maxTempSubLayers, layer);
+    }

     WRITE_UVLC(layer, "sps_seq_parameter_set_id");
-    WRITE_UVLC(sps.chromaFormatIdc, "chroma_format_idc");
+#if ENABLE_MULTIVIEW
+    if (layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7)
+        WRITE_FLAG(0, "update_rep_format_flag");
+    else
+#endif
+    {
+        WRITE_UVLC(sps.chromaFormatIdc, "chroma_format_idc");

-    if (sps.chromaFormatIdc == X265_CSP_I444)
-        WRITE_FLAG(0,                       "separate_colour_plane_flag");
+        if (sps.chromaFormatIdc == X265_CSP_I444)
+            WRITE_FLAG(0,
"separate_colour_plane_flag");

-    WRITE_UVLC(sps.picWidthInLumaSamples,   "pic_width_in_luma_samples");
-    WRITE_UVLC(sps.picHeightInLumaSamples,  "pic_height_in_luma_samples");
+        WRITE_UVLC(sps.picWidthInLumaSamples,
"pic_width_in_luma_samples");
+        WRITE_UVLC(sps.picHeightInLumaSamples,
 "pic_height_in_luma_samples");

-    const Window& conf = sps.conformanceWindow;
-    WRITE_FLAG(conf.bEnabled, "conformance_window_flag");
-    if (conf.bEnabled)
-    {
-        int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift =
CHROMA_V_SHIFT(sps.chromaFormatIdc);
-        WRITE_UVLC(conf.leftOffset   >> hShift, "conf_win_left_offset");
-        WRITE_UVLC(conf.rightOffset  >> hShift, "conf_win_right_offset");
-        WRITE_UVLC(conf.topOffset    >> vShift, "conf_win_top_offset");
-        WRITE_UVLC(conf.bottomOffset >> vShift, "conf_win_bottom_offset");
+        const Window& conf = sps.conformanceWindow;
+        WRITE_FLAG(conf.bEnabled, "conformance_window_flag");
+        if (conf.bEnabled)
+        {
+            int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift =
CHROMA_V_SHIFT(sps.chromaFormatIdc);
+            WRITE_UVLC(conf.leftOffset   >> hShift,
"conf_win_left_offset");
+            WRITE_UVLC(conf.rightOffset  >> hShift,
"conf_win_right_offset");
+            WRITE_UVLC(conf.topOffset    >> vShift, "conf_win_top_offset");
+            WRITE_UVLC(conf.bottomOffset >> vShift,
"conf_win_bottom_offset");
+        }
+
+        WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_luma_minus8");
+        WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_chroma_minus8");
     }

-    WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_luma_minus8");
-    WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_chroma_minus8");
     WRITE_UVLC(sps.log2MaxPocLsb - 4, "log2_max_pic_order_cnt_lsb_minus4");
-    WRITE_FLAG(true,
"sps_sub_layer_ordering_info_present_flag");
-
-    for (uint32_t i = 0; i < sps.maxTempSubLayers; i++)
+#if ENABLE_MULTIVIEW
+    if (!(layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7))
+#endif
     {
-        WRITE_UVLC(sps.maxDecPicBuffering[i] - 1,
"sps_max_dec_pic_buffering_minus1[i]");
-        WRITE_UVLC(sps.numReorderPics[i],
"sps_num_reorder_pics[i]");
-        WRITE_UVLC(sps.maxLatencyIncrease[i] + 1,
"sps_max_latency_increase_plus1[i]");
+        WRITE_FLAG(true,
"sps_sub_layer_ordering_info_present_flag");
+
+        for (uint32_t i = 0; i < sps.maxTempSubLayers; i++)
+        {
+            WRITE_UVLC(sps.maxDecPicBuffering[i] - 1,
"sps_max_dec_pic_buffering_minus1[i]");
+            WRITE_UVLC(sps.numReorderPics[i],
"sps_num_reorder_pics[i]");
+            WRITE_UVLC(sps.maxLatencyIncrease[i] + 1,
"sps_max_latency_increase_plus1[i]");
+        }
     }

     WRITE_UVLC(sps.log2MinCodingBlockSize - 3,
 "log2_min_coding_block_size_minus3");
@@ -429,9 +550,20 @@ void Entropy::codeSPS(const SPS& sps, const
ScalingList& scalingList, const Prof
     WRITE_FLAG(scalingList.m_bEnabled,
 "scaling_list_enabled_flag");
     if (scalingList.m_bEnabled)
     {
-        WRITE_FLAG(scalingList.m_bDataPresent,
 "sps_scaling_list_data_present_flag");
-        if (scalingList.m_bDataPresent)
-            codeScalingList(scalingList);
+#if ENABLE_MULTIVIEW
+        if (sps.maxViews > 1)
+        {
+            if ((layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7))
+                WRITE_FLAG(1, "sps_infer_scaling_list_flag");
+            WRITE_CODE(0, 6, "sps_scaling_list_ref_layer_id");
+        }
+        else
+#endif
+        {
+            WRITE_FLAG(scalingList.m_bDataPresent,
"sps_scaling_list_data_present_flag");
+            if (scalingList.m_bDataPresent)
+                codeScalingList(scalingList);
+        }
     }
     WRITE_FLAG(sps.bUseAMP, "amp_enabled_flag");
     WRITE_FLAG(sps.bUseSAO, "sample_adaptive_offset_enabled_flag");
@@ -448,7 +580,22 @@ void Entropy::codeSPS(const SPS& sps, const
ScalingList& scalingList, const Prof
     WRITE_FLAG(1, "vui_parameters_present_flag");
     codeVUI(sps.vuiParameters, sps.maxTempSubLayers,
sps.bEmitVUITimingInfo, sps.bEmitVUIHRDInfo, layer);

-    WRITE_FLAG(0, "sps_extension_flag");
+    WRITE_FLAG(sps.sps_extension_flag, "sps_extension_flag");
+
+#if ENABLE_MULTIVIEW
+    if (sps.sps_extension_flag)
+    {
+        WRITE_FLAG(0, "sps_range_extensions_flag");
+        WRITE_FLAG(sps.maxViews > 1, "sps_multilayer_extension_flag");
+        WRITE_FLAG(0, "sps_3d_extension_flag");
+        WRITE_CODE(0, 5, "sps_extension_5bits");
+
+        if (layer == 0)
+            WRITE_FLAG(0, "inter_view_mv_vert_constraint_flag");
+        else
+            WRITE_FLAG(1, "inter_view_mv_vert_constraint_flag");
+    }
+#endif
 }

 void Entropy::codePPS( const PPS& pps, bool filerAcross, int
iPPSInitQpMinus26, int layer)
@@ -457,7 +604,7 @@ void Entropy::codePPS( const PPS& pps, bool
filerAcross, int iPPSInitQpMinus26,
     WRITE_UVLC(layer,                          "pps_seq_parameter_set_id");
     WRITE_FLAG(0,
 "dependent_slice_segments_enabled_flag");
     WRITE_FLAG(0,                          "output_flag_present_flag");
-    WRITE_CODE(0, 3,                       "num_extra_slice_header_bits");
+    WRITE_CODE(pps.maxViews > 1 ? 2 : 0, 3,"num_extra_slice_header_bits");
     WRITE_FLAG(pps.bSignHideEnabled,       "sign_data_hiding_flag");
     WRITE_FLAG(0,                          "cabac_init_present_flag");
     WRITE_UVLC(pps.numRefIdxDefault[0] - 1,
"num_ref_idx_l0_default_active_minus1");
@@ -498,7 +645,25 @@ void Entropy::codePPS( const PPS& pps, bool
filerAcross, int iPPSInitQpMinus26,
     WRITE_FLAG(0, "lists_modification_present_flag");
     WRITE_UVLC(0, "log2_parallel_merge_level_minus2");
     WRITE_FLAG(0, "slice_segment_header_extension_present_flag");
-    WRITE_FLAG(0, "pps_extension_flag");
+    WRITE_FLAG(pps.pps_extension_flag, "pps_extension_flag");
+
+#if ENABLE_MULTIVIEW
+    if (pps.pps_extension_flag)
+    {
+        WRITE_FLAG(0, "pps_range_extensions_flag");
+        WRITE_FLAG(pps.maxViews > 1, "pps_multilayer_extension_flag");
+        WRITE_FLAG(0, "pps_3d_extension_flag");
+        WRITE_CODE(0, 5, "pps_extension_5bits");
+
+        if (pps.maxViews > 1)
+        {
+            WRITE_FLAG(0, "poc_reset_info_present_flag");
+            WRITE_FLAG(0, "pps_infer_scaling_list_flag");
+            WRITE_UVLC(0, "num_ref_loc_offsets");
+            WRITE_FLAG(0, "colour_mapping_enabled_flag");
+        }
+    }
+#endif
 }

 void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int
maxTempSubLayers, int layer)
@@ -519,7 +684,7 @@ void Entropy::codeProfileTier(const ProfileTierLevel&
ptl, int maxTempSubLayers,
     WRITE_FLAG(ptl.nonPackedConstraintFlag,
"general_non_packed_constraint_flag");
     WRITE_FLAG(ptl.frameOnlyConstraintFlag,
"general_frame_only_constraint_flag");

-    if (ptl.profileIdc[layer] == Profile::MAINREXT ||
ptl.profileIdc[layer] == Profile::HIGHTHROUGHPUTREXT ||
ptl.profileIdc[layer] == Profile::SCALABLEMAIN || ptl.profileIdc[layer] ==
Profile::SCALABLEMAIN10)
+    if (ptl.profileIdc[layer] == Profile::MAINREXT ||
ptl.profileIdc[layer] == Profile::HIGHTHROUGHPUTREXT ||
ptl.profileIdc[layer] == Profile::SCALABLEMAIN || ptl.profileIdc[layer] ==
Profile::SCALABLEMAIN10 || ptl.profileIdc[layer] == Profile::MULTIVIEWMAIN)
     {
         uint32_t bitDepthConstraint = ptl.bitDepthConstraint;
         int csp = ptl.chromaFormatConstraint;
@@ -740,12 +905,39 @@ void Entropy::codeSliceHeader(const Slice& slice,
FrameData& encData, uint32_t s
         WRITE_CODE(slice_addr, slice_addr_bits, "slice_segment_address");
     }

+#if ENABLE_MULTIVIEW
+    if (encData.m_param->numViews > 1)
+    {
+        int esb = 0;
+        if (2 > esb)
+        {
+            esb++;
+            WRITE_FLAG(0, "discardable_flag");
+        }
+        if (2 > esb)
+        {
+            esb++;
+            WRITE_FLAG(0, "cross_layer_bla_flag");
+        }
+    }
+#endif
+
     WRITE_UVLC(slice.m_sliceType, "slice_type");

-    if (!slice.getIdrPicFlag())
+    if (layer > 0 || !slice.getIdrPicFlag())
     {
         int picOrderCntLSB = (slice.m_poc - slice.m_lastIDR + (1 <<
slice.m_sps->log2MaxPocLsb)) % (1 << slice.m_sps->log2MaxPocLsb);
         WRITE_CODE(picOrderCntLSB, slice.m_sps->log2MaxPocLsb,
"pic_order_cnt_lsb");
+    }
+    if (!slice.getIdrPicFlag())
+    {
+#if ENABLE_MULTIVIEW
+        if (!(slice.m_param->numViews > 1))
+#endif
+        {
+            int picOrderCntLSB = (slice.m_poc - slice.m_lastIDR + (1 <<
slice.m_sps->log2MaxPocLsb)) % (1 << slice.m_sps->log2MaxPocLsb);
+            WRITE_CODE(picOrderCntLSB, slice.m_sps->log2MaxPocLsb,
"pic_order_cnt_lsb");
+        }

 #if _DEBUG || CHECKED_BUILD
         // check for bitstream restriction stating that:
diff --git a/source/encoder/level.cpp b/source/encoder/level.cpp
index c62c63426..12803baff 100644
--- a/source/encoder/level.cpp
+++ b/source/encoder/level.cpp
@@ -108,6 +108,11 @@ void determineLevel(const x265_param &param, VPS& vps)
     else
         vps.ptl.profileIdc[0] = Profile::MAINREXT;

+#if ENABLE_MULTIVIEW
+    if (param.numViews == 2)
+        vps.ptl.profileIdc[1] = Profile::MULTIVIEWMAIN;
+#endif
+
     /* determine which profiles are compatible with this stream */

     memset(vps.ptl.profileCompatibilityFlag, 0,
sizeof(vps.ptl.profileCompatibilityFlag));
diff --git a/source/x265.h b/source/x265.h
index baf18e4fc..091696e03 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -628,6 +628,9 @@ typedef enum

 #if ENABLE_MULTIVIEW
 #define MAX_VIEWS 2
+#define MAX_VPS_NUM_SCALABILITY_TYPES     16
+#define MAX_VPS_LAYER_ID_PLUS1            MAX_VIEWS
+#define MULTIVIEW_SCALABILITY_IDX         1
 #else
 #define MAX_VIEWS 1
 #endif
-- 
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/82cd6e11/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-Add-support-for-MV-HEVC-in-HLS.patch
Type: application/x-patch
Size: 32820 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/82cd6e11/attachment-0001.bin>


More information about the x265-devel mailing list