[FFmpeg-devel] [PATCH 2/2] lavc/vaapi_hevc: Don't require exact profiles
Xiang, Haihao
haihao.xiang at intel.com
Wed Apr 24 16:45:16 EEST 2024
On Ma, 2024-04-22 at 22:23 +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.
> ---
> This fixes decode of rext 8-bit 4:2:0; it will correctly pick Main 12 or Main
> 4:2:2 10 or Main 4:4:4 (first one available) to use as the decoding profile
> after this patch.
sw decoding and vaapi decoding might have different bits (There is the same
issue if applying Fei's patchset).
For example:
$ ffmpeg -hwaccel vaapi -f lavfi -i testsrc -vf 'format=nv12,hwupload' -c:v
hevc_vaapi -profile:v rext -vframes 30 -y out.mp4
8bit ouput if using sw decoding:
$ ffmpeg -i out.mp4 -f null -
[...]
Stream #0:0(und): Video: wrapped_avframe, yuv420p(tv, progressive), 320x240 [SAR
1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn (default)
12bit output if using vaapi decoding:
$ ffmpeg -hwaccel vaapi -i out.mp4 -f null -
[...]
Stream #0:0(und): Video: wrapped_avframe, p012le(tv, progressive), 320x240 [SAR
1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn (default)
Thanks
Haihao
>
> libavcodec/vaapi_decode.c | 45 ++++++++++++-------
> libavcodec/vaapi_hevc.c | 95 +++++++++++++++++++++------------------
> libavcodec/vaapi_hevc.h | 4 +-
> 3 files changed, 83 insertions(+), 61 deletions(-)
>
> diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
> index 21b273cd0f..f1327464f5 100644
> --- a/libavcodec/vaapi_decode.c
> +++ b/libavcodec/vaapi_decode.c
> @@ -387,7 +387,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 ),
> @@ -414,9 +416,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),
> @@ -499,22 +501,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 77f55ff8b1..28f7c9280e 100644
> --- a/libavcodec/vaapi_hevc.c
> +++ b/libavcodec/vaapi_hevc.c
> @@ -590,63 +590,70 @@ 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 {
> + int 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_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 },
> +#endif
> +#if VA_CHECK_VERSION(1, 8, 0)
> + { H265_PROFILE_SCREEN_EXTENDED_MAIN_444,
> + VAProfileHEVCSccMain444 },
> +#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