[FFmpeg-devel] [PATCH WIP 3/5] avcodec/hevc/ps: Add basic HEVC_SCALABILITY_AUXILIARY support

Zhao Zhili quinkblack at foxmail.com
Wed Dec 11 06:23:29 EET 2024


From: Zhao Zhili <zhilizhao at tencent.com>

Only implementing what's needed for HEVC with alpha.
---
 libavcodec/hevc/ps.c | 64 +++++++++++++++++++++++++++++---------------
 libavcodec/hevc/ps.h |  1 +
 2 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 5b1bcd9b7c..59df750b91 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -460,14 +460,14 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
                           uint64_t layer1_id_included)
 {
     PTL ptl_dummy;
-    uint8_t max_sub_layers[HEVC_MAX_LAYERS];
+    uint8_t max_sub_layers[HEVC_MAX_LAYERS] = {1, 1};
 
     int splitting_flag, dimension_id_len, view_id_len, num_add_olss, num_scalability_types,
         default_output_layer_idc, direct_dep_type_len, direct_dep_type,
         sub_layers_max_present, sub_layer_flag_info_present_flag, nb_ptl;
     unsigned non_vui_extension_length;
 
-    if (vps->vps_max_layers == 1 || vps->vps_num_layer_sets == 1) {
+    if (vps->vps_max_layers == 1) {
         av_log(avctx, AV_LOG_VERBOSE, "Ignoring VPS extensions with a single layer\n");
         return 0;
     }
@@ -535,7 +535,8 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
         return AVERROR_PATCHWELCOME;
     }
 
-    if (!(vps->scalability_mask_flag & HEVC_SCALABILITY_MULTIVIEW)) {
+    if (!(vps->scalability_mask_flag &
+          (HEVC_SCALABILITY_MULTIVIEW | HEVC_SCALABILITY_AUXILIARY))) {
         av_log(avctx, AV_LOG_ERROR, "Scalability type %d not supported\n",
                15 - ff_ctz(vps->scalability_mask_flag));
         return AVERROR_PATCHWELCOME;
@@ -571,16 +572,25 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
         for (int i = 0; i < 2 /* NumViews */; i++)
             vps->view_id[i] = get_bits(gb, view_id_len);
 
-    if (!get_bits1(gb) /* direct_dependency_flag */) {
-        av_log(avctx, AV_LOG_WARNING, "Independent output layers not supported\n");
-        return AVERROR_PATCHWELCOME;
+    /* direct_dependency_flag */
+    vps->num_direct_ref_layers[1] = get_bits1(gb);
+    if (!vps->num_direct_ref_layers[1]) {
+        vps->num_add_layer_sets = get_ue_golomb(gb);
+        for (int i = 0; i < vps->num_add_layer_sets; i++) {
+            /* highest_layer_idx_plus1 */
+            skip_bits1(gb);
+        }
     }
-    vps->num_direct_ref_layers[1] = 1;
+    vps->num_output_layer_sets = vps->vps_num_layer_sets + vps->num_add_layer_sets;
+    if (vps->num_output_layer_sets != 2)
+        return AVERROR_INVALIDDATA;
 
     sub_layers_max_present = get_bits1(gb); // vps_sub_layers_max_minus1_present_flag
-    for (int i = 0; i < vps->vps_max_layers; i++)
-        max_sub_layers[i] = sub_layers_max_present ? get_bits(gb, 3) + 1 :
-                                                     vps->vps_max_sub_layers;
+    if (sub_layers_max_present) {
+        for (int i = 0; i < vps->vps_max_layers; i++)
+            max_sub_layers[i] = sub_layers_max_present ? get_bits(gb, 3) + 1 :
+                                                         vps->vps_max_sub_layers;
+    }
 
     if (get_bits1(gb) /* max_tid_ref_present_flag */)
         skip_bits(gb, 3); // max_tid_il_ref_pics_plus1
@@ -613,18 +623,24 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
     }
 
     /* Consequence of established layer dependencies */
-    if (layer1_id_included != ((1 << vps->layer_id_in_nuh[0]) |
+    if (layer1_id_included &&
+        layer1_id_included != ((1 << vps->layer_id_in_nuh[0]) |
                                (1 << vps->layer_id_in_nuh[1]))) {
-        av_log(avctx, AV_LOG_ERROR, "Dependent layer not included in layer ID?\n");
-        return AVERROR_PATCHWELCOME;
+            av_log(avctx, AV_LOG_ERROR,
+                   "Dependent layer not included in layer ID?\n");
+            return AVERROR_PATCHWELCOME;
     }
+    if (!layer1_id_included)
+        vps->ols[1] = 2;
+    else
+        vps->ols[1] = 3;
 
-    vps->num_output_layer_sets = 2;
-    vps->ols[1] = 3;
+    if (vps->vps_num_layer_sets == 1 || default_output_layer_idc == 2)
+        skip_bits1(gb);
 
     for (int j = 0; j < av_popcount64(vps->ols[1]); j++) {
         int ptl_idx = get_bits(gb, av_ceil_log2(nb_ptl));
-        if (ptl_idx < 1 || ptl_idx >= nb_ptl) {
+        if (ptl_idx >= nb_ptl) {
             av_log(avctx, AV_LOG_ERROR, "Invalid PTL index: %d\n", ptl_idx);
             return AVERROR_INVALIDDATA;
         }
@@ -667,6 +683,8 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
 
     vps->max_one_active_ref_layer = get_bits1(gb);
     vps->poc_lsb_aligned          = get_bits1(gb);
+    if (!vps->num_direct_ref_layers[1])
+        vps->poc_lsb_not_present = get_bits1(gb) << 1;
 
     sub_layer_flag_info_present_flag = get_bits1(gb);
     for (int j = 0; j < FFMAX(max_sub_layers[0], max_sub_layers[1]); j++) {
@@ -688,12 +706,14 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps
         return AVERROR_INVALIDDATA;
     }
 
-    skip_bits1(gb); /* direct_depenency_all_layers_flag */
-    direct_dep_type = get_bits_long(gb, direct_dep_type_len);
-    if (direct_dep_type > HEVC_DEP_TYPE_BOTH) {
-        av_log(avctx, AV_LOG_WARNING, "Unsupported direct_dep_type: %d\n",
-               direct_dep_type);
-        return AVERROR_PATCHWELCOME;
+    /* direct_depenency_all_layers_flag */
+    if (get_bits1(gb)) {
+        direct_dep_type = get_bits_long(gb, direct_dep_type_len);
+        if (direct_dep_type > HEVC_DEP_TYPE_BOTH) {
+            av_log(avctx, AV_LOG_WARNING, "Unsupported direct_dep_type: %d\n",
+                   direct_dep_type);
+            return AVERROR_PATCHWELCOME;
+        }
     }
 
     non_vui_extension_length = get_ue_golomb(gb);
diff --git a/libavcodec/hevc/ps.h b/libavcodec/hevc/ps.h
index d3465e3d27..2b5c2c0c1d 100644
--- a/libavcodec/hevc/ps.h
+++ b/libavcodec/hevc/ps.h
@@ -237,6 +237,7 @@ typedef struct HEVCVPS {
 
     // NumDirectRefLayers[layer_idx]
     uint8_t num_direct_ref_layers[HEVC_VPS_MAX_LAYERS];
+    uint8_t num_add_layer_sets;
 
     RepFormat rep_format;
 
-- 
2.46.0



More information about the ffmpeg-devel mailing list