[FFmpeg-devel] [PATCH 6/7] avcodec: allow multiple hwaccels for the same codec/pixfmt
Philip Langdale
philipl at overt.org
Tue Oct 3 17:23:38 EEST 2017
On Tue, 3 Oct 2017 15:15:17 +0200
wm4 <nfxjfg at googlemail.com> wrote:
> Currently, AVHWAccels are looked up using a (codec_id, pixfmt) tuple.
> This means it's impossible to have 2 decoders for the same codec and
> using the same opaque hardware pixel format.
>
> This breaks merging Libav's CUVID hwaccel. FFmpeg has its own CUVID
> support, but it's a full stream decoder, using NVIDIA's codec parser.
> The Libav one is a true hwaccel, which is based on the builtin
> software decoders.
>
> Fix this by introducing another field to disambiguate AVHWAccels, and
> use it for our CUVID decoders. FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS
> makes this mechanism backwards compatible and optional.
> ---
> libavcodec/Makefile | 1 +
> libavcodec/avcodec.h | 5 +++++
> libavcodec/cuviddec.c | 2 ++
> libavcodec/decode.c | 12 ++++++++----
> libavcodec/internal.h | 5 +++++
> 5 files changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index fa3ab8f08a..3e0d654541 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -820,6 +820,7 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) +=
> adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) +=
> adpcmenc.o adpcm_data.o
> # hardware accelerators
> +OBJS-$(CONFIG_CUVID) += cuvid.o
> OBJS-$(CONFIG_D3D11VA) += dxva2.o
> OBJS-$(CONFIG_DXVA2) += dxva2.o
> OBJS-$(CONFIG_VAAPI) += vaapi_decode.o
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 52cc5b0ca0..ecc49e5643 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -4000,6 +4000,11 @@ typedef struct AVHWAccel {
> * Internal hwaccel capabilities.
> */
> int caps_internal;
> +
> + /**
> + * Some hwaccels are ambiguous if only
> + */
> + 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 668ef9667f..7060f6a3b7 100644
> --- a/libavcodec/decode.c
> +++ b/libavcodec/decode.c
> @@ -1152,15 +1152,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->av_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;
> }
>
> @@ -1168,7 +1172,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 faa923c11f..0177ea6521 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
Looks fine. Nothing beyond what Timo said.
--phil
More information about the ffmpeg-devel
mailing list