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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user