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.
This commit is contained in:
Martin Pulec
2023-10-02 15:31:14 +02:00
parent 1c84e8d546
commit b62566ca72
5 changed files with 83 additions and 41 deletions

View File

@@ -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;

View File

@@ -56,18 +56,9 @@ extern "C" {
#include <libavutil/hwcontext.h>
#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);
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}