From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 8A3274C08D for ; Wed, 5 Feb 2025 15:11:14 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D9CD068B6FC; Wed, 5 Feb 2025 17:11:09 +0200 (EET) Received: from out203-205-221-192.mail.qq.com (out203-205-221-192.mail.qq.com [203.205.221.192]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CF2CB68B480 for ; Wed, 5 Feb 2025 17:11:01 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foxmail.com; s=s201512; t=1738768252; bh=UfgVUmjeC7ofGrmoZ2P3VpLcALkqB6LUzw41OJS8R90=; h=From:To:Cc:Subject:Date; b=aM00bkYukD0OlmMM6HDU0p19eAnhna9x09ubyHfzd5UF1zWN76CWBX1MiRFRLTX/f ZeVh2gWNkG7idUqPMJFntyv2j1j2eauuJdB+XPtzokj8QrxR4M5sy5q9LvE/fDHVgk raXMzcSEOuOsGXZQNxCAqe2mUX8Hfnrf/Y35K9BA= Received: from ZHILIZHAO-MB1.tencent.com ([240e:3b7:3277:36f0:544a:7de:c82a:2aa2]) by newxmesmtplogicsvrsza29-0.qq.com (NewEsmtp) with SMTP id 2B3BEA3D; Wed, 05 Feb 2025 23:10:51 +0800 X-QQ-mid: xmsmtpt1738768251tzhpxzcvo Message-ID: X-QQ-XMAILINFO: OSiyqyQsnID8v0LPvLdLlzSX8TnwlYcz0f3HKd7WDwLhk/h7Ds46CLu0wconDm EkFYV4lZiIrbw41c3UshZph+6MqRf9HRmyHz4X7QtFYnwIDNihzYPdXmfMu9OCxk85lOABot6Qkc wEUjrVK7LqQDsYyH8movf6zMqb57m279d6yu4l4Q+AItw0POWfXDDzsQnUft4oqGVX4APCCCLISv mxuGms7mjdWsILRC2MNi7fhCfVZqfFZJlqu3mo6n9GtBxT0zELPx2exZVi6WYyc7bM1l7j9V6p96 GiBQn3zA1nBjXX39FBZhm96oR06QXc5bMqW4C/uJksJCbN/ca+SITfc8jJQMyDZLlGeutBPP+l+9 LPYw0EJC08fgNVvtMLSq1oOQ10u5mF/X88BuUQsaj4jlzdH7DxoLuqXpGWJxbl8QKfhkgMKgM1Vo 4snzqS7EMyFOCT/0KQccPQ/tcSiTvtctYbslD7c5Y9DC/6V93Rgm/m5ah1BRRENwxoFBO83dyI1l E22K0TTySeB47HgUumPA5bh0JTxITJJVu+dxMP+NWzUJxSwv9BeTc32cfhzrxvlDpJrWIx8mJjrM VTiM1FdJwvRi/y9VmUIlvoVP359Wea7LKEChvNG48w14Qf+EF824DF/URcRFjYF5E2H+elExARc4 78jFGCAGyUHSGnxvlqsrbawsHc1nb6OMpxcgFjuS9ClIeXPlqJlIbX0ETWeiakbvvABdNe6Srovm KSWaJRV/QpmJL9fOD83r3xx/TVs9fDhei6x5pCA5AZXunutjt9/mDwo0W9jbd/9jU178H51KNXp3 FcwsiqeygkYtHpNDQhEAkv+qurnO3xIs25GLQqEqREJ5Of+OtG6OHhcRwQ0XOqZD8+gY4DgFVhhM cTjK1y2Kh3j2avhzPluOQAjsi4AL4CenvTrWV4eAjxA7vYrLgr7s329K2WbrLxl9+54HvvGT/gmt znrlQvsku+M/c25cciynfCXngBSOu4 X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= From: Zhao Zhili To: ffmpeg-devel@ffmpeg.org Date: Wed, 5 Feb 2025 23:10:49 +0800 X-OQ-MSGID: <20250205151049.71095-1-quinkblack@foxmail.com> X-Mailer: git-send-email 2.46.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 2/3] avcodec/hevc/ps: Add basic HEVC_SCALABILITY_AUXILIARY support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Zhao Zhili Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: From: Zhao Zhili Only implementing what's needed for HEVC with alpha. Signed-off-by: Zhao Zhili --- libavcodec/hevc/hevc.h | 5 ++ libavcodec/hevc/ps.c | 126 +++++++++++++++++++++++++++++------------ libavcodec/hevc/ps.h | 4 ++ 3 files changed, 98 insertions(+), 37 deletions(-) diff --git a/libavcodec/hevc/hevc.h b/libavcodec/hevc/hevc.h index b2229fda40..710786a89d 100644 --- a/libavcodec/hevc/hevc.h +++ b/libavcodec/hevc/hevc.h @@ -170,4 +170,9 @@ enum HEVCScalabilityMask { HEVC_SCALABILITY_MASK_MAX = 0xFFFF, }; +enum HEVCAuxId { + HEVC_AUX_ALPHA = 1, + HEVC_AUX_DEPTH = 2, +}; + #endif /* AVCODEC_HEVC_HEVC_H */ diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c index 861a6bb0a2..a77c697c08 100644 --- a/libavcodec/hevc/ps.c +++ b/libavcodec/hevc/ps.c @@ -460,14 +460,17 @@ 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}; + uint8_t dimension_id_len[16] = {0}; + uint8_t dimension_id[16] = {0}; + unsigned n; - int splitting_flag, dimension_id_len, view_id_len, num_add_olss, num_scalability_types, + int splitting_flag, 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; } @@ -520,7 +523,8 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps */ vps->nb_layers = 2; - if (parse_ptl(gb, avctx, 0, &ptl_dummy, vps->vps_max_sub_layers) < 0) + if (vps->vps_base_layer_internal_flag && + parse_ptl(gb, avctx, 0, &ptl_dummy, vps->vps_max_sub_layers) < 0) return AVERROR_INVALIDDATA; splitting_flag = get_bits1(gb); @@ -529,20 +533,25 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps if (!num_scalability_types) { av_log(avctx, AV_LOG_ERROR, "Missing scalability mask\n"); return AVERROR_INVALIDDATA; - } else if (num_scalability_types > 1) { - av_log(avctx, AV_LOG_ERROR, "Scalability number %d not supported\n", - num_scalability_types); - 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; } + // x265 specify MULTIVIEW when the stream really is alpha video only. + if (num_scalability_types > 1) + av_log(avctx, AV_LOG_WARNING, "Multiple scalability types presented\n"); - if (!splitting_flag) - dimension_id_len = get_bits(gb, 3) + 1; + n = 0; + for (int i = 0; i < num_scalability_types - splitting_flag; i++) { + dimension_id_len[i] = get_bits(gb, 3) + 1; + n += dimension_id_len[i]; + } + if (splitting_flag) + dimension_id_len[num_scalability_types - 1] = 5 - n; if (get_bits1(gb)) { /* vps_nuh_layer_id_present_flag */ int layer_id_in_nuh = get_bits(gb, 6); @@ -559,28 +568,57 @@ static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS *vps } if (!splitting_flag) { - int view_idx = get_bits(gb, dimension_id_len); - if (view_idx != 1) { - av_log(avctx, AV_LOG_ERROR, "Unexpected ViewOrderIdx: %d\n", view_idx); + int index = 0; + + for (int i = 0; i < num_scalability_types; i++) + dimension_id[i] = get_bits(gb, dimension_id_len[i]); + + if (vps->scalability_mask_flag & HEVC_SCALABILITY_MULTIVIEW) + index++; + + /* AuxId 1 is alpha, 2 is depth. Only support alpha */ + if (vps->scalability_mask_flag & HEVC_SCALABILITY_AUXILIARY && + dimension_id[index] != HEVC_AUX_ALPHA) { + av_log(avctx, AV_LOG_WARNING, + "Unsupported dimension_id %d for HEVC_SCALABILITY_AUXILIARY\n", + dimension_id[index]); return AVERROR_PATCHWELCOME; } } view_id_len = get_bits(gb, 4); - if (view_id_len) - for (int i = 0; i < 2 /* NumViews */; i++) + if (view_id_len) { + n = (vps->scalability_mask_flag & HEVC_SCALABILITY_MULTIVIEW) ? 2 : 1; + for (int i = 0; i < n; 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); + if (vps->num_add_layer_sets > 1) { + av_log(avctx, AV_LOG_WARNING, + "Unsupported num_add_layer_sets: %d\n", vps->num_add_layer_sets); + return AVERROR_PATCHWELCOME; + } + + if (vps->num_add_layer_sets) { + /* highest_layer_idx_plus1 */ + if (!get_bits1(gb)) + return AVERROR_PATCHWELCOME; + } } - 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 +651,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 +711,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 +734,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); @@ -741,8 +789,12 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, } vps->vps_id = vps_id; - if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits - av_log(avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n"); + vps->vps_base_layer_internal_flag = get_bits1(gb); + vps->vps_base_layer_available_flag = get_bits1(gb); + if (!vps->vps_base_layer_internal_flag || !vps->vps_base_layer_available_flag) { + av_log(avctx, AV_LOG_ERROR, + "vps_base_layer_internal_flag or vps_base_layer_available_flag not set\n"); + ret = AVERROR_PATCHWELCOME; goto err; } diff --git a/libavcodec/hevc/ps.h b/libavcodec/hevc/ps.h index d3465e3d27..f706b889e6 100644 --- a/libavcodec/hevc/ps.h +++ b/libavcodec/hevc/ps.h @@ -171,6 +171,9 @@ typedef struct RepFormat { typedef struct HEVCVPS { unsigned int vps_id; + uint8_t vps_base_layer_internal_flag; + uint8_t vps_base_layer_available_flag; + uint8_t vps_temporal_id_nesting_flag; int vps_max_layers; int vps_max_sub_layers; ///< vps_max_temporal_layers_minus1 + 1 @@ -237,6 +240,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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".