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 */ _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".