From e50f4b3b57cf66a347d13edad3edd1cd629ca4ee Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 26 May 2022 15:03:41 +0200 Subject: [PATCH] lavd: refactor a bit Factor out some code from get_format_callback. It was too complex and it may be tricky to comprehend (probe vs non-probe). Moved to from_lavc_vid_conv because it will be also used by file capture to establish UG pixel format to capture to. --- src/libavcodec/from_lavc_vid_conv.c | 62 +++++++++++++++++++++++++++++ src/libavcodec/from_lavc_vid_conv.h | 2 + src/video_decompress/libavcodec.c | 50 +++++------------------ 3 files changed, 74 insertions(+), 40 deletions(-) diff --git a/src/libavcodec/from_lavc_vid_conv.c b/src/libavcodec/from_lavc_vid_conv.c index d7480dc24..febb0d137 100644 --- a/src/libavcodec/from_lavc_vid_conv.c +++ b/src/libavcodec/from_lavc_vid_conv.c @@ -1959,6 +1959,68 @@ av_to_uv_convert_p get_av_to_uv_conversion(int av_codec, codec_t uv_codec) { return NULL; } +/** + * Returns AVPixelFormat matching *ugc. If !*ugc, finds (probes) best UltraGrid codec + * to which can be one of fmt converted and returns AV_PIX_FMT_NONE. + * + * @param[in,out] ugc if zero, probing the codec, if nonzero, only finding matching AVPixelFormat + * @retval AV_PIX_FMT_NONE if !*ugc + * @retval !=AV_PIX_FMT_NONE if *ugc is non-zero + */ +static enum AVPixelFormat get_ug_codec_to_av(const enum AVPixelFormat *fmt, codec_t *ugc, bool use_hwaccel) { + // directly mapped UG codecs + for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) { + codec_t mapped_pix_fmt = get_av_to_ug_pixfmt(*fmt_it); + if (mapped_pix_fmt != VIDEO_CODEC_NONE) { + if (*ugc == VIDEO_CODEC_NONE) { // just probing internal format + *ugc = mapped_pix_fmt; + return AV_PIX_FMT_NONE; + } + if (*ugc == mapped_pix_fmt) { + return *fmt_it; + } + } + } + bool use_native[] = { true, false }; // try native first + for (const bool *use_native_it = use_native; use_native_it != + use_native + sizeof use_native / sizeof use_native[0]; ++use_native_it) { + for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) { + //If hwaccel is not enabled skip hw accel pixfmts even if there + //are convert functions + const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(*fmt_it); + if(!use_hwaccel && fmt_desc && (fmt_desc->flags & AV_PIX_FMT_FLAG_HWACCEL)){ + continue; + } + + for (const struct av_to_uv_conversion *c = get_av_to_uv_conversions(); c->uv_codec != VIDEO_CODEC_NONE; c++) { // FFMPEG conversion needed + if (c->av_codec != *fmt_it) // this conversion is not valid + continue; + if (*ugc == VIDEO_CODEC_NONE) { // just probing internal format + if (!*use_native_it || c->native) { + *ugc = c->uv_codec; + return AV_PIX_FMT_NONE; + } + } else { + if (*ugc == c->uv_codec) { // conversion found + return *fmt_it; + } + } + } + } + } + return AV_PIX_FMT_NONE; +} + +codec_t get_best_ug_codec_to_av(const enum AVPixelFormat *fmt, bool use_hwaccel) { + codec_t c = VIDEO_CODEC_NONE; + get_ug_codec_to_av(fmt, &c, use_hwaccel); + return c; +} + +enum AVPixelFormat lavd_get_av_to_ug_codec(const enum AVPixelFormat *fmt, codec_t c, bool use_hwaccel) { + return get_ug_codec_to_av(fmt, &c, use_hwaccel); +} + #pragma GCC diagnostic pop /* vi: set expandtab sw=8: */ diff --git a/src/libavcodec/from_lavc_vid_conv.h b/src/libavcodec/from_lavc_vid_conv.h index 8763769da..23bdfeb7a 100644 --- a/src/libavcodec/from_lavc_vid_conv.h +++ b/src/libavcodec/from_lavc_vid_conv.h @@ -60,6 +60,8 @@ struct av_to_uv_conversion { av_to_uv_convert_p get_av_to_uv_conversion(int av_codec, codec_t uv_codec); const struct av_to_uv_conversion *get_av_to_uv_conversions(void); +codec_t get_best_ug_codec_to_av(const enum AVPixelFormat *fmt, bool use_hwaccel); +enum AVPixelFormat lavd_get_av_to_ug_codec(const enum AVPixelFormat *fmt, codec_t c, bool use_hwaccel); #ifdef __cplusplus } diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index a7baa92d7..48e7677f4 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -467,7 +467,7 @@ int rpi4_hwacc_init(struct AVCodecContext *s, } #endif -static enum AVPixelFormat get_format_callback(struct AVCodecContext *s __attribute__((unused)), const enum AVPixelFormat *fmt) +static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const enum AVPixelFormat *fmt) { #define SELECT_PIXFMT(pixfmt) { log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Selected pixel format: %s\n", av_get_pix_fmt_name(pixfmt)); return pixfmt; } if (log_level >= LOG_LEVEL_VERBOSE) { @@ -533,46 +533,16 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s __attribu } #endif - // directly mapped UG codecs - for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) { - codec_t mapped_pix_fmt = get_av_to_ug_pixfmt(*fmt_it); - if (mapped_pix_fmt != VIDEO_CODEC_NONE) { - if (state->out_codec == VIDEO_CODEC_NONE) { // just probing internal format - state->internal_codec = mapped_pix_fmt; - return AV_PIX_FMT_NONE; - } - if (state->out_codec == mapped_pix_fmt) { - state->internal_codec = mapped_pix_fmt; - SELECT_PIXFMT(*fmt_it); - } + if (state->out_codec == VIDEO_CODEC_NONE) { // probe + codec_t c = get_best_ug_codec_to_av(fmt, hwaccel); + if (c != VIDEO_CODEC_NONE) { + state->internal_codec = c; + return AV_PIX_FMT_NONE; } - } - bool use_native[] = { true, false }; // try native first - for (const bool *use_native_it = use_native; use_native_it != - use_native + sizeof use_native / sizeof use_native[0]; ++use_native_it) { - for (const enum AVPixelFormat *fmt_it = fmt; *fmt_it != AV_PIX_FMT_NONE; fmt_it++) { - //If hwaccel is not enabled skip hw accel pixfmts even if there - //are convert functions - const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(*fmt_it); - if(!hwaccel && fmt_desc && (fmt_desc->flags & AV_PIX_FMT_FLAG_HWACCEL)){ - continue; - } - - for (const struct av_to_uv_conversion *c = get_av_to_uv_conversions(); c->uv_codec != VIDEO_CODEC_NONE; c++) { // FFMPEG conversion needed - if (c->av_codec != *fmt_it) // this conversion is not valid - continue; - if (state->out_codec == VIDEO_CODEC_NONE) { // just probing internal format - if (!*use_native_it || c->native) { - state->internal_codec = c->uv_codec; - return AV_PIX_FMT_NONE; - } - } else { - if (state->out_codec == c->uv_codec) { // conversion found - state->internal_codec = c->uv_codec; // same as out_codec - SELECT_PIXFMT(*fmt_it); - } - } - } + } else { + enum AVPixelFormat f = lavd_get_av_to_ug_codec(fmt, state->out_codec, hwaccel); + if (f != AV_PIX_FMT_NONE) { + SELECT_PIXFMT(f); } }