mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec: allow multiple hwaccels for the same codec/pixfmt
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.
This commit is contained in:
parent
5593049466
commit
ae5046e492
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue