On Sat,  5 Aug 2017 23:53:11 +0100
Mark Thompson <s...@jkqxz.net> wrote:

> ---
> This is several patches squashed together to invite thoughts.
> 
> The idea here is that we add a new array of possible hardware configurations 
> to codec definitions, expressed as a hardware device type and the matching 
> pixel format.  We can then use that to set up hwaccels without any additional 
> knowledge at all, creating the appropriate device at startup and then 
> matching the format in get_format in order to use it.
> 
> This is implemented here in lavc with the H.264 decoder and then used in 
> avconv.  There is quite a bit of churn in avconv hardware setup as the choice 
> of device all moves around, but it is hopefully a bit clearer now (and less 
> likely to try to give devices to things not needing them).  "-hwaccel auto" 
> is reimplemented completely as using the first device from the codec config 
> list which can be instantiated.
> 
> 
>  avtools/avconv.c     |  57 +++++++++----
>  avtools/avconv.h     |   9 +-
>  avtools/avconv_hw.c  | 233 
> ++++++++++++++++++++++++++++++++++-----------------
>  avtools/avconv_opt.c |  41 ++++-----
>  libavcodec/avcodec.h |  23 +++++
>  libavcodec/h264dec.c |  18 ++++
>  6 files changed, 254 insertions(+), 127 deletions(-)
> 
> diff --git a/avtools/avconv.c b/avtools/avconv.c
> index 4e3ffecde..c5b440e08 100644
> --- a/avtools/avconv.c
> +++ b/avtools/avconv.c
> @@ -1631,15 +1631,6 @@ static void print_sdp(void)
>      av_freep(&avc);
>  }
>  
> -static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
> -{
> -    int i;
> -    for (i = 0; hwaccels[i].name; i++)
> -        if (hwaccels[i].pix_fmt == pix_fmt)
> -            return &hwaccels[i];
> -    return NULL;
> -}
> -
>  static enum AVPixelFormat get_format(AVCodecContext *s, const enum 
> AVPixelFormat *pix_fmts)
>  {
>      InputStream *ist = s->opaque;
> @@ -1647,17 +1638,50 @@ static enum AVPixelFormat get_format(AVCodecContext 
> *s, const enum AVPixelFormat
>      int ret;
>  
>      for (p = pix_fmts; *p != -1; p++) {
> -        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
> -        const HWAccel *hwaccel;
> +        const AVPixFmtDescriptor *desc  = av_pix_fmt_desc_get(*p);
> +        const HWAccel *hwaccel          = NULL;
> +        const AVCodecHWConfig *hwconfig = NULL;
> +        int i;
>  
>          if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
>              break;
>  
> -        hwaccel = get_hwaccel(*p);
> -        if (!hwaccel ||
> -            (ist->active_hwaccel_id && ist->active_hwaccel_id != 
> hwaccel->id) ||
> -            (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != 
> hwaccel->id))
> -            continue;
> +        if (ist->hwaccel_id == HWACCEL_GENERIC && s->codec->hw_configs) {
> +            for (i = 0;; i++) {
> +                if (s->codec->hw_configs[i].device_type == 
> AV_HWDEVICE_TYPE_NONE)
> +                    break;
> +                if (s->codec->hw_configs[i].pix_fmt == *p) {
> +                    hwconfig = &s->codec->hw_configs[i];
> +                    break;
> +                }
> +            }
> +        }
> +        if (hwconfig) {
> +            if (hwconfig->device_type != ist->hwaccel_device_type) {
> +                // Different hwaccel offered, ignore.
> +                continue;
> +            }
> +            hwaccel = &hwaccels[0];
> +        }
> +        if (!hwaccel) {
> +            int i;
> +            hwaccel = NULL;
> +            for (i = 1; hwaccels[i].name; i++) {
> +                if (hwaccels[i].pix_fmt == *p) {
> +                    hwaccel = &hwaccels[i];
> +                    break;
> +                }
> +            }
> +            if (!hwaccel) {
> +                // No hwaccel supporting this pixfmt.
> +                continue;
> +            }
> +            if (hwaccel->id != ist->hwaccel_id &&
> +                hwaccel->id != HWACCEL_AUTO) {
> +                // Does not match requested hwaccel.
> +                continue;
> +            }
> +        }
>  
>          ret = hwaccel->init(s);
>          if (ret < 0) {
> @@ -1677,7 +1701,6 @@ static enum AVPixelFormat get_format(AVCodecContext *s, 
> const enum AVPixelFormat
>                  return AV_PIX_FMT_NONE;
>          }
>  
> -        ist->active_hwaccel_id = hwaccel->id;
>          ist->hwaccel_pix_fmt   = *p;
>          break;
>      }
> diff --git a/avtools/avconv.h b/avtools/avconv.h
> index b5843fbc0..0d24c71a7 100644
> --- a/avtools/avconv.h
> +++ b/avtools/avconv.h
> @@ -52,13 +52,9 @@
>  enum HWAccelID {
>      HWACCEL_NONE = 0,
>      HWACCEL_AUTO,
> -    HWACCEL_VDPAU,
> -    HWACCEL_DXVA2,
> +    HWACCEL_GENERIC,
>      HWACCEL_VDA,
>      HWACCEL_QSV,
> -    HWACCEL_VAAPI,
> -    HWACCEL_D3D11VA,
> -    HWACCEL_CUVID,
>  };
>  
>  typedef struct HWAccel {
> @@ -66,7 +62,6 @@ typedef struct HWAccel {
>      int (*init)(AVCodecContext *s);
>      enum HWAccelID id;
>      enum AVPixelFormat pix_fmt;
> -    enum AVHWDeviceType device_type;
>  } HWAccel;
>  
>  typedef struct HWDevice {
> @@ -301,11 +296,11 @@ typedef struct InputStream {
>  
>      /* hwaccel options */
>      enum HWAccelID hwaccel_id;
> +    enum AVHWDeviceType hwaccel_device_type;
>      char  *hwaccel_device;
>      enum AVPixelFormat hwaccel_output_format;
>  
>      /* hwaccel context */
> -    enum HWAccelID active_hwaccel_id;
>      void  *hwaccel_ctx;
>      void (*hwaccel_uninit)(AVCodecContext *s);
>      int  (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags);
> diff --git a/avtools/avconv_hw.c b/avtools/avconv_hw.c
> index 36ef86692..a424e7055 100644
> --- a/avtools/avconv_hw.c
> +++ b/avtools/avconv_hw.c
> @@ -62,6 +62,31 @@ static HWDevice *hw_device_add(void)
>      return hw_devices[nb_hw_devices++];
>  }
>  
> +static char *hw_device_default_name(enum AVHWDeviceType type)
> +{
> +    // Make an automatic name of the form "type%d".  We arbitrarily
> +    // limit at 1000 anonymous devices of the same type - there is
> +    // probably something else very wrong if you get to this limit.
> +    const char *type_name = av_hwdevice_get_type_name(type);
> +    char *name;
> +    size_t index_pos;
> +    int index, index_limit = 1000;
> +    index_pos = strlen(type_name);
> +    name = av_malloc(index_pos + 4);
> +    if (!name)
> +        return NULL;
> +    for (index = 0; index < index_limit; index++) {
> +        snprintf(name, index_pos + 4, "%s%d", type_name, index);
> +        if (!hw_device_get_by_name(name))
> +            break;
> +    }
> +    if (index >= index_limit) {
> +        av_freep(&name);
> +        return NULL;
> +    }
> +    return name;
> +}
> +
>  int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
>  {
>      // "type=name:device,key=value,key2=value2"
> @@ -109,27 +134,11 @@ int hw_device_init_from_string(const char *arg, 
> HWDevice **dev_out)
>  
>          p += 1 + k;
>      } else {
> -        // Give the device an automatic name of the form "type%d".
> -        // We arbitrarily limit at 1000 anonymous devices of the same
> -        // type - there is probably something else very wrong if you
> -        // get to this limit.
> -        size_t index_pos;
> -        int index, index_limit = 1000;
> -        index_pos = strlen(type_name);
> -        name = av_malloc(index_pos + 4);
> +        name = hw_device_default_name(type);
>          if (!name) {
>              err = AVERROR(ENOMEM);
>              goto fail;
>          }
> -        for (index = 0; index < index_limit; index++) {
> -            snprintf(name, index_pos + 4, "%s%d", type_name, index);
> -            if (!hw_device_get_by_name(name))
> -                break;
> -        }
> -        if (index >= index_limit) {
> -            errmsg = "too many devices";
> -            goto invalid;
> -        }
>      }
>  
>      if (!*p) {
> @@ -212,6 +221,49 @@ fail:
>      goto done;
>  }
>  
> +static int hw_device_init_from_type(enum AVHWDeviceType type,
> +                                    const char *device,
> +                                    HWDevice **dev_out)
> +{
> +    AVBufferRef *device_ref = NULL;
> +    HWDevice *dev;
> +    char *name;
> +    int err;
> +
> +    name = hw_device_default_name(type);
> +    if (!name) {
> +        err = AVERROR(ENOMEM);
> +        goto fail;
> +    }
> +
> +    err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
> +    if (err < 0) {
> +        av_log(NULL, AV_LOG_ERROR,
> +               "Device creation failed: %d.\n", err);
> +        goto fail;
> +    }
> +
> +    dev = hw_device_add();
> +    if (!dev) {
> +        err = AVERROR(ENOMEM);
> +        goto fail;
> +    }
> +
> +    dev->name = name;
> +    dev->type = type;
> +    dev->device_ref = device_ref;
> +
> +    if (dev_out)
> +        *dev_out = dev;
> +
> +    return 0;
> +
> +fail:
> +    av_freep(&name);
> +    av_buffer_unref(&device_ref);
> +    return err;
> +}
> +
>  void hw_device_free_all(void)
>  {
>      int i;
> @@ -224,85 +276,116 @@ void hw_device_free_all(void)
>      nb_hw_devices = 0;
>  }
>  
> -static enum AVHWDeviceType hw_device_match_type_by_hwaccel(enum HWAccelID 
> hwaccel_id)
> +static HWDevice *hw_device_match_by_codec(const AVCodec *codec)
>  {
> +    enum AVHWDeviceType type;
> +    HWDevice *dev = NULL;
>      int i;
> -    if (hwaccel_id == HWACCEL_NONE)
> +    if (!codec->hw_configs)
>          return AV_HWDEVICE_TYPE_NONE;
> -    for (i = 0; hwaccels[i].name; i++) {
> -        if (hwaccels[i].id == hwaccel_id)
> -            return hwaccels[i].device_type;
> +    for (i = 0;; i++) {
> +        type = codec->hw_configs[i].device_type;
> +        if (type == AV_HWDEVICE_TYPE_NONE)
> +            break;
> +        if ((dev = hw_device_get_by_type(type)))
> +            break;
>      }
> -    return AV_HWDEVICE_TYPE_NONE;
> -}
> -
> -static enum AVHWDeviceType hw_device_match_type_in_name(const char 
> *codec_name)
> -{
> -    const char *type_name;
> -    enum AVHWDeviceType type;
> -    for (type = av_hwdevice_iterate_types(AV_HWDEVICE_TYPE_NONE);
> -         type != AV_HWDEVICE_TYPE_NONE;
> -         type = av_hwdevice_iterate_types(type)) {
> -        type_name = av_hwdevice_get_type_name(type);
> -        if (strstr(codec_name, type_name))
> -            return type;
> -    }
> -    return AV_HWDEVICE_TYPE_NONE;
> +    return dev;
>  }
>  
>  int hw_device_setup_for_decode(InputStream *ist)
>  {
>      enum AVHWDeviceType type;
> -    HWDevice *dev;
> -    const char *type_name;
> -    int err;
> +    HWDevice *dev = NULL;
> +    int err, auto_device = 0;
>  
>      if (ist->hwaccel_device) {
>          dev = hw_device_get_by_name(ist->hwaccel_device);
>          if (!dev) {
> -            char *tmp;
> -            size_t len;
> -            type = hw_device_match_type_by_hwaccel(ist->hwaccel_id);
> -            if (type == AV_HWDEVICE_TYPE_NONE) {
> -                // No match - this isn't necessarily invalid, though,
> -                // because an explicit device might not be needed or
> -                // the hwaccel setup could be handled elsewhere.
> +            if (ist->hwaccel_id == HWACCEL_AUTO) {
> +                auto_device = 1;
> +            } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
> +                type = ist->hwaccel_device_type;
> +                err = hw_device_init_from_type(type, ist->hwaccel_device,
> +                                               &dev);
> +            } else {
> +                // This will be dealt with by API-specific initialisation
> +                // (using hwaccel_device), so nothing further needed here.
>                  return 0;
>              }
> -            type_name = av_hwdevice_get_type_name(type);
> -            len = strlen(type_name) + 1 +
> -                  strlen(ist->hwaccel_device) + 1;
> -            tmp = av_malloc(len);
> -            if (!tmp)
> -                return AVERROR(ENOMEM);
> -            snprintf(tmp, len, "%s:%s", type_name, ist->hwaccel_device);
> -            err = hw_device_init_from_string(tmp, &dev);
> -            av_free(tmp);
> -            if (err < 0)
> -                return err;
>          }
>      } else {
> -        if (ist->hwaccel_id != HWACCEL_NONE)
> -            type = hw_device_match_type_by_hwaccel(ist->hwaccel_id);
> -        else
> -            type = hw_device_match_type_in_name(ist->dec->name);
> -        if (type != AV_HWDEVICE_TYPE_NONE) {
> +        if (ist->hwaccel_id == HWACCEL_AUTO) {
> +            auto_device = 1;
> +        } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
> +            type = ist->hwaccel_device_type;
>              dev = hw_device_get_by_type(type);
> +            if (!dev)
> +                err = hw_device_init_from_type(type, NULL, &dev);
> +        } else {
> +            dev = hw_device_match_by_codec(ist->dec);
>              if (!dev) {
> -                hw_device_init_from_string(av_hwdevice_get_type_name(type),
> +                // No device for this codec, but not using generic hwaccel
> +                // and therefore may well not need one - ignore.
> +                return 0;
> +            }
> +        }
> +    }
> +
> +    if (auto_device) {
> +        int i;
> +        if (!ist->dec->hw_configs) {
> +            // Decoder does not support any hardware devices.
> +            return 0;
> +        }
> +        for (i = 0; !dev; i++) {
> +            type = ist->dec->hw_configs[i].device_type;
> +            if (type == AV_HWDEVICE_TYPE_NONE)
> +                break;
> +            if ((dev = hw_device_get_by_type(type))) {
> +                av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
> +                       "hwaccel type %s with existing device %s.\n",
> +                       av_hwdevice_get_type_name(type), dev->name);
> +            }
> +        }
> +        for (i = 0; !dev; i++) {
> +            type = ist->dec->hw_configs[i].device_type;
> +            if (type == AV_HWDEVICE_TYPE_NONE)
> +                break;
> +            // Try to make a new device of this type.
> +            err = hw_device_init_from_type(type, ist->hwaccel_device,
>                                             &dev);
> +            if (err < 0) {
> +                // Can't make a device of this type.
> +                continue;
> +            }
> +            if (ist->hwaccel_device) {
> +                av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
> +                       "hwaccel type %s with new device created "
> +                       "from %s.\n", av_hwdevice_get_type_name(type),
> +                       ist->hwaccel_device);
> +            } else {
> +                av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
> +                       "hwaccel type %s with new default device.\n",
> +                       av_hwdevice_get_type_name(type));
>              }
> +        }
> +        if (dev) {
> +            ist->hwaccel_id = HWACCEL_GENERIC;
> +            ist->hwaccel_device_type = type;
>          } else {
> -            // No device required.
> +            av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
> +                   "disabled: no device found.\n");
> +            ist->hwaccel_id = HWACCEL_NONE;
>              return 0;
>          }
>      }
>  
>      if (!dev) {
> -        av_log(ist->dec_ctx, AV_LOG_WARNING, "No device available "
> -               "for decoder (device type %s for codec %s).\n",
> +        av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available "
> +               "for decoder: device type %s needed for codec %s.\n",
>                 av_hwdevice_get_type_name(type), ist->dec->name);
> -        return 0;
> +        return err;
>      }
>  
>      ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
> @@ -314,24 +397,16 @@ int hw_device_setup_for_decode(InputStream *ist)
>  
>  int hw_device_setup_for_encode(OutputStream *ost)
>  {
> -    enum AVHWDeviceType type;
>      HWDevice *dev;
>  
> -    type = hw_device_match_type_in_name(ost->enc->name);
> -    if (type != AV_HWDEVICE_TYPE_NONE) {
> -        dev = hw_device_get_by_type(type);
> -        if (!dev) {
> -            av_log(ost->enc_ctx, AV_LOG_WARNING, "No device available "
> -                   "for encoder (device type %s for codec %s).\n",
> -                   av_hwdevice_get_type_name(type), ost->enc->name);
> -            return 0;
> -        }
> +    dev = hw_device_match_by_codec(ost->enc);
> +    if (dev) {
>          ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
>          if (!ost->enc_ctx->hw_device_ctx)
>              return AVERROR(ENOMEM);
>          return 0;
>      } else {
> -        // No device required.
> +        // No device required, or no device available.
>          return 0;
>      }
>  }
> diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c
> index df693360a..f523f1566 100644
> --- a/avtools/avconv_opt.c
> +++ b/avtools/avconv_opt.c
> @@ -56,33 +56,13 @@
>  }
>  
>  const HWAccel hwaccels[] = {
> -#if HAVE_VDPAU_X11
> -    { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU,
> -      AV_HWDEVICE_TYPE_VDPAU },
> -#endif
> -#if CONFIG_D3D11VA
> -    { "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11,
> -      AV_HWDEVICE_TYPE_D3D11VA },
> -#endif
> -#if CONFIG_DXVA2
> -    { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
> -      AV_HWDEVICE_TYPE_DXVA2 },
> -#endif
> +    // Generic hwaccel must be first in this list.
> +    { "generic", hwaccel_decode_init, HWACCEL_GENERIC },
>  #if CONFIG_VDA
> -    { "vda",   vda_init,   HWACCEL_VDA,   AV_PIX_FMT_VDA,
> -      AV_HWDEVICE_TYPE_NONE },
> +    { "vda",   vda_init,   HWACCEL_VDA,   AV_PIX_FMT_VDA },
>  #endif
>  #if CONFIG_LIBMFX
> -    { "qsv",   qsv_init,   HWACCEL_QSV,   AV_PIX_FMT_QSV,
> -      AV_HWDEVICE_TYPE_NONE },
> -#endif
> -#if CONFIG_VAAPI
> -    { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI,
> -      AV_HWDEVICE_TYPE_VAAPI },
> -#endif
> -#if CONFIG_CUVID
> -    { "cuvid", hwaccel_decode_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA,
> -       AV_HWDEVICE_TYPE_CUDA },
> +    { "qsv",   qsv_init,   HWACCEL_QSV,   AV_PIX_FMT_QSV },
>  #endif
>      { 0 },
>  };
> @@ -201,9 +181,13 @@ static double parse_frame_aspect_ratio(const char *arg)
>  
>  static int show_hwaccels(void *optctx, const char *opt, const char *arg)
>  {
> +    enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
>      int i;
>  
>      printf("Supported hardware acceleration:\n");
> +    while ((type = av_hwdevice_iterate_types(type)) !=
> +           AV_HWDEVICE_TYPE_NONE)
> +        printf("%s\n", av_hwdevice_get_type_name(type));
>      for (i = 0; hwaccels[i].name; i++) {
>          printf("%s\n", hwaccels[i].name);
>      }
> @@ -623,6 +607,7 @@ static void add_input_streams(OptionsContext *o, 
> AVFormatContext *ic)
>                  else if (!strcmp(hwaccel, "auto"))
>                      ist->hwaccel_id = HWACCEL_AUTO;
>                  else {
> +                    enum AVHWDeviceType type;
>                      int i;
>                      for (i = 0; hwaccels[i].name; i++) {
>                          if (!strcmp(hwaccels[i].name, hwaccel)) {
> @@ -632,6 +617,14 @@ static void add_input_streams(OptionsContext *o, 
> AVFormatContext *ic)
>                      }
>  
>                      if (!ist->hwaccel_id) {
> +                        type = av_hwdevice_find_type_by_name(hwaccel);
> +                        if (type != AV_HWDEVICE_TYPE_NONE) {
> +                            ist->hwaccel_id = HWACCEL_GENERIC;
> +                            ist->hwaccel_device_type = type;
> +                        }
> +                    }
> +
> +                    if (!ist->hwaccel_id) {
>                          av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: 
> %s.\n",
>                                 hwaccel);
>                          av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: ");
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 847b7f139..0dafe05ec 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -35,6 +35,7 @@
>  #include "libavutil/cpu.h"
>  #include "libavutil/dict.h"
>  #include "libavutil/frame.h"
> +#include "libavutil/hwcontext.h"
>  #include "libavutil/log.h"
>  #include "libavutil/pixfmt.h"
>  #include "libavutil/rational.h"
> @@ -2771,6 +2772,19 @@ typedef struct AVProfile {
>      const char *name; ///< short name for the profile
>  } AVProfile;
>  
> +typedef struct AVCodecHWConfig {
> +    /**
> +     * A device type which can be supplied to the codec.
> +     */
> +    enum AVHWDeviceType device_type;
> +    /**
> +     * The matching hardware pixel format which the codec can produce.
> +     *
> +     * Set to AV_PIX_FMT_NONE if no hardware pixel format is available.
> +     */
> +    enum AVPixelFormat pix_fmt;
> +} AVCodecHWConfig;
> +
>  typedef struct AVCodecDefault AVCodecDefault;
>  
>  struct AVSubtitle;
> @@ -2806,6 +2820,15 @@ typedef struct AVCodec {
>      const AVClass *priv_class;              ///< AVClass for the private 
> context
>      const AVProfile *profiles;              ///< array of recognized 
> profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}
>  
> +    /**
> +     * Array of hardware configurations supported by the codec, or NULL
> +     * if no hardware supported.
> +     *
> +     * The array is terminated by a configuration with a device_type of
> +     * AV_HW_DEVICE_TYPE_NONE.
> +     */
> +    const AVCodecHWConfig *hw_configs;
> +
>      /*****************************************************************
>       * No fields below this line are part of the public API. They
>       * may not be used outside of libavcodec and can be changed and
> diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
> index 7a8293efa..0d3d87a64 100644
> --- a/libavcodec/h264dec.c
> +++ b/libavcodec/h264dec.c
> @@ -786,6 +786,24 @@ AVCodec ff_h264_decoder = {
>      .capabilities          = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ 
> AV_CODEC_CAP_DR1 |
>                               AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS 
> |
>                               AV_CODEC_CAP_FRAME_THREADS,
> +    .hw_configs            = (const AVCodecHWConfig[]) {
> +#if CONFIG_H264_CUVID_HWACCEL
> +                             { AV_HWDEVICE_TYPE_CUVID,   AV_PIX_FMT_CUVID },
> +#endif
> +#if CONFIG_H264_DXVA2_HWACCEL
> +                             { AV_HWDEVICE_TYPE_DXVA2,   AV_PIX_FMT_DXVA2 },
> +#endif
> +#if CONFIG_H264_D3D11VA_HWACCEL
> +                             { AV_HWDEVICE_TYPE_D3D11VA, AV_PIX_FMT_D3D11 },
> +#endif
> +#if CONFIG_H264_VAAPI_HWACCEL
> +                             { AV_HWDEVICE_TYPE_VAAPI,   AV_PIX_FMT_VAAPI },
> +#endif
> +#if CONFIG_H264_VDPAU_HWACCEL
> +                             { AV_HWDEVICE_TYPE_VDPAU,   AV_PIX_FMT_VDPAU },
> +#endif
> +                             { AV_HWDEVICE_TYPE_NONE },
> +                           },
>      .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE | 
> FF_CODEC_CAP_EXPORTS_CROPPING,
>      .flush                 = flush_dpb,
>      .init_thread_copy      = 
> ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),

Seems like AVHWAccel, except actually useful and much simpler. I like at
least the direction this is taking.

Eventually, I'd certainly love if get_format and identifying hwaccels
by codec/pixel format combination could be replaced by something nicer.
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to