diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 429d62a60a..15ca871b59 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3532,6 +3532,13 @@ typedef struct AVHWAccel { * Internal hwaccel capabilities. */ int caps_internal; + + /** + * Some hwaccels are ambiguous if only the id and pix_fmt fields are used. + * If non-NULL, the associated AVCodec must have + * FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS set. + */ + const AVClass *decoder_class; } AVHWAccel; /** diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index 2ba8e00c6a..6370348639 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -1106,6 +1106,7 @@ static const AVOption options[] = { .type = AVMEDIA_TYPE_VIDEO, \ .id = AV_CODEC_ID_##X, \ .pix_fmt = AV_PIX_FMT_CUDA, \ + .decoder_class = &x##_cuvid_class, \ }; \ AVCodec ff_##x##_cuvid_decoder = { \ .name = #x "_cuvid", \ @@ -1120,6 +1121,7 @@ static const AVOption options[] = { .receive_frame = cuvid_output_frame, \ .flush = cuvid_flush, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS, \ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \ AV_PIX_FMT_NV12, \ AV_PIX_FMT_P010, \ diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 44b874d4f8..9fdc7bb565 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1090,15 +1090,19 @@ enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const en return fmt[0]; } -static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, +static AVHWAccel *find_hwaccel(AVCodecContext *avctx, enum AVPixelFormat pix_fmt) { AVHWAccel *hwaccel = NULL; + const AVClass *av_class = + (avctx->codec->caps_internal & FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS) + ? avctx->codec->priv_class : NULL; - while ((hwaccel = av_hwaccel_next(hwaccel))) - if (hwaccel->id == codec_id + while ((hwaccel = av_hwaccel_next(hwaccel))) { + if (hwaccel->decoder_class == av_class && hwaccel->id == avctx->codec_id && hwaccel->pix_fmt == pix_fmt) return hwaccel; + } return NULL; } @@ -1106,7 +1110,7 @@ static int setup_hwaccel(AVCodecContext *avctx, const enum AVPixelFormat fmt, const char *name) { - AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt); + AVHWAccel *hwa = find_hwaccel(avctx, fmt); int ret = 0; if (!hwa) { diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 7748f09f54..948d5461c1 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -69,6 +69,11 @@ */ #define FF_CODEC_CAP_SLICE_THREAD_HAS_MF (1 << 5) +/** + * Allow only AVHWAccels which have a matching decoder_class field. + */ +#define FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS (1 << 6) + #ifdef TRACE # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) #else