Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: James Almer <jamrial@gmail.com>
To: ffmpeg-devel@ffmpeg.org
Subject: Re: [FFmpeg-devel] [PATCH v4 2/3] avcodec/hevc/ps: Add basic HEVC_SCALABILITY_AUXILIARY support
Date: Thu, 6 Feb 2025 10:25:31 -0300
Message-ID: <d04f73fd-01b4-4a39-be1b-bed3b5c1b920@gmail.com> (raw)
In-Reply-To: <tencent_572AB8A896154D2DA04B4D8C4FD55520A707@qq.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 11784 bytes --]

On 2/6/2025 12:49 AM, Zhao Zhili wrote:
> From: Zhao Zhili <zhilizhao@tencent.com>
> 
> Only implementing what's needed for HEVC with alpha.
> 
> Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
> ---
>   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..4f18cd72e4 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 &&

What's the point checking for this flag if this code will not be reached 
if it's false?

> +        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;

Huh, so this was being checked in hls_slice_header() but never set 
before now?

>   
>       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_dependency_all_layers_flag */
> +    if (get_bits1(gb) || vps->num_direct_ref_layers[1]) {
> +        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;

These two can be variables local to ff_hevc_decode_nal_vps() instead of 
being in this struct.

> +
>       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;
>   


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

  reply	other threads:[~2025-02-06 13:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-06  3:49 Zhao Zhili
2025-02-06 13:25 ` James Almer [this message]
2025-02-06 14:28   ` Zhao Zhili

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d04f73fd-01b4-4a39-be1b-bed3b5c1b920@gmail.com \
    --to=jamrial@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git