[FFmpeg-devel] [PATCH 6/7] avcodec: allow multiple hwaccels for the same codec/pixfmt

Timo Rothenpieler timo at rothenpieler.org
Tue Oct 3 16:58:32 EEST 2017


Am 03.10.2017 um 15:15 schrieb wm4:
> 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

This seems to be truncated?

> +     */
> +    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
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3994 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20171003/7d0c0afc/attachment.bin>


More information about the ffmpeg-devel mailing list