This removes the dependency that hardware pixel formats previously had on
AVHWAccel instances, meaning only those which actually do something need
exist after this patch.
Also updates avcodec_default_get_format() to be able to choose hardware
formats if either a matching device has been supplied or no additional
external configuration is required, and avcodec_get_hw_frames_parameters()
to use the hardware config rather than searching the old hwaccel list.
The FF_CODEC_CAP_HWACCEL_REQUIRE_CLASS mechanism is deleted because it
no longer does anything (the codec already contains the pointers to the
matching hwaccels).
---
libavcodec/avcodec.h | 7 --
libavcodec/cuviddec.c | 2 -
libavcodec/decode.c | 285 +++---
libavcodec/internal.h | 11 +-
4 files changed, 208 insertions(+), 97 deletions(-)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5bbeb67a0d..fb18f46ea2 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3652,13 +3652,6 @@ typedef struct AVHWAccel {
* that avctx->hwaccel_priv_data is invalid.
*/
int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx);
-
-/**
- * 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 0e5123304a..346e54e7c6 100644
--- a/libavcodec/cuviddec.c
+++ b/libavcodec/cuviddec.c
@@ -1120,7 +1120,6 @@ static const AVCodecHWConfigInternal *cuvid_hw_configs[]
= {
.type = AVMEDIA_TYPE_VIDEO, \
.id = AV_CODEC_ID_##X, \
.pix_fmt= AV_PIX_FMT_CUDA, \
-.decoder_class = ##_cuvid_class, \
}; \
AVCodec ff_##x##_cuvid_decoder = { \
.name = #x "_cuvid", \
@@ -1135,7 +1134,6 @@ static const AVCodecHWConfigInternal *cuvid_hw_configs[]
= {
.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 a7f1e23fc2..8b2bec1ce9 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -40,6 +40,7 @@
#include "avcodec.h"
#include "bytestream.h"
#include "decode.h"
+#include "hwaccel.h"
#include "internal.h"
#include "thread.h"
@@ -1077,33 +1078,67 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx,
AVSubtitle *sub,
return ret;
}
-static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
+enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx,
+ const enum AVPixelFormat *fmt)
{
-const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
-return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
-}
-
-enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const
enum AVPixelFormat *fmt)
-{
-while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt))
-++fmt;
-return fmt[0];
-}
-
-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->decoder_class == av_class && hwaccel->id ==
avctx->codec_id
-&& hwaccel->pix_fmt == pix_fmt)
-return hwaccel;
+const AVPixFmtDescriptor *desc;
+const AVCodecHWConfig *config;
+int i, n;
+
+// If a device was supplied when the codec was opened, assume that the
+// user wants to use it.
+if (avctx->hw_device_ctx && avctx->codec->hw_configs) {
+AVHWDeviceContext *device_ctx =
+(AVHWDeviceContext*)avctx->hw_device_ctx->data;
+for (i = 0;; i++) {
+config = >codec->hw_configs[i]->public;
+if (!config)
+break;
+if (!(config->methods &
+ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
+continue;
+if (device_ctx->type != config->device_type)
+continue;
+for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) {
+if (config->pix_fmt == fmt[n])
+return fmt[n];
+}
+}
+}
+// No device or other setup, so we have to choose from things which
+// don't any other external information.
+
+// If