On 04/05/17 07:44, wm4 wrote:
> This also adds support to avconv (which is trivial due to the new
> hwaccel API being generic enough). For now, this keeps avconv_dxva2.c as
> "dxva2-old", although it doesn't work as avconv.c can't handle multiple
> hwaccels with the same pixfmt.

Is there any reason to keep it on in avconv?  It doesn't look like it offers 
anything which isn't fully replaced.

> The new decoder setup code in dxva2.c is significantly based on work by
> Steve Lhomme <[email protected]>, but with heavy changes/rewrites.
> ---
>  Changelog                   |   1 +
>  avtools/avconv.h            |   2 +
>  avtools/avconv_opt.c        |   8 +-
>  configure                   |  12 +-
>  doc/APIchanges              |   6 +
>  libavcodec/allcodecs.c      |   5 +
>  libavcodec/dxva2.c          | 654 
> +++++++++++++++++++++++++++++++++++++++++++-
>  libavcodec/dxva2_h264.c     |  22 ++
>  libavcodec/dxva2_hevc.c     |  22 ++
>  libavcodec/dxva2_internal.h |  43 ++-
>  libavcodec/dxva2_mpeg2.c    |  22 ++
>  libavcodec/dxva2_vc1.c      |  44 +++
>  libavcodec/h264_slice.c     |   3 +-
>  libavcodec/hevcdec.c        |   3 +-
>  libavcodec/mpeg12dec.c      |   1 +
>  libavcodec/vc1dec.c         |   1 +
>  libavcodec/version.h        |   4 +-
>  libavutil/hwcontext_dxva2.h |   3 +
>  18 files changed, 844 insertions(+), 12 deletions(-)
> 
> diff --git a/Changelog b/Changelog
> index 6fd30fddb9..e44df54c93 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -15,6 +15,7 @@ version <next>:
>  - VP9 superframe split/merge bitstream filters
>  - FM Screen Capture Codec decoder
>  - ClearVideo decoder (I-frames only)
> +- support for decoding through D3D11VA in avconv
>  
>  
>  version 12:
> diff --git a/avtools/avconv.h b/avtools/avconv.h
> index 3354c50444..fe2bb313b7 100644
> --- a/avtools/avconv.h
> +++ b/avtools/avconv.h
> @@ -54,9 +54,11 @@ enum HWAccelID {
>      HWACCEL_AUTO,
>      HWACCEL_VDPAU,
>      HWACCEL_DXVA2,
> +    HWACCEL_DXVA2_OLD,
>      HWACCEL_VDA,
>      HWACCEL_QSV,
>      HWACCEL_VAAPI,
> +    HWACCEL_D3D11VA,
>  };
>  
>  typedef struct HWAccel {
> diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c
> index 9839a2269e..e2599bd4d8 100644
> --- a/avtools/avconv_opt.c
> +++ b/avtools/avconv_opt.c
> @@ -60,8 +60,14 @@ const HWAccel hwaccels[] = {
>      { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU,
>        AV_HWDEVICE_TYPE_VDPAU },
>  #endif
> +#if HAVE_D3D11VA_LIB
> +    { "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11,
> +      AV_HWDEVICE_TYPE_D3D11VA },
> +#endif
>  #if HAVE_DXVA2_LIB
> -    { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
> +    { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
> +      AV_HWDEVICE_TYPE_DXVA2},

Nit: missing space.

> +    { "dxva2-old", dxva2_init, HWACCEL_DXVA2_OLD, AV_PIX_FMT_DXVA2_VLD,
>        AV_HWDEVICE_TYPE_NONE },
>  #endif
>  #if CONFIG_VDA

(No changes at all in avconv_hw :)


> ...
> +// This must work before the decoder is created.
> +// This somehow needs to be exported to the user.
> +static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext 
> *frames_ctx)
> +{
> +    FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
> +    int surface_alignment, num_surfaces;
> +
> +    frames_ctx->format = sctx->pix_fmt;
> +
> +    /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
> +    but it causes issues for H.264 on certain AMD GPUs..... */
> +    if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO)
> +        surface_alignment = 32;
> +    /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
> +    all coding features have enough room to work with */
> +    else if (avctx->codec_id == AV_CODEC_ID_HEVC)
> +        surface_alignment = 128;
> +    else
> +        surface_alignment = 16;
> +
> +    /* 4 base work surfaces */
> +    num_surfaces = 4;
> +
> +    /* add surfaces based on number of possible refs */
> +    if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == 
> AV_CODEC_ID_HEVC)
> +        num_surfaces += 16;
> +    else
> +        num_surfaces += 2;
> +
> +    /* add extra surfaces for frame threading */
> +    if (avctx->active_thread_type & FF_THREAD_FRAME)
> +        num_surfaces += avctx->thread_count;
> +
> +    frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
> +                            AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
> +    frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
> +    frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment);
> +    frames_ctx->initial_pool_size = num_surfaces;
> +
> +    if (frames_ctx->format == AV_PIX_FMT_DXVA2_VLD) {
> +        AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
> +
> +        frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
> +    }
> +
> +    if (frames_ctx->format == AV_PIX_FMT_D3D11) {
> +        AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
> +
> +        frames_hwctx->BindFlags |= D3D11_BIND_DECODER;
> +    }
> +}
> +
> +int ff_dxva2_decode_init(AVCodecContext *avctx)
> +{
> +    FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
> +    AVHWFramesContext *frames_ctx = NULL;
> +    int ret = 0;
> +
> +    // Old API.
> +    if (avctx->hwaccel_context)
> +        return 0;
> +
> +    // (avctx->pix_fmt is not updated yet at this point)
> +    sctx->pix_fmt = avctx->hwaccel->pix_fmt;
> +
> +    if (avctx->codec_id == AV_CODEC_ID_H264 &&
> +        (avctx->profile & ~FF_PROFILE_H264_CONSTRAINED) > 
> FF_PROFILE_H264_HIGH) {
> +        av_log(avctx, AV_LOG_VERBOSE, "Unsupported H.264 profile for DXVA 
> HWAccel: %d\n",avctx->profile);
> +        return AVERROR(ENOTSUP);
> +    }
> +
> +    if (avctx->codec_id == AV_CODEC_ID_HEVC &&
> +        avctx->profile != FF_PROFILE_HEVC_MAIN && avctx->profile != 
> FF_PROFILE_HEVC_MAIN_10) {
> +        av_log(avctx, AV_LOG_VERBOSE, "Unsupported HEVC profile for DXVA 
> HWAccel: %d\n", avctx->profile);
> +        return AVERROR(ENOTSUP);
> +    }
> +
> +    if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
> +        av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a 
> hw_device_ctx needs to be set for hardware decoding.\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    if (avctx->hw_frames_ctx) {
> +        frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
> +    } else {
> +        avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
> +        if (!avctx->hw_frames_ctx)
> +            return AVERROR(ENOMEM);
> +
> +        frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
> +
> +        dxva_adjust_hwframes(avctx, frames_ctx);
> +
> +        ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
> +        if (ret < 0)
> +            goto fail;
> +    }
> +
> +    sctx->device_ctx = frames_ctx->device_ctx;
> +
> +    if (frames_ctx->format != sctx->pix_fmt ||
> +        !((sctx->pix_fmt == AV_PIX_FMT_D3D11 && CONFIG_D3D11VA) ||
> +          (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && CONFIG_DXVA2))) {
> +        av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n");
> +        ret = AVERROR(EINVAL);
> +        goto fail;
> +    }
> +
> +#if CONFIG_D3D11VA
> +    if (sctx->pix_fmt == AV_PIX_FMT_D3D11) {
> +        AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
> +        AVD3D11VAContext *d3d11_ctx = &sctx->ctx.d3d11va;
> +        HRESULT hr;
> +
> +        ret = d3d11va_create_decoder(avctx);
> +        if (ret < 0)
> +            goto fail;
> +
> +        d3d11_ctx->decoder       = sctx->d3d11_decoder;
> +        d3d11_ctx->video_context = device_hwctx->video_context;
> +        d3d11_ctx->cfg           = &sctx->d3d11_config;
> +        d3d11_ctx->surface_count = sctx->nb_d3d11_views;
> +        d3d11_ctx->surface       = sctx->d3d11_views;
> +        d3d11_ctx->workaround    = sctx->workaround;
> +        d3d11_ctx->context_mutex = INVALID_HANDLE_VALUE;
> +    }
> +#endif
> +
> +#if CONFIG_DXVA2
> +    if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
> +        AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
> +        struct dxva_context *dxva_ctx = &sctx->ctx.dxva2;
> +
> +        ret = dxva2_create_decoder(avctx);
> +        if (ret < 0)
> +            goto fail;
> +
> +        dxva_ctx->decoder       = sctx->dxva2_decoder;
> +        dxva_ctx->cfg           = &sctx->dxva2_config;
> +        dxva_ctx->surface       = frames_hwctx->surfaces;
> +        dxva_ctx->surface_count = frames_hwctx->nb_surfaces;
> +        dxva_ctx->workaround    = sctx->workaround;
> +    }
> +#endif
> +
> +    return 0;
> +
> +fail:
> +    ff_dxva2_decode_uninit(avctx);
> +    return ret;
> +}

So the user configuration we want here is replacement of the 
dxva_adjust_hwframes function?

AVCodecContext.init_hw_frames from 
<https://lists.libav.org/pipermail/libav-devel/2017-March/083133.html> looks 
like exactly this (ignoring all the other parts there) - I think we were both 
loosely agreeing to something like it but the discussion tailed off without a 
conclusion, so maybe we should reopen it now.


Rest of patch appears sensible, but I don't know enough API detail to review 
carefully.

Thanks,

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

Reply via email to