[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 ¶m, 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