Quoting Mark Thompson (2017-02-02 13:54:39)
> In this case, the user only supplies a device and the frame context
> is allocated internally by lavc.
> ---
> This is identical to 2/5 in the previous version (now it supports a bit more 
> than the specified API, but irrelevantly).
> 
> 
>  libavcodec/vaapi_decode.c | 132 
> ++++++++++++++++++++++++++++++++++++++++------
>  libavcodec/vaapi_decode.h |   3 ++
>  2 files changed, 118 insertions(+), 17 deletions(-)
> 
> diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
> index 42f03ab..3ba0790 100644
> --- a/libavcodec/vaapi_decode.c
> +++ b/libavcodec/vaapi_decode.c
> @@ -18,6 +18,7 @@
>  
>  #include "libavutil/avassert.h"
>  #include "libavutil/common.h"
> +#include "libavutil/pixdesc.h"
>  
>  #include "avcodec.h"
>  #include "internal.h"
> @@ -280,6 +281,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
> @@ -373,7 +375,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;
> @@ -381,24 +385,77 @@ 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);
> @@ -462,12 +519,32 @@ int ff_vaapi_decode_init(AVCodecContext *avctx)
>          ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
>          ctx->hwfc   = ctx->frames->hwctx;
>  
> +        if (ctx->frames->format != AV_PIX_FMT_VAAPI) {
> +            av_log(avctx, AV_LOG_ERROR, "Frames supplied for VAAPI "
> +                   "decoding must be VAAPI frames (not %d).\n",
> +                   ctx->frames->format);
> +            err = AVERROR(EINVAL);
> +            goto fail;
> +        }

When does this happen? Doesn't the check in ff_get_format() catch this?

> +
>          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;
>      }
> @@ -486,6 +563,27 @@ 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);

Needs to be checked.

Otherwise looks ok.

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to