<div dir="ltr">From 6a325e53a2243244486250088f22de1517158a58 Mon Sep 17 00:00:00 2001<br>From: AnusuyaKumarasamy <<a href="mailto:anusuya.kumarasamy@multicorewareinc.com" target="_blank">anusuya.kumarasamy@multicorewareinc.com</a>><br>Date: Thu, 11 Jul 2024 16:22:15 +0530<br>Subject: [PATCH] Add support for MV-HEVC in HLS<br><br>---<br> source/common/slice.h      |  26 ++-<br> source/encoder/encoder.cpp |  77 ++++++-<br> source/encoder/entropy.cpp | 426 +++++++++++++++++++++++++++----------<br> source/encoder/level.cpp   |   5 +<br> source/x265.h              |   3 +<br> 5 files changed, 417 insertions(+), 120 deletions(-)<br><br>diff --git a/source/common/slice.h b/source/common/slice.h<br>index 2a78c9338..9a05840a0 100644<br>--- a/source/common/slice.h<br>+++ b/source/common/slice.h<br>@@ -74,6 +74,7 @@ namespace Profile {<br>         MAINSTILLPICTURE = 3,<br>         MAINREXT = 4,<br>         HIGHTHROUGHPUTREXT = 5,<br>+        MULTIVIEWMAIN = 6,<br>         SCALABLEMAIN = 7,<br>         SCALABLEMAIN10 = 8<br>     };<br>@@ -108,7 +109,11 @@ namespace Level {<br> <br> struct ProfileTierLevel<br> {<br>+#if ENABLE_MULTIVIEW<br>+    int      profileIdc[MAX_VIEWS];<br>+#else<br>     int      profileIdc[MAX_SCALABLE_LAYERS];<br>+#endif<br>     int      levelIdc;<br>     uint32_t minCrForLevel;<br>     uint32_t maxLumaSrForLevel;<br>@@ -162,8 +167,9 @@ struct VPS<br>     uint32_t         maxDecPicBuffering[MAX_T_LAYERS];<br>     uint32_t         maxLatencyIncrease[MAX_T_LAYERS];<br>     int              m_numLayers;<br>+    int              m_numViews;<br> <br>-#if ENABLE_ALPHA<br>+#if (ENABLE_ALPHA || ENABLE_MULTIVIEW)<br>     bool             splitting_flag;<br>     int              m_scalabilityMask[MAX_VPS_NUM_SCALABILITY_TYPES];<br>     int              scalabilityTypes;<br>@@ -176,6 +182,11 @@ struct VPS<br>     int              m_vpsNumLayerSetsMinus1;<br>     bool             vps_extension_flag;<br> #endif<br>+<br>+#if ENABLE_MULTIVIEW<br>+    int              m_viewId[MAX_VIEWS];<br>+    int              m_layerIdIncludedFlag;<br>+#endif<br> };<br> <br> struct Window<br>@@ -270,6 +281,13 @@ struct SPS<br>     Window   conformanceWindow;<br>     VUI      vuiParameters;<br> <br>+#if ENABLE_MULTIVIEW<br>+    bool     sps_extension_flag;<br>+    int      setSpsExtOrMaxSubLayersMinus1;<br>+    int      maxViews;<br>+    bool     vui_parameters_present_flag;<br>+#endif<br>+<br>     SPS()<br>     {<br>         memset(this, 0, sizeof(*this));<br>@@ -307,6 +325,12 @@ struct PPS<br> <br>     int      numRefIdxDefault[2];<br>     bool     pps_slice_chroma_qp_offsets_present_flag;<br>+<br>+#if ENABLE_MULTIVIEW<br>+    bool     pps_extension_flag;<br>+    int      maxViews;<br>+#endif<br>+<br> };<br> <br> struct WeightParam<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 55248ff2a..a79ad6dab 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -3300,7 +3300,11 @@ void Encoder::getStreamHeaders(NALList& list, Entropy& sbacCoder, Bitstream& bs)<br>     bs.writeByteAlignment();<br>     list.serialize(NAL_UNIT_VPS, bs);<br> <br>+#if ENABLE_MULTIVIEW<br>+    for (int layer = 0; layer < m_param->numViews; layer++)<br>+#else<br>     for (int layer = 0; layer < m_param->numScalableLayers; layer++)<br>+#endif<br>     {<br>         bs.resetBits();<br>         sbacCoder.codeSPS(m_sps, m_scalingList, m_vps.ptl, layer);<br>@@ -3308,7 +3312,11 @@ void Encoder::getStreamHeaders(NALList& list, Entropy& sbacCoder, Bitstream& bs)<br>         list.serialize(NAL_UNIT_SPS, bs, layer);<br>     }<br> <br>+#if ENABLE_MULTIVIEW<br>+    for (int layer = 0; layer < m_param->numViews; layer++)<br>+#else<br>     for (int layer = 0; layer < m_param->numScalableLayers; layer++)<br>+#endif<br>     {<br>         bs.resetBits();<br>         sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1), m_iPPSQpMinus26, layer);<br>@@ -3405,10 +3413,10 @@ void Encoder::initVPS(VPS *vps)<br>     vps->ptl.nonPackedConstraintFlag = false;<br>     vps->ptl.frameOnlyConstraintFlag = !m_param->interlaceMode;<br>     vps->m_numLayers = m_param->numScalableLayers;<br>-<br>-#if ENABLE_ALPHA<br>+    vps->m_numViews = m_param->numViews;<br>     vps->vps_extension_flag = false;<br> <br>+#if ENABLE_ALPHA<br>     if (m_param->numScalableLayers > 1)<br>     {<br>         vps->vps_extension_flag = true;<br>@@ -3452,6 +3460,53 @@ void Encoder::initVPS(VPS *vps)<br>         vps->m_vpsNumLayerSetsMinus1 = 1;<br>     }<br> #endif<br>+<br>+#if ENABLE_MULTIVIEW<br>+    if (m_param->numViews > 1)<br>+    {<br>+        vps->vps_extension_flag = true;<br>+        uint8_t dimIdLen = 0, auxDimIdLen = 0, maxAuxId = 1, auxId[2] = { 0,1 };<br>+        vps->splitting_flag = false;<br>+        memset(vps->m_scalabilityMask, 0, sizeof(vps->m_scalabilityMask));<br>+        memset(vps->m_layerIdInNuh, 0, sizeof(vps->m_layerIdInNuh));<br>+        memset(vps->m_layerIdInVps, 0, sizeof(vps->m_layerIdInVps));<br>+        memset(vps->m_dimensionIdLen, 0, sizeof(vps->m_dimensionIdLen));<br>+        vps->scalabilityTypes = 0;<br>+<br>+        vps->m_scalabilityMask[MULTIVIEW_SCALABILITY_IDX] = 1;<br>+        for (int i = 0; i < MAX_VPS_NUM_SCALABILITY_TYPES; i++)<br>+        {<br>+            vps->scalabilityTypes += vps->m_scalabilityMask[i];<br>+        }<br>+        while ((1 << dimIdLen) <= m_param->numViews)<br>+        {<br>+            dimIdLen++;<br>+        }<br>+        vps->m_dimensionIdLen[0] = dimIdLen;<br>+<br>+        for (uint8_t i = 1; i < m_param->numViews; i++)<br>+        {<br>+            vps->m_layerIdInNuh[i] = i;<br>+            vps->m_dimensionId[i][0] = i;<br>+            vps->m_layerIdInVps[vps->m_layerIdInNuh[i]] = i;<br>+            vps->m_dimensionId[i][1] = auxId[i];<br>+        }<br>+<br>+        while ((1 << auxDimIdLen) < (maxAuxId + 1))<br>+        {<br>+            auxDimIdLen++;<br>+        }<br>+        vps->m_dimensionIdLen[1] = auxDimIdLen;<br>+<br>+        vps->m_nuhLayerIdPresentFlag = 0;<br>+        vps->m_viewIdLen = 1;<br>+<br>+        vps->m_viewId[0] = 1;<br>+        vps->m_viewId[1] = 0;<br>+<br>+        vps->m_vpsNumLayerSetsMinus1 = 1;<br>+    }<br>+#endif<br> }<br> <br> void Encoder::initSPS(SPS *sps)<br>@@ -3535,6 +3590,16 @@ void Encoder::initSPS(SPS *sps)<br> <br>     vui.timingInfo.numUnitsInTick = m_param->fpsDenom;<br>     vui.timingInfo.timeScale = m_param->fpsNum;<br>+<br>+#if ENABLE_MULTIVIEW<br>+    if (m_param->numViews > 1)<br>+    {<br>+        sps->sps_extension_flag = true;<br>+        sps->setSpsExtOrMaxSubLayersMinus1 = 7;<br>+        sps->maxViews = m_param->numViews;<br>+    }<br>+#endif<br>+<br> }<br> <br> void Encoder::initPPS(PPS *pps)<br>@@ -3579,6 +3644,14 @@ void Encoder::initPPS(PPS *pps)<br> <br>     pps->numRefIdxDefault[0] = 1;<br>     pps->numRefIdxDefault[1] = 1;<br>+<br>+#if ENABLE_MULTIVIEW<br>+    if (m_param->numViews > 1)<br>+    {<br>+        pps->pps_extension_flag = true;<br>+        pps->maxViews = m_param->numViews;<br>+    }<br>+#endif<br> }<br> <br> void Encoder::configureZone(x265_param *p, x265_param *zone)<br>diff --git a/source/encoder/entropy.cpp b/source/encoder/entropy.cpp<br>index 8a99ba4e5..1fe3d5895 100644<br>--- a/source/encoder/entropy.cpp<br>+++ b/source/encoder/entropy.cpp<br>@@ -232,9 +232,10 @@ Entropy::Entropy()<br> <br> void Entropy::codeVPS(const VPS& vps, const SPS& sps)<br> {<br>+    int maxLayers = (vps.m_numLayers > 1 || vps.m_numViews > 1) + 1;<br>     WRITE_CODE(0,       4, "vps_video_parameter_set_id");<br>     WRITE_CODE(3,       2, "vps_reserved_three_2bits");<br>-    WRITE_CODE(vps.m_numLayers - 1, 6, "vps_reserved_zero_6bits");<br>+    WRITE_CODE(maxLayers - 1, 6, "vps_reserved_zero_6bits");<br>     WRITE_CODE(vps.maxTempSubLayers - 1, 3, "vps_max_sub_layers_minus1");<br>     WRITE_FLAG(vps.maxTempSubLayers == 1,   "vps_temporal_id_nesting_flag");<br>     WRITE_CODE(0xffff, 16, "vps_reserved_ffff_16bits");<br>@@ -250,17 +251,31 @@ void Entropy::codeVPS(const VPS& vps, const SPS& sps)<br>         WRITE_UVLC(vps.maxLatencyIncrease[i] + 1, "vps_max_latency_increase_plus1[i]");<br>     }<br> <br>-#if ENABLE_ALPHA<br>-    if (vps.m_numLayers > 1)<br>+#if ENABLE_ALPHA || ENABLE_MULTIVIEW<br>+    if (vps.m_numLayers > 1 || vps.m_numViews > 1)<br>     {<br>-        WRITE_CODE(vps.m_numLayers - 1, 6, "vps_max_nuh_reserved_zero_layer_id");<br>+        WRITE_CODE(maxLayers - 1, 6, "vps_max_nuh_reserved_zero_layer_id");<br>         WRITE_UVLC(vps.m_vpsNumLayerSetsMinus1, "vps_max_op_sets_minus1");<br>         for (int i = 1; i <= vps.m_vpsNumLayerSetsMinus1; i++)<br>         {<br>-            for (int j = 0; j < vps.m_numLayers; j++)<br>+#if ENABLE_MULTIVIEW<br>+            if (vps.m_numViews > 1)<br>             {<br>-                WRITE_FLAG(1, "layer_id_included_flag[opsIdx][i]");<br>+                for (int j = 0; j < vps.m_numViews; j++)<br>+                {<br>+                    WRITE_FLAG(1, "layer_id_included_flag[opsIdx][i]");<br>+                }<br>+            }<br>+#endif<br>+#if ENABLE_ALPHA<br>+            if (vps.m_numLayers > 1)<br>+            {<br>+                for (int j = 0; j < vps.m_numLayers; j++)<br>+                {<br>+                    WRITE_FLAG(1, "layer_id_included_flag[opsIdx][i]");<br>+                }<br>             }<br>+#endif<br>         }<br>     }<br>     else<br>@@ -275,106 +290,195 @@ void Entropy::codeVPS(const VPS& vps, const SPS& sps)<br> <br>     WRITE_FLAG(0,    "vps_timing_info_present_flag"); /* we signal timing info in SPS-VUI */<br> <br>-#if ENABLE_ALPHA<br>-    WRITE_FLAG(vps.vps_extension_flag, "vps_extension_flag");<br>-<br>-    if (vps.vps_extension_flag)<br>+#if ENABLE_ALPHA || ENABLE_MULTIVIEW<br>+    if (vps.m_numLayers > 1 || vps.m_numViews > 1)<br>     {<br>-        while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)<br>+        if (vps.vps_extension_flag)<br>         {<br>-            WRITE_FLAG(1, "vps_extension_alignment_bit_equal_to_one");<br>-        }<br>+            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)<br>+            {<br>+                WRITE_FLAG(1, "vps_extension_alignment_bit_equal_to_one");<br>+            }<br> <br>-        WRITE_CODE(vps.ptl.levelIdc, 8, "general_level_idc");<br>+            WRITE_CODE(vps.ptl.levelIdc, 8, "general_level_idc");<br> <br>-        WRITE_FLAG(vps.splitting_flag, "splitting flag");<br>-        for (int i = 0; i < MAX_VPS_NUM_SCALABILITY_TYPES; i++)<br>-        {<br>-            WRITE_FLAG(vps.m_scalabilityMask[i], "scalability_mask[i]");<br>-        }<br>-        for (int i = 0; i < vps.scalabilityTypes - vps.splitting_flag; i++)<br>-        {<br>-            WRITE_CODE(vps.m_dimensionIdLen[i] - 1, 3, "dimension_id_len_minus1[i]");<br>-        }<br>-        WRITE_FLAG(vps.m_nuhLayerIdPresentFlag, "vps_nuh_layer_id_present_flag");<br>-        for (int i = 1; i < vps.m_numLayers; i++)<br>-        {<br>-            if (vps.m_nuhLayerIdPresentFlag)<br>-                WRITE_CODE(vps.m_layerIdInNuh[i], 6, "layer_id_in_nuh[i]");<br>-<br>-            if (!vps.splitting_flag)<br>+            WRITE_FLAG(vps.splitting_flag, "splitting flag");<br>+            for (int i = 0; i < MAX_VPS_NUM_SCALABILITY_TYPES; i++)<br>+            {<br>+                WRITE_FLAG(vps.m_scalabilityMask[i], "scalability_mask[i]");<br>+            }<br>+            for (int i = 0; i < vps.scalabilityTypes - vps.splitting_flag; i++)<br>+            {<br>+                WRITE_CODE(vps.m_dimensionIdLen[i] - 1, 3, "dimension_id_len_minus1[i]");<br>+            }<br>+            WRITE_FLAG(vps.m_nuhLayerIdPresentFlag, "vps_nuh_layer_id_present_flag");<br>+            for (int i = 1; i < maxLayers; i++)<br>             {<br>-                for (int j = 0; j < vps.scalabilityTypes; j++)<br>+                if (vps.m_nuhLayerIdPresentFlag)<br>+                    WRITE_CODE(vps.m_layerIdInNuh[i], 6, "layer_id_in_nuh[i]");<br>+<br>+                if (!vps.splitting_flag)<br>                 {<br>-                    uint8_t bits = vps.m_dimensionIdLen[j];<br>-                    WRITE_CODE(vps.m_dimensionId[i][j], bits, "dimension_id[i][j]");<br>+                    for (int j = 0; j < vps.scalabilityTypes; j++)<br>+                    {<br>+                        uint8_t bits = vps.m_dimensionIdLen[j];<br>+                        WRITE_CODE(vps.m_dimensionId[i][j], bits, "dimension_id[i][j]");<br>+                    }<br>                 }<br>             }<br>-        }<br>-        WRITE_CODE(vps.m_viewIdLen, 4, "view_id_len");<br>+            WRITE_CODE(vps.m_viewIdLen, 4, "view_id_len");<br> <br>-        WRITE_FLAG(0, "direct_dependency_flag[1][0]");<br>-        WRITE_UVLC(0, "num_add_layer_sets");<br>-        WRITE_FLAG(0, "vps_sub_layers_max_minus1_present_flag");<br>-        WRITE_FLAG(0, "max_tid_ref_present_flag");<br>-        WRITE_FLAG(0, "default_ref_layers_active_flag");<br>-        WRITE_UVLC(2, "vps_num_profile_tier_level_minus1");<br>-        WRITE_FLAG(1, "vps_profile_present_flag");<br>-        codeProfileTier(vps.ptl, vps.maxTempSubLayers, 1);<br>+#if ENABLE_ALPHA<br>+            if (vps.m_numLayers > 1)<br>+            {<br>+                WRITE_FLAG(0, "direct_dependency_flag[1][0]");<br>+                WRITE_UVLC(0, "num_add_layer_sets");<br>+                WRITE_FLAG(0, "vps_sub_layers_max_minus1_present_flag");<br>+                WRITE_FLAG(0, "max_tid_ref_present_flag");<br>+                WRITE_FLAG(0, "default_ref_layers_active_flag");<br>+                WRITE_UVLC(2, "vps_num_profile_tier_level_minus1");<br>+                WRITE_FLAG(1, "vps_profile_present_flag");<br>+                codeProfileTier(vps.ptl, vps.maxTempSubLayers, 1);<br> <br>-        WRITE_UVLC(0, "num_add_olss");<br>-        WRITE_CODE(0, 2, "default_output_layer_idc");<br>-        WRITE_CODE(1, 2, "profile_tier_level_idx[ i ][ j ]");<br>-        WRITE_CODE(2, 2, "profile_tier_level_idx[ i ][ j ]");<br>+                WRITE_UVLC(0, "num_add_olss");<br>+                WRITE_CODE(0, 2, "default_output_layer_idc");<br>+                WRITE_CODE(1, 2, "profile_tier_level_idx[ i ][ j ]");<br>+                WRITE_CODE(2, 2, "profile_tier_level_idx[ i ][ j ]");<br> <br>-        WRITE_UVLC(0, "vps_num_rep_formats_minus1");<br>+                WRITE_UVLC(0, "vps_num_rep_formats_minus1");<br> <br>-        WRITE_CODE(sps.picWidthInLumaSamples, 16, "pic_width_vps_in_luma_samples");<br>-        WRITE_CODE(sps.picHeightInLumaSamples, 16, "pic_height_vps_in_luma_samples");<br>-        WRITE_FLAG(1, "chroma_and_bit_depth_vps_present_flag");<br>+                WRITE_CODE(sps.picWidthInLumaSamples, 16, "pic_width_vps_in_luma_samples");<br>+                WRITE_CODE(sps.picHeightInLumaSamples, 16, "pic_height_vps_in_luma_samples");<br>+                WRITE_FLAG(1, "chroma_and_bit_depth_vps_present_flag");<br> <br>-        WRITE_CODE(sps.chromaFormatIdc, 2, "chroma_format_vps_idc");<br>+                WRITE_CODE(sps.chromaFormatIdc, 2, "chroma_format_vps_idc");<br> <br>-        if (sps.chromaFormatIdc == X265_CSP_I444)<br>-            WRITE_FLAG(0, "separate_colour_plane_vps_flag");<br>+                if (sps.chromaFormatIdc == X265_CSP_I444)<br>+                    WRITE_FLAG(0, "separate_colour_plane_vps_flag");<br> <br>-        WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_luma_minus8");<br>-        WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_chroma_minus8");<br>+                WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_luma_minus8");<br>+                WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_chroma_minus8");<br> <br>-        const Window& conf = sps.conformanceWindow;<br>-        WRITE_FLAG(conf.bEnabled, "conformance_window_vps_flag");<br>-        if (conf.bEnabled)<br>-        {<br>-            int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);<br>-            WRITE_UVLC(conf.leftOffset >> hShift, "conf_win_vps_left_offset");<br>-            WRITE_UVLC(conf.rightOffset >> hShift, "conf_win_vps_right_offset");<br>-            WRITE_UVLC(conf.topOffset >> vShift, "conf_win_vps_top_offset");<br>-            WRITE_UVLC(conf.bottomOffset >> vShift, "conf_win_vps_bottom_offset");<br>-        }<br>+                const Window& conf = sps.conformanceWindow;<br>+                WRITE_FLAG(conf.bEnabled, "conformance_window_vps_flag");<br>+                if (conf.bEnabled)<br>+                {<br>+                    int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);<br>+                    WRITE_UVLC(conf.leftOffset >> hShift, "conf_win_vps_left_offset");<br>+                    WRITE_UVLC(conf.rightOffset >> hShift, "conf_win_vps_right_offset");<br>+                    WRITE_UVLC(conf.topOffset >> vShift, "conf_win_vps_top_offset");<br>+                    WRITE_UVLC(conf.bottomOffset >> vShift, "conf_win_vps_bottom_offset");<br>+                }<br> <br>-        WRITE_FLAG(1, "max_one_active_ref_layer_flag");<br>-        WRITE_FLAG(0, "vps_poc_lsb_aligned_flag");<br>-        WRITE_FLAG(1, "poc_lsb_not_present_flag[");<br>-        WRITE_FLAG(0, "sub_layer_flag_info_present_flag");<br>+                WRITE_FLAG(1, "max_one_active_ref_layer_flag");<br>+                WRITE_FLAG(0, "vps_poc_lsb_aligned_flag");<br>+                WRITE_FLAG(1, "poc_lsb_not_present_flag[");<br>+                WRITE_FLAG(0, "sub_layer_flag_info_present_flag");<br> <br>-        for (int i = 1; i <= 1; i++)<br>-        {<br>-            for (int j = 0; j < vps.m_numLayers; j++)<br>-            {<br>-                WRITE_UVLC(vps.maxDecPicBuffering[0] - 1, "vps_max_dec_pic_buffering_minus1[i]");<br>-            }<br>+                for (int i = 1; i <= 1; i++)<br>+                {<br>+                    for (int j = 0; j < vps.m_numLayers; j++)<br>+                    {<br>+                        WRITE_UVLC(vps.maxDecPicBuffering[0] - 1, "vps_max_dec_pic_buffering_minus1[i]");<br>+                    }<br>+                }<br>+<br>+                WRITE_UVLC(vps.numReorderPics[0], "vps_num_reorder_pics[i]");<br>+                WRITE_UVLC(vps.maxLatencyIncrease[0] + 1, "vps_max_latency_increase_plus1[i]");<br>+<br>+                WRITE_UVLC(0, "direct_dep_type_len_minus2");<br>+<br>+                WRITE_FLAG(0, "default_direct_dependency_flag");<br>+                WRITE_UVLC(0, "vps_non_vui_extension_length");<br>+                WRITE_FLAG(0, "vps_vui_present_flag");<br>+                WRITE_FLAG(0, "vps_extension2_flag");<br>         }<br>+#endif<br> <br>-        WRITE_UVLC(vps.numReorderPics[0], "vps_num_reorder_pics[i]");<br>-        WRITE_UVLC(vps.maxLatencyIncrease[0] + 1, "vps_max_latency_increase_plus1[i]");<br>+#if ENABLE_MULTIVIEW<br>+            if (vps.m_numViews > 1)<br>+            {<br>+                for (uint8_t i = 0; i < vps.m_numViews; i++)<br>+                    WRITE_CODE(vps.m_viewId[i], vps.m_viewIdLen, "view_id_val[i]");<br>+<br>+                for (int i = 1; i < vps.m_numViews; i++)<br>+                {<br>+                    for (int j = 0; j < i; j++)<br>+                    {<br>+                        if (j == 0)<br>+                            WRITE_FLAG(1, "direct_dependency_flag[1][0]");<br>+                        else<br>+                            WRITE_FLAG(0, "direct_dependency_flag[1][0]");<br>+                    }<br>+                }<br>+                WRITE_FLAG(0, "vps_sub_layers_max_minus1_present_flag");<br>+                WRITE_FLAG(0, "max_tid_ref_present_flag");<br>+                WRITE_FLAG(1, "default_ref_layers_active_flag");<br>+                WRITE_UVLC(2, "vps_num_profile_tier_level_minus1");<br>+                WRITE_FLAG(1, "vps_profile_present_flag[i]");<br>+                codeProfileTier(vps.ptl, vps.maxTempSubLayers, 1);<br>+                WRITE_UVLC(0, "num_add_olss");<br>+                WRITE_CODE(0, 2, "default_output_layer_idc");<br>+<br>+                for (int i = 1; i <= vps.m_vpsNumLayerSetsMinus1; i++)<br>+                {<br>+                    for (int j = 0; j < vps.m_numViews; j++)<br>+                    {<br>+                        WRITE_CODE((j == 0) ? 1 : 2, 2, "profile_tier_level_idx[ i ][ j ]");<br>+                    }<br>+                }<br>+                WRITE_UVLC(0, "vps_num_rep_formats_minus1");<br>+<br>+                WRITE_CODE(sps.picWidthInLumaSamples, 16, "pic_width_vps_in_luma_samples");<br>+                WRITE_CODE(sps.picHeightInLumaSamples, 16, "pic_height_vps_in_luma_samples");<br>+                WRITE_FLAG(1, "chroma_and_bit_depth_vps_present_flag");<br>+<br>+                WRITE_CODE(sps.chromaFormatIdc, 2, "chroma_format_vps_idc");<br> <br>-        WRITE_UVLC(0, "direct_dep_type_len_minus2");<br>+                if (sps.chromaFormatIdc == X265_CSP_I444)<br>+                    WRITE_FLAG(0, "separate_colour_plane_vps_flag");<br>+<br>+                WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_luma_minus8");<br>+                WRITE_CODE(X265_DEPTH - 8, 4, "bit_depth_vps_chroma_minus8");<br>+<br>+                const Window& conf = sps.conformanceWindow;<br>+                WRITE_FLAG(conf.bEnabled, "conformance_window_vps_flag");<br>+                if (conf.bEnabled)<br>+                {<br>+                    int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);<br>+                    WRITE_UVLC(conf.leftOffset >> hShift, "conf_win_vps_left_offset");<br>+                    WRITE_UVLC(conf.rightOffset >> hShift, "conf_win_vps_right_offset");<br>+                    WRITE_UVLC(conf.topOffset >> vShift, "conf_win_vps_top_offset");<br>+                    WRITE_UVLC(conf.bottomOffset >> vShift, "conf_win_vps_bottom_offset");<br>+                }<br> <br>-        WRITE_FLAG(0, "default_direct_dependency_flag");<br>-        WRITE_UVLC(0, "vps_non_vui_extension_length");<br>-        WRITE_FLAG(0, "vps_vui_present_flag");<br>-        WRITE_FLAG(0, "vps_extension2_flag");<br>+                WRITE_FLAG(1, "max_one_active_ref_layer_flag");<br>+                WRITE_FLAG(0, "vps_poc_lsb_aligned_flag");<br>+                WRITE_FLAG(0, "sub_layer_flag_info_present_flag");<br>+<br>+                for (int i = 1; i <= vps.m_vpsNumLayerSetsMinus1; i++)<br>+                {<br>+                    for (int j = 0; j < vps.m_numViews; j++)<br>+                    {<br>+                        WRITE_UVLC(vps.maxDecPicBuffering[0] - 1, "vps_max_dec_pic_buffering_minus1[i]");<br>+                    }<br>+                }<br>+                WRITE_UVLC(vps.numReorderPics[0], "vps_num_reorder_pics[i]");<br>+                WRITE_UVLC(vps.maxLatencyIncrease[0] + 1, "vps_max_latency_increase_plus1[i]");<br>+<br>+                WRITE_UVLC(0, "direct_dep_type_len_minus2");<br>+<br>+                WRITE_FLAG(1, "default_direct_dependency_flag");<br>+                WRITE_CODE(2, 2, "default_direct_dependency_type");<br>+                WRITE_UVLC(0, "vps_non_vui_extension_length");<br>+                WRITE_FLAG(0, "vps_vui_present_flag");<br>+                WRITE_FLAG(0, "vps_extension2_flag");<br>+            }<br>+#endif<br>+        }<br>     }<br>+    else<br>+        WRITE_FLAG(0, "vps_extension_flag");<br> #else<br>     WRITE_FLAG(0, "vps_extension_flag");<br> #endif<br>@@ -383,41 +487,58 @@ void Entropy::codeVPS(const VPS& vps, const SPS& sps)<br> void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList, const ProfileTierLevel& ptl, int layer)<br> {<br>     WRITE_CODE(0, 4, "sps_video_parameter_set_id");<br>-    WRITE_CODE(sps.maxTempSubLayers - 1, 3, "sps_max_sub_layers_minus1");<br>-    WRITE_FLAG(sps.maxTempSubLayers == 1,   "sps_temporal_id_nesting_flag");<br>-<br>-    codeProfileTier(ptl, sps.maxTempSubLayers);<br>+    WRITE_CODE(!layer ? sps.maxTempSubLayers - 1 : sps.setSpsExtOrMaxSubLayersMinus1, 3, "sps_ext_or_max_sub_layers_minus1");<br>+#if ENABLE_MULTIVIEW<br>+    if (!(layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7))<br>+#endif<br>+    {<br>+        WRITE_FLAG(sps.maxTempSubLayers == 1, "sps_temporal_id_nesting_flag");<br>+        codeProfileTier(ptl, sps.maxTempSubLayers, layer);<br>+    }<br> <br>     WRITE_UVLC(layer, "sps_seq_parameter_set_id");<br>-    WRITE_UVLC(sps.chromaFormatIdc, "chroma_format_idc");<br>+#if ENABLE_MULTIVIEW<br>+    if (layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7)<br>+        WRITE_FLAG(0, "update_rep_format_flag");<br>+    else<br>+#endif<br>+    {<br>+        WRITE_UVLC(sps.chromaFormatIdc, "chroma_format_idc");<br> <br>-    if (sps.chromaFormatIdc == X265_CSP_I444)<br>-        WRITE_FLAG(0,                       "separate_colour_plane_flag");<br>+        if (sps.chromaFormatIdc == X265_CSP_I444)<br>+            WRITE_FLAG(0,                       "separate_colour_plane_flag");<br> <br>-    WRITE_UVLC(sps.picWidthInLumaSamples,   "pic_width_in_luma_samples");<br>-    WRITE_UVLC(sps.picHeightInLumaSamples,  "pic_height_in_luma_samples");<br>+        WRITE_UVLC(sps.picWidthInLumaSamples,   "pic_width_in_luma_samples");<br>+        WRITE_UVLC(sps.picHeightInLumaSamples,  "pic_height_in_luma_samples");<br> <br>-    const Window& conf = sps.conformanceWindow;<br>-    WRITE_FLAG(conf.bEnabled, "conformance_window_flag");<br>-    if (conf.bEnabled)<br>-    {<br>-        int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);<br>-        WRITE_UVLC(conf.leftOffset   >> hShift, "conf_win_left_offset");<br>-        WRITE_UVLC(conf.rightOffset  >> hShift, "conf_win_right_offset");<br>-        WRITE_UVLC(conf.topOffset    >> vShift, "conf_win_top_offset");<br>-        WRITE_UVLC(conf.bottomOffset >> vShift, "conf_win_bottom_offset");<br>+        const Window& conf = sps.conformanceWindow;<br>+        WRITE_FLAG(conf.bEnabled, "conformance_window_flag");<br>+        if (conf.bEnabled)<br>+        {<br>+            int hShift = CHROMA_H_SHIFT(sps.chromaFormatIdc), vShift = CHROMA_V_SHIFT(sps.chromaFormatIdc);<br>+            WRITE_UVLC(conf.leftOffset   >> hShift, "conf_win_left_offset");<br>+            WRITE_UVLC(conf.rightOffset  >> hShift, "conf_win_right_offset");<br>+            WRITE_UVLC(conf.topOffset    >> vShift, "conf_win_top_offset");<br>+            WRITE_UVLC(conf.bottomOffset >> vShift, "conf_win_bottom_offset");<br>+        }<br>+<br>+        WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_luma_minus8");<br>+        WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_chroma_minus8");<br>     }<br> <br>-    WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_luma_minus8");<br>-    WRITE_UVLC(X265_DEPTH - 8,   "bit_depth_chroma_minus8");<br>     WRITE_UVLC(sps.log2MaxPocLsb - 4, "log2_max_pic_order_cnt_lsb_minus4");<br>-    WRITE_FLAG(true,             "sps_sub_layer_ordering_info_present_flag");<br>-<br>-    for (uint32_t i = 0; i < sps.maxTempSubLayers; i++)<br>+#if ENABLE_MULTIVIEW<br>+    if (!(layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7))<br>+#endif<br>     {<br>-        WRITE_UVLC(sps.maxDecPicBuffering[i] - 1, "sps_max_dec_pic_buffering_minus1[i]");<br>-        WRITE_UVLC(sps.numReorderPics[i],         "sps_num_reorder_pics[i]");<br>-        WRITE_UVLC(sps.maxLatencyIncrease[i] + 1, "sps_max_latency_increase_plus1[i]");<br>+        WRITE_FLAG(true,             "sps_sub_layer_ordering_info_present_flag");<br>+<br>+        for (uint32_t i = 0; i < sps.maxTempSubLayers; i++)<br>+        {<br>+            WRITE_UVLC(sps.maxDecPicBuffering[i] - 1, "sps_max_dec_pic_buffering_minus1[i]");<br>+            WRITE_UVLC(sps.numReorderPics[i],         "sps_num_reorder_pics[i]");<br>+            WRITE_UVLC(sps.maxLatencyIncrease[i] + 1, "sps_max_latency_increase_plus1[i]");<br>+        }<br>     }<br> <br>     WRITE_UVLC(sps.log2MinCodingBlockSize - 3,    "log2_min_coding_block_size_minus3");<br>@@ -429,9 +550,20 @@ void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList, const Prof<br>     WRITE_FLAG(scalingList.m_bEnabled,            "scaling_list_enabled_flag");<br>     if (scalingList.m_bEnabled)<br>     {<br>-        WRITE_FLAG(scalingList.m_bDataPresent,    "sps_scaling_list_data_present_flag");<br>-        if (scalingList.m_bDataPresent)<br>-            codeScalingList(scalingList);<br>+#if ENABLE_MULTIVIEW<br>+        if (sps.maxViews > 1)<br>+        {<br>+            if ((layer != 0 && sps.setSpsExtOrMaxSubLayersMinus1 == 7))<br>+                WRITE_FLAG(1, "sps_infer_scaling_list_flag");<br>+            WRITE_CODE(0, 6, "sps_scaling_list_ref_layer_id");<br>+        }<br>+        else<br>+#endif<br>+        {<br>+            WRITE_FLAG(scalingList.m_bDataPresent, "sps_scaling_list_data_present_flag");<br>+            if (scalingList.m_bDataPresent)<br>+                codeScalingList(scalingList);<br>+        }<br>     }<br>     WRITE_FLAG(sps.bUseAMP, "amp_enabled_flag");<br>     WRITE_FLAG(sps.bUseSAO, "sample_adaptive_offset_enabled_flag");<br>@@ -448,7 +580,22 @@ void Entropy::codeSPS(const SPS& sps, const ScalingList& scalingList, const Prof<br>     WRITE_FLAG(1, "vui_parameters_present_flag");<br>     codeVUI(sps.vuiParameters, sps.maxTempSubLayers, sps.bEmitVUITimingInfo, sps.bEmitVUIHRDInfo, layer);<br> <br>-    WRITE_FLAG(0, "sps_extension_flag");<br>+    WRITE_FLAG(sps.sps_extension_flag, "sps_extension_flag");<br>+<br>+#if ENABLE_MULTIVIEW<br>+    if (sps.sps_extension_flag)<br>+    {<br>+        WRITE_FLAG(0, "sps_range_extensions_flag");<br>+        WRITE_FLAG(sps.maxViews > 1, "sps_multilayer_extension_flag");<br>+        WRITE_FLAG(0, "sps_3d_extension_flag");<br>+        WRITE_CODE(0, 5, "sps_extension_5bits");<br>+<br>+        if (layer == 0)<br>+            WRITE_FLAG(0, "inter_view_mv_vert_constraint_flag");<br>+        else<br>+            WRITE_FLAG(1, "inter_view_mv_vert_constraint_flag");<br>+    }<br>+#endif<br> }<br> <br> void Entropy::codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26, int layer)<br>@@ -457,7 +604,7 @@ void Entropy::codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26,<br>     WRITE_UVLC(layer,                          "pps_seq_parameter_set_id");<br>     WRITE_FLAG(0,                          "dependent_slice_segments_enabled_flag");<br>     WRITE_FLAG(0,                          "output_flag_present_flag");<br>-    WRITE_CODE(0, 3,                       "num_extra_slice_header_bits");<br>+    WRITE_CODE(pps.maxViews > 1 ? 2 : 0, 3,"num_extra_slice_header_bits");<br>     WRITE_FLAG(pps.bSignHideEnabled,       "sign_data_hiding_flag");<br>     WRITE_FLAG(0,                          "cabac_init_present_flag");<br>     WRITE_UVLC(pps.numRefIdxDefault[0] - 1, "num_ref_idx_l0_default_active_minus1");<br>@@ -498,7 +645,25 @@ void Entropy::codePPS( const PPS& pps, bool filerAcross, int iPPSInitQpMinus26,<br>     WRITE_FLAG(0, "lists_modification_present_flag");<br>     WRITE_UVLC(0, "log2_parallel_merge_level_minus2");<br>     WRITE_FLAG(0, "slice_segment_header_extension_present_flag");<br>-    WRITE_FLAG(0, "pps_extension_flag");<br>+    WRITE_FLAG(pps.pps_extension_flag, "pps_extension_flag");<br>+<br>+#if ENABLE_MULTIVIEW<br>+    if (pps.pps_extension_flag)<br>+    {<br>+        WRITE_FLAG(0, "pps_range_extensions_flag");<br>+        WRITE_FLAG(pps.maxViews > 1, "pps_multilayer_extension_flag");<br>+        WRITE_FLAG(0, "pps_3d_extension_flag");<br>+        WRITE_CODE(0, 5, "pps_extension_5bits");<br>+<br>+        if (pps.maxViews > 1)<br>+        {<br>+            WRITE_FLAG(0, "poc_reset_info_present_flag");<br>+            WRITE_FLAG(0, "pps_infer_scaling_list_flag");<br>+            WRITE_UVLC(0, "num_ref_loc_offsets");<br>+            WRITE_FLAG(0, "colour_mapping_enabled_flag");<br>+        }<br>+    }<br>+#endif<br> }<br> <br> void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers, int layer)<br>@@ -519,7 +684,7 @@ void Entropy::codeProfileTier(const ProfileTierLevel& ptl, int maxTempSubLayers,<br>     WRITE_FLAG(ptl.nonPackedConstraintFlag, "general_non_packed_constraint_flag");<br>     WRITE_FLAG(ptl.frameOnlyConstraintFlag, "general_frame_only_constraint_flag");<br> <br>-    if (ptl.profileIdc[layer] == Profile::MAINREXT || ptl.profileIdc[layer] == Profile::HIGHTHROUGHPUTREXT || ptl.profileIdc[layer] == Profile::SCALABLEMAIN || ptl.profileIdc[layer] == Profile::SCALABLEMAIN10)<br>+    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)<br>     {<br>         uint32_t bitDepthConstraint = ptl.bitDepthConstraint;<br>         int csp = ptl.chromaFormatConstraint;<br>@@ -740,12 +905,39 @@ void Entropy::codeSliceHeader(const Slice& slice, FrameData& encData, uint32_t s<br>         WRITE_CODE(slice_addr, slice_addr_bits, "slice_segment_address");<br>     }<br> <br>+#if ENABLE_MULTIVIEW<br>+    if (encData.m_param->numViews > 1)<br>+    {<br>+        int esb = 0;<br>+        if (2 > esb)<br>+        {<br>+            esb++;<br>+            WRITE_FLAG(0, "discardable_flag");<br>+        }<br>+        if (2 > esb)<br>+        {<br>+            esb++;<br>+            WRITE_FLAG(0, "cross_layer_bla_flag");<br>+        }<br>+    }<br>+#endif<br>+<br>     WRITE_UVLC(slice.m_sliceType, "slice_type");<br> <br>-    if (!slice.getIdrPicFlag())<br>+    if (layer > 0 || !slice.getIdrPicFlag())<br>     {<br>         int picOrderCntLSB = (slice.m_poc - slice.m_lastIDR + (1 << slice.m_sps->log2MaxPocLsb)) % (1 << slice.m_sps->log2MaxPocLsb);<br>         WRITE_CODE(picOrderCntLSB, slice.m_sps->log2MaxPocLsb, "pic_order_cnt_lsb");<br>+    }<br>+    if (!slice.getIdrPicFlag())<br>+    {<br>+#if ENABLE_MULTIVIEW<br>+        if (!(slice.m_param->numViews > 1))<br>+#endif<br>+        {<br>+            int picOrderCntLSB = (slice.m_poc - slice.m_lastIDR + (1 << slice.m_sps->log2MaxPocLsb)) % (1 << slice.m_sps->log2MaxPocLsb);<br>+            WRITE_CODE(picOrderCntLSB, slice.m_sps->log2MaxPocLsb, "pic_order_cnt_lsb");<br>+        }<br> <br> #if _DEBUG || CHECKED_BUILD<br>         // check for bitstream restriction stating that:<br>diff --git a/source/encoder/level.cpp b/source/encoder/level.cpp<br>index c62c63426..12803baff 100644<br>--- a/source/encoder/level.cpp<br>+++ b/source/encoder/level.cpp<br>@@ -108,6 +108,11 @@ void determineLevel(const x265_param &param, VPS& vps)<br>     else<br>         vps.ptl.profileIdc[0] = Profile::MAINREXT;<br> <br>+#if ENABLE_MULTIVIEW<br>+    if (param.numViews == 2)<br>+        vps.ptl.profileIdc[1] = Profile::MULTIVIEWMAIN;<br>+#endif<br>+<br>     /* determine which profiles are compatible with this stream */<br> <br>     memset(vps.ptl.profileCompatibilityFlag, 0, sizeof(vps.ptl.profileCompatibilityFlag));<br>diff --git a/source/x265.h b/source/x265.h<br>index baf18e4fc..091696e03 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -628,6 +628,9 @@ typedef enum<br> <br> #if ENABLE_MULTIVIEW<br> #define MAX_VIEWS 2<br>+#define MAX_VPS_NUM_SCALABILITY_TYPES     16<br>+#define MAX_VPS_LAYER_ID_PLUS1            MAX_VIEWS<br>+#define MULTIVIEW_SCALABILITY_IDX         1<br> #else<br> #define MAX_VIEWS 1<br> #endif<br>-- <br>2.36.0.windows.1<br><br></div>