vaapi: Implement device-only setup
In this case, the user only supplies a device and the frame context is allocated internally by lavc. (cherry picked from commit 5dd9a4b88b287bf8c93520afda7becb1ad0d1894)
This commit is contained in:
		
							parent
							
								
									6ff3da4f6a
								
							
						
					
					
						commit
						81b7deab82
					
				@ -18,6 +18,7 @@
 | 
			
		||||
 | 
			
		||||
#include "libavutil/avassert.h"
 | 
			
		||||
#include "libavutil/common.h"
 | 
			
		||||
#include "libavutil/pixdesc.h"
 | 
			
		||||
 | 
			
		||||
#include "avcodec.h"
 | 
			
		||||
#include "internal.h"
 | 
			
		||||
@ -283,6 +284,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx)
 | 
			
		||||
    const AVCodecDescriptor *codec_desc;
 | 
			
		||||
    VAProfile profile, *profile_list = NULL;
 | 
			
		||||
    int profile_count, exact_match, alt_profile;
 | 
			
		||||
    const AVPixFmtDescriptor *sw_desc, *desc;
 | 
			
		||||
 | 
			
		||||
    // Allowing a profile mismatch can be useful because streams may
 | 
			
		||||
    // over-declare their required capabilities - in particular, many
 | 
			
		||||
@ -375,7 +377,9 @@ static int vaapi_decode_make_config(AVCodecContext *avctx)
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hwconfig = av_hwdevice_hwconfig_alloc(ctx->frames->device_ref);
 | 
			
		||||
    hwconfig = av_hwdevice_hwconfig_alloc(avctx->hw_device_ctx ?
 | 
			
		||||
                                          avctx->hw_device_ctx :
 | 
			
		||||
                                          ctx->frames->device_ref);
 | 
			
		||||
    if (!hwconfig) {
 | 
			
		||||
        err = AVERROR(ENOMEM);
 | 
			
		||||
        goto fail;
 | 
			
		||||
@ -383,25 +387,78 @@ static int vaapi_decode_make_config(AVCodecContext *avctx)
 | 
			
		||||
    hwconfig->config_id = ctx->va_config;
 | 
			
		||||
 | 
			
		||||
    constraints =
 | 
			
		||||
        av_hwdevice_get_hwframe_constraints(ctx->frames->device_ref,
 | 
			
		||||
        av_hwdevice_get_hwframe_constraints(avctx->hw_device_ctx ?
 | 
			
		||||
                                            avctx->hw_device_ctx :
 | 
			
		||||
                                            ctx->frames->device_ref,
 | 
			
		||||
                                            hwconfig);
 | 
			
		||||
    if (!constraints) {
 | 
			
		||||
        // Ignore.
 | 
			
		||||
    } else {
 | 
			
		||||
        if (avctx->coded_width  < constraints->min_width  ||
 | 
			
		||||
            avctx->coded_height < constraints->min_height ||
 | 
			
		||||
            avctx->coded_width  > constraints->max_width  ||
 | 
			
		||||
            avctx->coded_height > constraints->max_height) {
 | 
			
		||||
            av_log(avctx, AV_LOG_ERROR, "Hardware does not support image "
 | 
			
		||||
                   "size %dx%d (constraints: width %d-%d height %d-%d).\n",
 | 
			
		||||
                   avctx->coded_width, avctx->coded_height,
 | 
			
		||||
                   constraints->min_width,  constraints->max_width,
 | 
			
		||||
                   constraints->min_height, constraints->max_height);
 | 
			
		||||
            err = AVERROR(EINVAL);
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
        err = AVERROR(ENOMEM);
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (avctx->coded_width  < constraints->min_width  ||
 | 
			
		||||
        avctx->coded_height < constraints->min_height ||
 | 
			
		||||
        avctx->coded_width  > constraints->max_width  ||
 | 
			
		||||
        avctx->coded_height > constraints->max_height) {
 | 
			
		||||
        av_log(avctx, AV_LOG_ERROR, "Hardware does not support image "
 | 
			
		||||
               "size %dx%d (constraints: width %d-%d height %d-%d).\n",
 | 
			
		||||
               avctx->coded_width, avctx->coded_height,
 | 
			
		||||
               constraints->min_width,  constraints->max_width,
 | 
			
		||||
               constraints->min_height, constraints->max_height);
 | 
			
		||||
        err = AVERROR(EINVAL);
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    if (!constraints->valid_sw_formats ||
 | 
			
		||||
        constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) {
 | 
			
		||||
        av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any "
 | 
			
		||||
               "usable surface formats.\n");
 | 
			
		||||
        err = AVERROR(EINVAL);
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Find the first format in the list which matches the expected
 | 
			
		||||
    // bit depth and subsampling.  If none are found (this can happen
 | 
			
		||||
    // when 10-bit streams are decoded to 8-bit surfaces, for example)
 | 
			
		||||
    // then just take the first format on the list.
 | 
			
		||||
    ctx->surface_format = constraints->valid_sw_formats[0];
 | 
			
		||||
    sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
 | 
			
		||||
    for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
 | 
			
		||||
        desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]);
 | 
			
		||||
        if (desc->nb_components != sw_desc->nb_components ||
 | 
			
		||||
            desc->log2_chroma_w != sw_desc->log2_chroma_w ||
 | 
			
		||||
            desc->log2_chroma_h != sw_desc->log2_chroma_h)
 | 
			
		||||
            continue;
 | 
			
		||||
        for (j = 0; j < desc->nb_components; j++) {
 | 
			
		||||
            if (desc->comp[j].depth != sw_desc->comp[j].depth)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (j < desc->nb_components)
 | 
			
		||||
            continue;
 | 
			
		||||
        ctx->surface_format = constraints->valid_sw_formats[i];
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Start with at least four surfaces.
 | 
			
		||||
    ctx->surface_count = 4;
 | 
			
		||||
    // Add per-codec number of surfaces used for storing reference frames.
 | 
			
		||||
    switch (avctx->codec_id) {
 | 
			
		||||
    case AV_CODEC_ID_H264:
 | 
			
		||||
    case AV_CODEC_ID_HEVC:
 | 
			
		||||
        ctx->surface_count += 16;
 | 
			
		||||
        break;
 | 
			
		||||
    case AV_CODEC_ID_VP9:
 | 
			
		||||
        ctx->surface_count += 8;
 | 
			
		||||
        break;
 | 
			
		||||
    case AV_CODEC_ID_VP8:
 | 
			
		||||
        ctx->surface_count += 3;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        ctx->surface_count += 2;
 | 
			
		||||
    }
 | 
			
		||||
    // Add an additional surface per thread is frame threading is enabled.
 | 
			
		||||
    if (avctx->active_thread_type & FF_THREAD_FRAME)
 | 
			
		||||
        ctx->surface_count += avctx->thread_count;
 | 
			
		||||
 | 
			
		||||
    av_hwframe_constraints_free(&constraints);
 | 
			
		||||
    av_freep(&hwconfig);
 | 
			
		||||
 | 
			
		||||
@ -463,13 +520,24 @@ int ff_vaapi_decode_init(AVCodecContext *avctx)
 | 
			
		||||
 | 
			
		||||
        ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
 | 
			
		||||
        ctx->hwfc   = ctx->frames->hwctx;
 | 
			
		||||
 | 
			
		||||
        ctx->device = ctx->frames->device_ctx;
 | 
			
		||||
        ctx->hwctx  = ctx->device->hwctx;
 | 
			
		||||
 | 
			
		||||
    } else if (avctx->hw_device_ctx) {
 | 
			
		||||
        ctx->device = (AVHWDeviceContext*)avctx->hw_device_ctx->data;
 | 
			
		||||
        ctx->hwctx  = ctx->device->hwctx;
 | 
			
		||||
 | 
			
		||||
        if (ctx->device->type != AV_HWDEVICE_TYPE_VAAPI) {
 | 
			
		||||
            av_log(avctx, AV_LOG_ERROR, "Device supplied for VAAPI "
 | 
			
		||||
                   "decoding must be a VAAPI device (not %d).\n",
 | 
			
		||||
                   ctx->device->type);
 | 
			
		||||
            err = AVERROR(EINVAL);
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        av_log(avctx, AV_LOG_ERROR, "A hardware frames context is "
 | 
			
		||||
               "required for VAAPI decoding.\n");
 | 
			
		||||
        av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context "
 | 
			
		||||
               "is required for VAAPI decoding.\n");
 | 
			
		||||
        err = AVERROR(EINVAL);
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
@ -488,6 +556,31 @@ int ff_vaapi_decode_init(AVCodecContext *avctx)
 | 
			
		||||
    if (err)
 | 
			
		||||
        goto fail;
 | 
			
		||||
 | 
			
		||||
    if (!avctx->hw_frames_ctx) {
 | 
			
		||||
        avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
 | 
			
		||||
        if (!avctx->hw_frames_ctx) {
 | 
			
		||||
            err = AVERROR(ENOMEM);
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
        ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
 | 
			
		||||
 | 
			
		||||
        ctx->frames->format = AV_PIX_FMT_VAAPI;
 | 
			
		||||
        ctx->frames->width  = avctx->coded_width;
 | 
			
		||||
        ctx->frames->height = avctx->coded_height;
 | 
			
		||||
 | 
			
		||||
        ctx->frames->sw_format         = ctx->surface_format;
 | 
			
		||||
        ctx->frames->initial_pool_size = ctx->surface_count;
 | 
			
		||||
 | 
			
		||||
        err = av_hwframe_ctx_init(avctx->hw_frames_ctx);
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
            av_log(avctx, AV_LOG_ERROR, "Failed to initialise internal "
 | 
			
		||||
                   "frames context: %d.\n", err);
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ctx->hwfc = ctx->frames->hwctx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
 | 
			
		||||
                          avctx->coded_width, avctx->coded_height,
 | 
			
		||||
                          VA_PROGRESSIVE,
 | 
			
		||||
 | 
			
		||||
@ -69,6 +69,9 @@ typedef struct VAAPIDecodeContext {
 | 
			
		||||
 | 
			
		||||
    AVHWFramesContext    *frames;
 | 
			
		||||
    AVVAAPIFramesContext *hwfc;
 | 
			
		||||
 | 
			
		||||
    enum AVPixelFormat    surface_format;
 | 
			
		||||
    int                   surface_count;
 | 
			
		||||
} VAAPIDecodeContext;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@
 | 
			
		||||
 | 
			
		||||
#define LIBAVCODEC_VERSION_MAJOR  57
 | 
			
		||||
#define LIBAVCODEC_VERSION_MINOR  83
 | 
			
		||||
#define LIBAVCODEC_VERSION_MICRO 101
 | 
			
		||||
#define LIBAVCODEC_VERSION_MICRO 102
 | 
			
		||||
 | 
			
		||||
#define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
 | 
			
		||||
                                               LIBAVCODEC_VERSION_MINOR, \
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user