[FFmpeg-devel] [PATCH v3 3/3] lavc/vaapi_hevc: Don't require exact profiles

Wang, Fei W fei.w.wang at intel.com
Wed Jul 10 05:02:48 EEST 2024


On Wed, 2024-06-05 at 20:59 +0100, Mark Thompson wrote:
> Rather than turning the constraint flags into a single profile and
> then
> searching for that profile (and failing if it doesn't match any
> profile
> exactly), instead search all supported profiles and use the first one
> which supports the given set of constraint flags.
> ---
>  libavcodec/vaapi_decode.c | 45 +++++++++++-------
>  libavcodec/vaapi_hevc.c   | 99 ++++++++++++++++++++++---------------
> --
>  libavcodec/vaapi_hevc.h   |  4 +-
>  3 files changed, 87 insertions(+), 61 deletions(-)

Test good for me. Thanks.

--
Fei

> 
> diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
> index 7c91d50f7b..c9d8add69f 100644
> --- a/libavcodec/vaapi_decode.c
> +++ b/libavcodec/vaapi_decode.c
> @@ -393,7 +393,9 @@ static const struct {
>      enum AVCodecID codec_id;
>      int codec_profile;
>      VAProfile va_profile;
> -    VAProfile (*profile_parser)(AVCodecContext *avctx);
> +    VAProfile (*match_profile)(AVCodecContext *avctx,
> +                               const VAProfile *profile_list,
> +                               int profile_count);
>  } vaapi_profile_map[] = {
>  #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, AV_PROFILE_ ## p,
> VAProfile ## v, __VA_ARGS__ }
>      MAP(MPEG2VIDEO,  MPEG2_SIMPLE,    MPEG2Simple ),
> @@ -420,9 +422,9 @@ static const struct {
>  #endif
>  #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
>      MAP(HEVC,        HEVC_REXT,       None,
> -                 ff_vaapi_parse_hevc_rext_scc_profile ),
> +             ff_vaapi_hevc_match_rext_scc_profile ),
>      MAP(HEVC,        HEVC_SCC,        None,
> -                 ff_vaapi_parse_hevc_rext_scc_profile ),
> +             ff_vaapi_hevc_match_rext_scc_profile ),
>  #endif
>      MAP(MJPEG,       MJPEG_HUFFMAN_BASELINE_DCT,
>                                        JPEGBaseline),
> @@ -505,22 +507,33 @@ static int
> vaapi_decode_make_config(AVCodecContext *avctx,
>              vaapi_profile_map[i].codec_profile ==
> AV_PROFILE_UNKNOWN)
>              profile_match = 1;
>  
> -        va_profile = vaapi_profile_map[i].profile_parser ?
> -                     vaapi_profile_map[i].profile_parser(avctx) :
> -                     vaapi_profile_map[i].va_profile;
>          codec_profile = vaapi_profile_map[i].codec_profile;
> -
> -        for (j = 0; j < profile_count; j++) {
> -            if (va_profile == profile_list[j]) {
> -                exact_match = profile_match;
> +        if (vaapi_profile_map[i].match_profile) {
> +            va_profile =
> +                vaapi_profile_map[i].match_profile(avctx,
> profile_list,
> +                                                   profile_count);
> +            if (va_profile != VAProfileNone) {
> +                matched_va_profile = va_profile;
> +                matched_ff_profile = codec_profile;
> +                exact_match = 1;
>                  break;
>              }
> -        }
> -        if (j < profile_count) {
> -            matched_va_profile = va_profile;
> -            matched_ff_profile = codec_profile;
> -            if (exact_match)
> -                break;
> +        } else {
> +            va_profile = vaapi_profile_map[i].va_profile;
> +
> +            for (j = 0; j < profile_count; j++) {
> +                if (va_profile == profile_list[j]) {
> +                    exact_match = profile_match;
> +                    break;
> +                }
> +            }
> +
> +            if (j < profile_count) {
> +                matched_va_profile = va_profile;
> +                matched_ff_profile = codec_profile;
> +                if (exact_match)
> +                    break;
> +            }
>          }
>      }
>      av_freep(&profile_list);
> diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
> index 6164a1d223..716a4a4b43 100644
> --- a/libavcodec/vaapi_hevc.c
> +++ b/libavcodec/vaapi_hevc.c
> @@ -589,63 +589,74 @@ static int ptl_convert(const PTLCommon
> *general_ptl, H265RawProfileTierLevel *h2
>  }
>  
>  /*
> - * Find exact va_profile for HEVC Range Extension and Screen Content
> Coding Extension
> + * Find compatible va_profile for HEVC Range Extension and Screen
> + * Content Coding Extension profiles.
>   */
> -VAProfile ff_vaapi_parse_hevc_rext_scc_profile(AVCodecContext
> *avctx)
> +VAProfile ff_vaapi_hevc_match_rext_scc_profile(AVCodecContext
> *avctx,
> +                                               const VAProfile
> *profile_list,
> +                                               int profile_count)
>  {
>      const HEVCContext *h = avctx->priv_data;
>      const HEVCSPS *sps = h->ps.sps;
>      const PTL *ptl = &sps->ptl;
>      const PTLCommon *general_ptl = &ptl->general_ptl;
> -    const H265ProfileDescriptor *profile;
>      H265RawProfileTierLevel h265_raw_ptl = {0};
>  
> +    static const struct {
> +        enum H265Profile profile;
> +        VAProfile     va_profile;
> +    } map[] = {
> +#if VA_CHECK_VERSION(1, 2, 0)
> +        { H265_PROFILE_MAIN_12,
> +          VAProfileHEVCMain12 },
> +        { H265_PROFILE_MAIN_422_10,
> +          VAProfileHEVCMain422_10 },
> +        { H265_PROFILE_MAIN_422_12,
> +          VAProfileHEVCMain422_12 },
> +        { H265_PROFILE_MAIN_444,
> +          VAProfileHEVCMain444 },
> +        { H265_PROFILE_MAIN_444_10,
> +          VAProfileHEVCMain444_10 },
> +        { H265_PROFILE_MAIN_444_12,
> +          VAProfileHEVCMain444_12 },
> +        { H265_PROFILE_SCREEN_EXTENDED_MAIN,
> +          VAProfileHEVCSccMain },
> +        { H265_PROFILE_SCREEN_EXTENDED_MAIN_10,
> +          VAProfileHEVCSccMain10 },
> +        { H265_PROFILE_SCREEN_EXTENDED_MAIN_444,
> +          VAProfileHEVCSccMain444 },
> +#endif
> +#if VA_CHECK_VERSION(1, 8, 0)
> +        { H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10,
> +          VAProfileHEVCSccMain444_10 },
> +#endif
> +    };
> +
>      /* convert PTLCommon to H265RawProfileTierLevel */
>      ptl_convert(general_ptl, &h265_raw_ptl);
>  
> -    profile = ff_h265_find_profile(&h265_raw_ptl);
> -    if (!profile) {
> -        av_log(avctx, AV_LOG_WARNING, "HEVC profile is not
> found.\n");
> -        goto end;
> -    } else {
> -        av_log(avctx, AV_LOG_VERBOSE, "HEVC profile %s is found.\n",
> profile->name);
> +    for (int i = 0; i < FF_ARRAY_ELEMS(map); i++) {
> +        int available = 0;
> +        for (int j = 0; j < profile_count; j++) {
> +            if (profile_list[j] == map[i].va_profile) {
> +                available = 1;
> +                break;
> +            }
> +        }
> +        if (!available)
> +            continue;
> +
> +        if (ff_h265_profile_compatible(&h265_raw_ptl,
> +                                       map[i].profile)) {
> +            const H265ProfileDescriptor *profile_desc =
> +                ff_h265_get_profile(map[i].profile);
> +            av_log(avctx, AV_LOG_VERBOSE,
> +                   "Decoding with HEVC profile %s.\n",
> +                   profile_desc->name);
> +            return map[i].va_profile;
> +        }
>      }
>  
> -#if VA_CHECK_VERSION(1, 2, 0)
> -    if (!strcmp(profile->name, "Main 12") ||
> -        !strcmp(profile->name, "Main 12 Intra"))
> -        return VAProfileHEVCMain12;
> -    else if (!strcmp(profile->name, "Main 4:2:2 10") ||
> -        !strcmp(profile->name, "Main 4:2:2 10 Intra"))
> -        return VAProfileHEVCMain422_10;
> -    else if (!strcmp(profile->name, "Main 4:2:2 12") ||
> -        !strcmp(profile->name, "Main 4:2:2 12 Intra"))
> -        return VAProfileHEVCMain422_12;
> -    else if (!strcmp(profile->name, "Main 4:4:4") ||
> -             !strcmp(profile->name, "Main 4:4:4 Intra"))
> -        return VAProfileHEVCMain444;
> -    else if (!strcmp(profile->name, "Main 4:4:4 10") ||
> -             !strcmp(profile->name, "Main 4:4:4 10 Intra"))
> -        return VAProfileHEVCMain444_10;
> -    else if (!strcmp(profile->name, "Main 4:4:4 12") ||
> -             !strcmp(profile->name, "Main 4:4:4 12 Intra"))
> -        return VAProfileHEVCMain444_12;
> -    else if (!strcmp(profile->name, "Screen-Extended Main"))
> -        return VAProfileHEVCSccMain;
> -    else if (!strcmp(profile->name, "Screen-Extended Main 10"))
> -        return VAProfileHEVCSccMain10;
> -    else if (!strcmp(profile->name, "Screen-Extended Main 4:4:4"))
> -        return VAProfileHEVCSccMain444;
> -#if VA_CHECK_VERSION(1, 8, 0)
> -    else if (!strcmp(profile->name, "Screen-Extended Main 4:4:4
> 10"))
> -        return VAProfileHEVCSccMain444_10;
> -#endif
> -#else
> -    av_log(avctx, AV_LOG_WARNING, "HEVC profile %s is "
> -           "not supported with this VA version.\n", profile->name);
> -#endif
> -
> -end:
>      if (avctx->hwaccel_flags &
> AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) {
>          // Default to selecting Main profile if profile mismatch is
> allowed
>          return VAProfileHEVCMain;
> diff --git a/libavcodec/vaapi_hevc.h b/libavcodec/vaapi_hevc.h
> index 449635d0d7..455c68e6ba 100644
> --- a/libavcodec/vaapi_hevc.h
> +++ b/libavcodec/vaapi_hevc.h
> @@ -22,6 +22,8 @@
>  #include <va/va.h>
>  #include "avcodec.h"
>  
> -VAProfile ff_vaapi_parse_hevc_rext_scc_profile(AVCodecContext
> *avctx);
> +VAProfile ff_vaapi_hevc_match_rext_scc_profile(AVCodecContext
> *avctx,
> +                                               const VAProfile
> *profile_list,
> +                                               int profile_count);
>  
>  #endif /* AVCODEC_VAAPI_HEVC_H */



More information about the ffmpeg-devel mailing list