From b62566ca727a7f73b58a767d6ec607ca26bec18e Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 2 Oct 2023 15:31:14 +0200 Subject: [PATCH] lavd: advertise accelerated codesc if probed Advertise conversion to HW-accelerated codecs (eg. HW_VDPAU, RPI4_8) only if probe (which now works in the same way as regular init since HEAD^) would initialize to an accelerated codec. This would prevent situations, when eg. `--param use-hw-accel=vaapi -d gl` is used, in which case HW_VDPAU was selected as a display codec, although not intended. --- src/hwaccel_libav_common.c | 43 +++++++++++++++++++++++----- src/hwaccel_libav_common.h | 13 ++------- src/libavcodec/lavc_common.h | 8 ++++++ src/types.h | 13 ++++++++- src/video_decompress/libavcodec.c | 47 ++++++++++++++++--------------- 5 files changed, 83 insertions(+), 41 deletions(-) diff --git a/src/hwaccel_libav_common.c b/src/hwaccel_libav_common.c index 4cd82f6fc..defabee7b 100644 --- a/src/hwaccel_libav_common.c +++ b/src/hwaccel_libav_common.c @@ -49,19 +49,22 @@ #include "hwaccel_libav_common.h" #include "libavcodec/lavc_common.h" +#include "types.h" #include "utils/color_out.h" #include "utils/macros.h" -struct { +static const struct { const char *name; enum hw_accel_type type; + enum AVPixelFormat av_pixfmt; + codec_t ug_pixfmt; } accel_str_map[] = { - {"vdpau", HWACCEL_VDPAU}, - {"vaapi", HWACCEL_VAAPI}, - {"videotoolbox", HWACCEL_VIDEOTOOLBOX}, - {"rpi4", HWACCEL_RPI4}, - {"cuda", HWACCEL_CUDA}, - {"vulkan", HWACCEL_VULKAN}, + {"vdpau", HWACCEL_VDPAU, AV_PIX_FMT_VDPAU, HW_VDPAU}, + { "vaapi", HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, 0 }, + { "videotoolbox", HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, 0 }, + { "rpi4", HWACCEL_RPI4, AV_PIX_FMT_RPI4_8, RPI4_8 }, + { "cuda", HWACCEL_CUDA, AV_PIX_FMT_CUDA, 0 }, + { "vulkan", HWACCEL_VULKAN, AV_PIX_FMT_VULKAN, 0 }, }; enum hw_accel_type hw_accel_from_str(const char *str){ @@ -84,6 +87,20 @@ enum hw_accel_type hw_accel_from_str(const char *str){ return HWACCEL_NONE; } + +enum hw_accel_type +hw_accel_from_pixfmt(enum AVPixelFormat pixfmt) +{ + for (unsigned i = 0; i < sizeof accel_str_map / sizeof accel_str_map[0]; + i++) { + if (accel_str_map[i].av_pixfmt == pixfmt) { + return accel_str_map[i].type; + } + } + + return HWACCEL_NONE; +} + const char *hw_accel_to_str(enum hw_accel_type type){ for(unsigned i = 0; i < sizeof(accel_str_map) / sizeof(accel_str_map[0]); i++){ if(type == accel_str_map[i].type){ @@ -94,6 +111,18 @@ const char *hw_accel_to_str(enum hw_accel_type type){ return "unknown"; } +codec_t +hw_accel_to_ug_pixfmt(enum hw_accel_type type) +{ + for (unsigned i = 0; + i < sizeof(accel_str_map) / sizeof(accel_str_map[0]); i++) { + if (type == accel_str_map[i].type) { + return accel_str_map[i].ug_pixfmt; + } + } + return VIDEO_CODEC_NONE; +} + void hwaccel_state_init(struct hw_accel_state *hwaccel){ hwaccel->type = HWACCEL_NONE; hwaccel->copy = false; diff --git a/src/hwaccel_libav_common.h b/src/hwaccel_libav_common.h index 123a97c0f..08e017ae7 100644 --- a/src/hwaccel_libav_common.h +++ b/src/hwaccel_libav_common.h @@ -56,18 +56,9 @@ extern "C" { #include #endif -enum hw_accel_type { - HWACCEL_NONE, - HWACCEL_VDPAU, - HWACCEL_VAAPI, - HWACCEL_VIDEOTOOLBOX, - HWACCEL_RPI4, - HWACCEL_CUDA, - HWACCEL_VULKAN, - HWACCEL_COUNT -}; - +enum hw_accel_type hw_accel_from_pixfmt(enum AVPixelFormat); enum hw_accel_type hw_accel_from_str(const char *str); +codec_t hw_accel_to_ug_pixfmt(enum hw_accel_type type); const char *hw_accel_to_str(enum hw_accel_type type); /** diff --git a/src/libavcodec/lavc_common.h b/src/libavcodec/lavc_common.h index 1a383b77b..71c2dd7d9 100644 --- a/src/libavcodec/lavc_common.h +++ b/src/libavcodec/lavc_common.h @@ -92,6 +92,14 @@ enum { #define AV_CODEC_CAP_OTHER_THREADS AV_CODEC_CAP_AUTO_THREADS #endif + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 39, 100) +#define AV_PIX_FMT_VULKAN AV_PIX_FMT_NONE +#endif +#ifndef HWACC_RPI4 +#define AV_PIX_FMT_RPI4_8 AV_PIX_FMT_NONE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/src/types.h b/src/types.h index 5b0806bba..eedd925f4 100644 --- a/src/types.h +++ b/src/types.h @@ -108,13 +108,24 @@ typedef enum { VIDEO_CODEC_END = VIDEO_CODEC_COUNT } codec_t; +enum hw_accel_type { + HWACCEL_NONE, + HWACCEL_VDPAU, + HWACCEL_VAAPI, + HWACCEL_VIDEOTOOLBOX, + HWACCEL_RPI4, + HWACCEL_CUDA, + HWACCEL_VULKAN, + HWACCEL_COUNT +}; + struct pixfmt_desc { int depth; ///< bit depth; 0 means that whole struct is undefined int subsampling; ///< in 'JabA' format, eg. '4444' bool rgb; + enum hw_accel_type accel_type; }; - /** * @enum interlacing_t * Specifies interlacing mode of the frame diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index 723ee239c..e9bdf202c 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -54,6 +54,7 @@ #include "utils/misc.h" // get_cpu_core_count() #include "utils/worker.h" #include "video.h" +#include "video_codec.h" #include "video_decompress.h" #ifdef HAVE_SWSCALE @@ -573,26 +574,25 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const en static const struct{ enum AVPixelFormat pix_fmt; - enum hw_accel_type accel_type; int (*init_func)(AVCodecContext *, struct hw_accel_state *, codec_t); } accels[] = { #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 39, 100) - {AV_PIX_FMT_VULKAN, HWACCEL_VULKAN, vulkan_init}, + {AV_PIX_FMT_VULKAN, vulkan_init}, #endif #ifdef HWACC_VDPAU - {AV_PIX_FMT_VDPAU, HWACCEL_VDPAU, vdpau_init}, + {AV_PIX_FMT_VDPAU, vdpau_init}, #endif - {AV_PIX_FMT_CUDA, HWACCEL_CUDA, hwacc_cuda_init}, + {AV_PIX_FMT_CUDA, hwacc_cuda_init}, #ifdef HWACC_VAAPI - {AV_PIX_FMT_VAAPI, HWACCEL_VAAPI, vaapi_init}, + {AV_PIX_FMT_VAAPI, vaapi_init}, #endif #ifdef HAVE_MACOSX - {AV_PIX_FMT_VIDEOTOOLBOX, HWACCEL_VIDEOTOOLBOX, videotoolbox_init}, + {AV_PIX_FMT_VIDEOTOOLBOX, videotoolbox_init}, #endif #ifdef HWACC_RPI4 - {AV_PIX_FMT_RPI4_8, HWACCEL_RPI4, rpi4_hwacc_init}, + {AV_PIX_FMT_RPI4_8, rpi4_hwacc_init}, #endif - {AV_PIX_FMT_NONE, HWACCEL_NONE, NULL} + {AV_PIX_FMT_NONE, NULL} }; if (hwaccel != NULL) { @@ -607,18 +607,21 @@ static enum AVPixelFormat get_format_callback(struct AVCodecContext *s, const en : HWACCEL_NONE; for(const enum AVPixelFormat *it = fmt; *it != AV_PIX_FMT_NONE; it++){ for(unsigned i = 0; i < sizeof(accels) / sizeof(accels[0]); i++){ - if(*it == accels[i].pix_fmt && !state->block_accel[accels[i].accel_type]) - { - if(forced_hwaccel != HWACCEL_NONE && accels[i].accel_type != forced_hwaccel){ - break; - } - int ret = accels[i].init_func(s, &state->hwaccel, state->out_codec); - if(ret < 0){ - hwaccel_state_reset(&state->hwaccel); - break; - } - SELECT_PIXFMT(accels[i].pix_fmt); + if (*it != accels[i].pix_fmt || + state->block_accel[hw_accel_from_pixfmt(accels[i].pix_fmt)]) { + continue; } + if (forced_hwaccel != HWACCEL_NONE && + hw_accel_from_pixfmt(accels[i].pix_fmt) != + forced_hwaccel) { + break; + } + int ret = accels[i].init_func(s, &state->hwaccel, state->out_codec); + if(ret < 0){ + hwaccel_state_reset(&state->hwaccel); + break; + } + SELECT_PIXFMT(accels[i].pix_fmt); } } if(forced_hwaccel != HWACCEL_NONE){ @@ -1074,6 +1077,8 @@ static decompress_status libavcodec_decompress(void *state, unsigned char *dst, av_get_pix_fmt_name(s->codec_ctx->pix_fmt), av_get_pix_fmt_name(s->codec_ctx->sw_pix_fmt)); *internal_props = av_pixfmt_get_desc(s->codec_ctx->sw_pix_fmt); + internal_props->accel_type = + hw_accel_from_pixfmt(s->codec_ctx->pix_fmt); return DECODER_GOT_CODEC; } @@ -1130,9 +1135,7 @@ static void libavcodec_decompress_done(void *state) * This should be take into account existing conversions. */ static int libavcodec_decompress_get_priority(codec_t compression, struct pixfmt_desc internal, codec_t ugc) { - if (get_commandline_param("use-hw-accel") && - (((compression == H264 || compression == H265) && ugc == HW_VDPAU) || - (compression == H265 && ugc == RPI4_8))) { + if (hw_accel_to_ug_pixfmt(internal.accel_type) == ugc) { return 200; }