[FFmpeg-cvslog] D3D11va: add a Direct3D11 video decoder similar to DXVA2

Steve Lhomme git at videolan.org
Mon May 25 22:40:17 CEST 2015


ffmpeg | branch: master | Steve Lhomme <robux4 at videolabs.io> | Mon May 11 10:52:47 2015 +0200| [d8039ef8d221ea273aa4f1e62e5df21bf618c772] | committer: Luca Barbato

D3D11va: add a Direct3D11 video decoder similar to DXVA2

Signed-off-by: Luca Barbato <lu_zero at gentoo.org>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d8039ef8d221ea273aa4f1e62e5df21bf618c772
---

 Changelog                   |    1 +
 configure                   |   31 ++++++++-
 libavcodec/Makefile         |    7 ++
 libavcodec/allcodecs.c      |    5 ++
 libavcodec/d3d11va.h        |   98 ++++++++++++++++++++++++++
 libavcodec/dxva2.c          |  161 ++++++++++++++++++++++++++++++++++---------
 libavcodec/dxva2_h264.c     |  138 ++++++++++++++++++++++++++-----------
 libavcodec/dxva2_hevc.c     |  108 ++++++++++++++++++++++-------
 libavcodec/dxva2_internal.h |   32 +++++++--
 libavcodec/dxva2_mpeg2.c    |  102 +++++++++++++++++++++------
 libavcodec/dxva2_vc1.c      |  131 +++++++++++++++++++++++++++--------
 libavcodec/h264_slice.c     |    3 +
 libavcodec/hevc.c           |    3 +
 libavcodec/mpeg12dec.c      |    3 +
 libavcodec/vc1dec.c         |    3 +
 libavcodec/version.h        |    2 +-
 libavutil/pixdesc.c         |    6 ++
 libavutil/pixfmt.h          |    2 +
 libavutil/version.h         |    2 +-
 19 files changed, 682 insertions(+), 156 deletions(-)

diff --git a/Changelog b/Changelog
index 9d73449..41fe7c8 100644
--- a/Changelog
+++ b/Changelog
@@ -12,6 +12,7 @@ version <next>:
 - VP8 in Ogg demuxing
 - OpenH264 encoder wrapper
 - Support DNx100 (960x720 at 8)
+- Direct3D11-accelerated decoding
 - DXVA2-accelerated HEVC decoding
 - AAC ELD 480 decoding
 - Intel QSV-accelerated H.264 decoding
diff --git a/configure b/configure
index 5bcc2df..18280b9 100755
--- a/configure
+++ b/configure
@@ -133,6 +133,7 @@ Component options:
   --disable-faan           disable floating point AAN (I)DCT code
 
 Hardware accelerators:
+  --enable-d3d11va         enable D3D11VA code
   --enable-dxva2           enable DXVA2 code
   --enable-vaapi           enable VAAPI code
   --enable-vda             enable VDA code
@@ -1206,6 +1207,7 @@ FEATURE_LIST="
 "
 
 HWACCEL_LIST="
+    d3d11va
     dxva2
     vaapi
     vda
@@ -1396,6 +1398,7 @@ HEADERS_LIST="
     dev_video_meteor_ioctl_meteor_h
     direct_h
     dlfcn_h
+    d3d11_h
     dxva_h
     gsm_h
     io_h
@@ -1551,6 +1554,8 @@ HAVE_LIST="
     $TYPES_LIST
     atomics_native
     dos_paths
+    d3d11_cobj
+    d3d11va_lib
     dxva2_lib
     libc_msvcrt
     libdc1394_1
@@ -1965,6 +1970,7 @@ zmbv_decoder_deps="zlib"
 zmbv_encoder_deps="zlib"
 
 # hardware accelerators
+d3d11va_deps="d3d11_h dxva_h"
 dxva2_deps="dxva2api_h"
 vaapi_deps="va_va_h"
 vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads"
@@ -1975,6 +1981,8 @@ h263_vaapi_hwaccel_deps="vaapi"
 h263_vaapi_hwaccel_select="h263_decoder"
 h263_vdpau_hwaccel_deps="vdpau"
 h263_vdpau_hwaccel_select="h263_decoder"
+h264_d3d11va_hwaccel_deps="d3d11va"
+h264_d3d11va_hwaccel_select="h264_decoder"
 h264_dxva2_hwaccel_deps="dxva2"
 h264_dxva2_hwaccel_select="h264_decoder"
 h264_mmal_decoder_deps="mmal"
@@ -1990,10 +1998,14 @@ h264_vda_old_hwaccel_deps="vda"
 h264_vda_old_hwaccel_select="h264_decoder"
 h264_vdpau_hwaccel_deps="vdpau"
 h264_vdpau_hwaccel_select="h264_decoder"
+hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC"
+hevc_d3d11va_hwaccel_select="hevc_decoder"
 hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
 hevc_dxva2_hwaccel_select="hevc_decoder"
 mpeg1_vdpau_hwaccel_deps="vdpau"
 mpeg1_vdpau_hwaccel_select="mpeg1video_decoder"
+mpeg2_d3d11va_hwaccel_deps="d3d11va"
+mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder"
 mpeg2_dxva2_hwaccel_deps="dxva2"
 mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
 mpeg2_vaapi_hwaccel_deps="vaapi"
@@ -2004,12 +2016,15 @@ mpeg4_vaapi_hwaccel_deps="vaapi"
 mpeg4_vaapi_hwaccel_select="mpeg4_decoder"
 mpeg4_vdpau_hwaccel_deps="vdpau"
 mpeg4_vdpau_hwaccel_select="mpeg4_decoder"
+vc1_d3d11va_hwaccel_deps="d3d11va"
+vc1_d3d11va_hwaccel_select="vc1_decoder"
 vc1_dxva2_hwaccel_deps="dxva2"
 vc1_dxva2_hwaccel_select="vc1_decoder"
 vc1_vaapi_hwaccel_deps="vaapi"
 vc1_vaapi_hwaccel_select="vc1_decoder"
 vc1_vdpau_hwaccel_deps="vdpau"
 vc1_vdpau_hwaccel_select="vc1_decoder"
+wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel"
 wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
 wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
 wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
@@ -2288,7 +2303,7 @@ enable swscale_alpha
 enable valgrind_backtrace
 
 # By default, enable only those hwaccels that have no external dependencies.
-enable dxva2 vda vdpau
+enable d3d11va dxva2 vda vdpau
 
 # build settings
 SHFLAGS='-shared -Wl,-soname,$$(@F)'
@@ -4155,6 +4170,7 @@ check_struct windows.h "CONDITION_VARIABLE" Ptr
 
 check_header direct.h
 check_header dlfcn.h
+check_header d3d11.h
 check_header dxva.h
 check_header dxva2api.h
 check_header io.h
@@ -4372,6 +4388,15 @@ if enabled x11grab; then
     require Xfixes X11/extensions/Xfixes.h XFixesGetCursorImage -lXfixes
 fi
 
+enabled d3d11_h &&
+    check_cc <<EOF && enable d3d11_cobj
+#define _WIN32_WINNT 0x0600
+#define COBJMACROS
+#include <windows.h>
+#include <d3d11.h>
+int main(void) { ID3D11VideoDecoder *o = NULL; ID3D11VideoDecoder_Release(o); return 0; }
+EOF
+
 enabled vaapi && enabled xlib &&
     check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 &&
     enable vaapi_x11
@@ -4593,6 +4618,10 @@ check_deps $CONFIG_LIST       \
            $HAVE_LIST         \
            $ALL_COMPONENTS    \
 
+enabled_all d3d11va d3d11_cobj CoTaskMemFree &&
+    prepend avconv_libs $($ldflags_filter "-lole32") &&
+    enable d3d11va_lib
+
 enabled_all dxva2 CoTaskMemFree &&
     prepend avconv_libs $($ldflags_filter "-lole32") &&
     enable dxva2_lib
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fc8c6e9..e4ca551 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -3,6 +3,7 @@ NAME = avcodec
 HEADERS = avcodec.h                                                     \
           avfft.h                                                       \
           dv_profile.h                                                  \
+          d3d11va.h                                                     \
           dxva2.h                                                       \
           qsv.h                                                         \
           vaapi.h                                                       \
@@ -557,6 +558,7 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER)       += adpcmenc.o adpcm_data.o
 
 # hardware accelerators
+OBJS-$(CONFIG_D3D11VA)                    += dxva2.o
 OBJS-$(CONFIG_DXVA2)                      += dxva2.o
 OBJS-$(CONFIG_VAAPI)                      += vaapi.o
 OBJS-$(CONFIG_VDA)                        += vda.o
@@ -564,17 +566,21 @@ OBJS-$(CONFIG_VDPAU)                      += vdpau.o
 
 OBJS-$(CONFIG_H263_VAAPI_HWACCEL)         += vaapi_mpeg4.o
 OBJS-$(CONFIG_H263_VDPAU_HWACCEL)         += vdpau_mpeg4.o
+OBJS-$(CONFIG_H264_D3D11VA_HWACCEL)       += dxva2_h264.o
 OBJS-$(CONFIG_H264_DXVA2_HWACCEL)         += dxva2_h264.o
 OBJS-$(CONFIG_H264_VAAPI_HWACCEL)         += vaapi_h264.o
 OBJS-$(CONFIG_H264_VDA_HWACCEL)           += vda_h264.o
 OBJS-$(CONFIG_H264_VDPAU_HWACCEL)         += vdpau_h264.o
+OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL)       += dxva2_hevc.o
 OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL)         += dxva2_hevc.o
 OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL)        += vdpau_mpeg12.o
+OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL)      += dxva2_mpeg2.o
 OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL)        += dxva2_mpeg2.o
 OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL)        += vaapi_mpeg2.o
 OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL)        += vdpau_mpeg12.o
 OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL)        += vaapi_mpeg4.o
 OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL)        += vdpau_mpeg4.o
+OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL)        += dxva2_vc1.o
 OBJS-$(CONFIG_VC1_DXVA2_HWACCEL)          += dxva2_vc1.o
 OBJS-$(CONFIG_VC1_VAAPI_HWACCEL)          += vaapi_vc1.o
 OBJS-$(CONFIG_VC1_VDPAU_HWACCEL)          += vdpau_vc1.o
@@ -723,6 +729,7 @@ SKIPHEADERS                            += %_tablegen.h                  \
                                           tableprint.h                  \
                                           $(ARCH)/vp56_arith.h          \
 
+SKIPHEADERS-$(CONFIG_D3D11VA)          += d3d11va.h dxva2_internal.h
 SKIPHEADERS-$(CONFIG_DXVA2)            += dxva2.h dxva2_internal.h
 SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER)  += libschroedinger.h
 SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index d2679ad..a8b5b53 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -76,6 +76,7 @@ void avcodec_register_all(void)
     /* hardware accelerators */
     REGISTER_HWACCEL(H263_VAAPI,        h263_vaapi);
     REGISTER_HWACCEL(H263_VDPAU,        h263_vdpau);
+    REGISTER_HWACCEL(H264_D3D11VA,      h264_d3d11va);
     REGISTER_HWACCEL(H264_DXVA2,        h264_dxva2);
     REGISTER_HWACCEL(H264_MMAL,         h264_mmal);
     REGISTER_HWACCEL(H264_QSV,          h264_qsv);
@@ -83,16 +84,20 @@ void avcodec_register_all(void)
     REGISTER_HWACCEL(H264_VDA,          h264_vda);
     REGISTER_HWACCEL(H264_VDA_OLD,      h264_vda_old);
     REGISTER_HWACCEL(H264_VDPAU,        h264_vdpau);
+    REGISTER_HWACCEL(HEVC_D3D11VA,      hevc_d3d11va);
     REGISTER_HWACCEL(HEVC_DXVA2,        hevc_dxva2);
     REGISTER_HWACCEL(MPEG1_VDPAU,       mpeg1_vdpau);
+    REGISTER_HWACCEL(MPEG2_D3D11VA,     mpeg2_d3d11va);
     REGISTER_HWACCEL(MPEG2_DXVA2,       mpeg2_dxva2);
     REGISTER_HWACCEL(MPEG2_VAAPI,       mpeg2_vaapi);
     REGISTER_HWACCEL(MPEG2_VDPAU,       mpeg2_vdpau);
     REGISTER_HWACCEL(MPEG4_VAAPI,       mpeg4_vaapi);
     REGISTER_HWACCEL(MPEG4_VDPAU,       mpeg4_vdpau);
+    REGISTER_HWACCEL(VC1_D3D11VA,       vc1_d3d11va);
     REGISTER_HWACCEL(VC1_DXVA2,         vc1_dxva2);
     REGISTER_HWACCEL(VC1_VAAPI,         vc1_vaapi);
     REGISTER_HWACCEL(VC1_VDPAU,         vc1_vdpau);
+    REGISTER_HWACCEL(WMV3_D3D11VA,      wmv3_d3d11va);
     REGISTER_HWACCEL(WMV3_DXVA2,        wmv3_dxva2);
     REGISTER_HWACCEL(WMV3_VAAPI,        wmv3_vaapi);
     REGISTER_HWACCEL(WMV3_VDPAU,        wmv3_vdpau);
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h
new file mode 100644
index 0000000..2163b35
--- /dev/null
+++ b/libavcodec/d3d11va.h
@@ -0,0 +1,98 @@
+/*
+ * Direct3D11 HW acceleration
+ *
+ * copyright (c) 2009 Laurent Aimar
+ * copyright (c) 2015 Steve Lhomme
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_D3D11VA_H
+#define AVCODEC_D3D11VA_H
+
+/**
+ * @file
+ * @ingroup lavc_codec_hwaccel_d3d11va
+ * Public libavcodec D3D11VA header.
+ */
+
+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
+#include <stdint.h>
+#include <d3d11.h>
+
+/**
+ * @defgroup lavc_codec_hwaccel_d3d11va Direct3D11
+ * @ingroup lavc_codec_hwaccel
+ *
+ * @{
+ */
+
+#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards
+#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO    2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface
+
+/**
+ * This structure is used to provides the necessary configurations and data
+ * to the Direct3D11 Libav HWAccel implementation.
+ *
+ * The application must make it available as AVCodecContext.hwaccel_context.
+ */
+struct AVD3D11VAContext {
+    /**
+     * D3D11 decoder object
+     */
+    ID3D11VideoDecoder *decoder;
+
+    /**
+      * D3D11 VideoContext
+      */
+    ID3D11VideoContext *video_context;
+
+    /**
+     * D3D11 configuration used to create the decoder
+     */
+    D3D11_VIDEO_DECODER_CONFIG *cfg;
+
+    /**
+     * The number of surface in the surface array
+     */
+    unsigned surface_count;
+
+    /**
+     * The array of Direct3D surfaces used to create the decoder
+     */
+    ID3D11VideoDecoderOutputView **surface;
+
+    /**
+     * A bit field configuring the workarounds needed for using the decoder
+     */
+    uint64_t workaround;
+
+    /**
+     * Private to the Libav AVHWAccel implementation
+     */
+    unsigned report_id;
+};
+
+/**
+ * @}
+ */
+
+#endif /* AVCODEC_D3D11VA_H */
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index 9ee22c8..76a9d54 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -35,14 +35,15 @@ void *ff_dxva2_get_surface(const AVFrame *frame)
     return frame->data[3];
 }
 
-unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx,
+unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
+                                    const AVDXVAContext *ctx,
                                     const AVFrame *frame)
 {
     void *surface = ff_dxva2_get_surface(frame);
     unsigned i;
 
-    for (i = 0; i < ctx->surface_count; i++)
-        if (ctx->surface[i] == surface)
+    for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++)
+        if (DXVA_CONTEXT_SURFACE(avctx, ctx, i) == surface)
             return i;
 
     assert(0);
@@ -50,8 +51,8 @@ unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx,
 }
 
 int ff_dxva2_commit_buffer(AVCodecContext *avctx,
-                           struct dxva_context *ctx,
-                           DXVA2_DecodeBufferDesc *dsc,
+                           AVDXVAContext *ctx,
+                           DECODER_BUFFER_DESC *dsc,
                            unsigned type, const void *data, unsigned size,
                            unsigned mb_count)
 {
@@ -60,8 +61,18 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx,
     int      result;
     HRESULT hr;
 
-    hr = IDirectXVideoDecoder_GetBuffer(ctx->decoder, type,
-                                        &dxva_data, &dxva_size);
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
+                                                 D3D11VA_CONTEXT(ctx)->decoder,
+                                                 type,
+                                                 &dxva_size, &dxva_data);
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type,
+                                            &dxva_data, &dxva_size);
+#endif
     if (FAILED(hr)) {
         av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n",
                type, hr);
@@ -70,10 +81,24 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx,
     if (size <= dxva_size) {
         memcpy(dxva_data, data, size);
 
-        memset(dsc, 0, sizeof(*dsc));
-        dsc->CompressedBufferType = type;
-        dsc->DataSize             = size;
-        dsc->NumMBsInBuffer       = mb_count;
+#if CONFIG_D3D11VA
+        if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+            D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc;
+            memset(dsc11, 0, sizeof(*dsc11));
+            dsc11->BufferType           = type;
+            dsc11->DataSize             = size;
+            dsc11->NumMBsInBuffer       = mb_count;
+        }
+#endif
+#if CONFIG_DXVA2
+        if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+            DXVA2_DecodeBufferDesc *dsc2 = dsc;
+            memset(dsc2, 0, sizeof(*dsc2));
+            dsc2->CompressedBufferType = type;
+            dsc2->DataSize             = size;
+            dsc2->NumMBsInBuffer       = mb_count;
+        }
+#endif
 
         result = 0;
     } else {
@@ -81,7 +106,14 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx,
         result = -1;
     }
 
-    hr = IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type);
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type);
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type);
+#endif
     if (FAILED(hr)) {
         av_log(avctx, AV_LOG_ERROR,
                "Failed to release buffer type %u: 0x%lx\n",
@@ -95,20 +127,31 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
                               const void *pp, unsigned pp_size,
                               const void *qm, unsigned qm_size,
                               int (*commit_bs_si)(AVCodecContext *,
-                                                  DXVA2_DecodeBufferDesc *bs,
-                                                  DXVA2_DecodeBufferDesc *slice))
+                                                  DECODER_BUFFER_DESC *bs,
+                                                  DECODER_BUFFER_DESC *slice))
 {
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     unsigned               buffer_count = 0;
-    DXVA2_DecodeBufferDesc buffer[4];
-    DXVA2_DecodeExecuteParams exec = { 0 };
+    D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4];
+    DXVA2_DecodeBufferDesc          buffer2[4];
+    DECODER_BUFFER_DESC             *buffer,*buffer_slice;
     int result, runs = 0;
     HRESULT hr;
+    unsigned type;
 
     do {
-        hr = IDirectXVideoDecoder_BeginFrame(ctx->decoder,
-                                             ff_dxva2_get_surface(frame),
-                                             NULL);
+#if CONFIG_D3D11VA
+        if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+            hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder,
+                                                      ff_dxva2_get_surface(frame),
+                                                      0, NULL);
+#endif
+#if CONFIG_DXVA2
+        if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+            hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder,
+                                                 ff_dxva2_get_surface(frame),
+                                                 NULL);
+#endif
         if (hr == E_PENDING)
             av_usleep(2000);
     } while (hr == E_PENDING && ++runs < 50);
@@ -118,8 +161,20 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
         return -1;
     }
 
-    result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count],
-                                    DXVA2_PictureParametersBufferType,
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        buffer = &buffer11[buffer_count];
+        type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        buffer = &buffer2[buffer_count];
+        type = DXVA2_PictureParametersBufferType;
+    }
+#endif
+    result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
+                                    type,
                                     pp, pp_size, 0);
     if (result) {
         av_log(avctx, AV_LOG_ERROR,
@@ -129,8 +184,20 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
     buffer_count++;
 
     if (qm_size > 0) {
-        result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count],
-                                        DXVA2_InverseQuantizationMatrixBufferType,
+#if CONFIG_D3D11VA
+        if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+            buffer = &buffer11[buffer_count];
+            type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
+        }
+#endif
+#if CONFIG_DXVA2
+        if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+            buffer = &buffer2[buffer_count];
+            type = DXVA2_InverseQuantizationMatrixBufferType;
+        }
+#endif
+        result = ff_dxva2_commit_buffer(avctx, ctx, buffer,
+                                        type,
                                         qm, qm_size, 0);
         if (result) {
             av_log(avctx, AV_LOG_ERROR,
@@ -140,9 +207,22 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
         buffer_count++;
     }
 
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        buffer       = &buffer11[buffer_count + 0];
+        buffer_slice = &buffer11[buffer_count + 1];
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        buffer       = &buffer2[buffer_count + 0];
+        buffer_slice = &buffer2[buffer_count + 1];
+    }
+#endif
+
     result = commit_bs_si(avctx,
-                          &buffer[buffer_count + 0],
-                          &buffer[buffer_count + 1]);
+                          buffer,
+                          buffer_slice);
     if (result) {
         av_log(avctx, AV_LOG_ERROR,
                "Failed to add bitstream or slice control buffer\n");
@@ -154,17 +234,36 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
 
     assert(buffer_count == 1 + (qm_size > 0) + 2);
 
-    exec.NumCompBuffers      = buffer_count;
-    exec.pCompressedBuffers  = buffer;
-    exec.pExtensionData      = NULL;
-    hr = IDirectXVideoDecoder_Execute(ctx->decoder, &exec);
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context,
+                                                     D3D11VA_CONTEXT(ctx)->decoder,
+                                                     buffer_count, buffer11);
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        DXVA2_DecodeExecuteParams exec = {
+            .NumCompBuffers     = buffer_count,
+            .pCompressedBuffers = buffer2,
+            .pExtensionData     = NULL,
+        };
+        hr = IDirectXVideoDecoder_Execute(DXVA2_CONTEXT(ctx)->decoder, &exec);
+    }
+#endif
     if (FAILED(hr)) {
         av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%lx\n", hr);
         result = -1;
     }
 
 end:
-    hr = IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL);
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder);
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL);
+#endif
     if (FAILED(hr)) {
         av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%lx\n", hr);
         result = -1;
diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
index a5e9705..a4a88ce 100644
--- a/libavcodec/dxva2_h264.c
+++ b/libavcodec/dxva2_h264.c
@@ -42,7 +42,7 @@ static void fill_picture_entry(DXVA_PicEntry_H264 *pic,
     pic->bPicEntry = index | (flag << 7);
 }
 
-static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h,
+static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h,
                                     DXVA_PicParams_H264 *pp)
 {
     const H264Picture *current_picture = h->cur_pic_ptr;
@@ -51,7 +51,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context
     memset(pp, 0, sizeof(*pp));
     /* Configure current picture */
     fill_picture_entry(&pp->CurrPic,
-                       ff_dxva2_get_surface_index(ctx, current_picture->f),
+                       ff_dxva2_get_surface_index(avctx, ctx, current_picture->f),
                        h->picture_structure == PICT_BOTTOM_FIELD);
     /* Configure the set of references */
     pp->UsedForReferenceFlags  = 0;
@@ -67,7 +67,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context
         }
         if (r) {
             fill_picture_entry(&pp->RefFrameList[i],
-                               ff_dxva2_get_surface_index(ctx, r->f),
+                               ff_dxva2_get_surface_index(avctx, ctx, r->f),
                                r->long_ref != 0);
 
             if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX)
@@ -114,13 +114,13 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context
 
     pp->bit_depth_luma_minus8         = h->sps.bit_depth_luma - 8;
     pp->bit_depth_chroma_minus8       = h->sps.bit_depth_chroma - 8;
-    if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG)
+    if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG)
         pp->Reserved16Bits            = 0;
-    else if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
+    else if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
         pp->Reserved16Bits            = 0x34c;
     else
         pp->Reserved16Bits            = 3; /* FIXME is there a way to detect the right mode ? */
-    pp->StatusReportFeedbackNumber    = 1 + ctx->report_id++;
+    pp->StatusReportFeedbackNumber    = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
     pp->CurrFieldOrderCnt[0] = 0;
     if ((h->picture_structure & PICT_TOP_FIELD) &&
         current_picture->field_poc[0] != INT_MAX)
@@ -156,11 +156,11 @@ static void fill_picture_parameters(struct dxva_context *ctx, const H264Context
     //pp->SliceGroupMap[810];               /* XXX not implemented by Libav */
 }
 
-static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm)
+static void fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm)
 {
     unsigned i, j;
     memset(qm, 0, sizeof(*qm));
-    if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) {
+    if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) {
         for (i = 0; i < 6; i++)
             for (j = 0; j < 16; j++)
                 qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][j];
@@ -181,11 +181,11 @@ static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, D
     }
 }
 
-static int is_slice_short(struct dxva_context *ctx)
+static int is_slice_short(const AVCodecContext *avctx, AVDXVAContext *ctx)
 {
-    assert(ctx->cfg->ConfigBitstreamRaw == 1 ||
-           ctx->cfg->ConfigBitstreamRaw == 2);
-    return ctx->cfg->ConfigBitstreamRaw == 2;
+    assert(DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 1 ||
+           DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2);
+    return DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx) == 2;
 }
 
 static void fill_slice_short(DXVA_Slice_H264_Short *slice,
@@ -212,7 +212,7 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
 {
     const H264Context *h = avctx->priv_data;
     H264SliceContext *sl = &h->slice_ctx[0];
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     unsigned list;
 
     memset(slice, 0, sizeof(*slice));
@@ -243,10 +243,10 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
                 const H264Picture *r = sl->ref_list[list][i].parent;
                 unsigned plane;
                 unsigned index;
-                if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
-                    index = ff_dxva2_get_surface_index(ctx, r->f);
+                if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
+                    index = ff_dxva2_get_surface_index(avctx, ctx, r->f);
                 else
-                    index = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, r->f));
+                    index = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, r->f));
                 fill_picture_entry(&slice->RefPicList[list][i], index,
                                    r->reference == PICT_BOTTOM_FIELD);
                 for (plane = 0; plane < 3; plane++) {
@@ -289,12 +289,12 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
 }
 
 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
-                                             DXVA2_DecodeBufferDesc *bs,
-                                             DXVA2_DecodeBufferDesc *sc)
+                                             DECODER_BUFFER_DESC *bs,
+                                             DECODER_BUFFER_DESC *sc)
 {
     const H264Context *h = avctx->priv_data;
     const unsigned mb_count = h->mb_width * h->mb_height;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     const H264Picture *current_picture = h->cur_pic_ptr;
     struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
     DXVA_Slice_H264_Short *slice = NULL;
@@ -305,12 +305,28 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     unsigned slice_size;
     unsigned padding;
     unsigned i;
+    unsigned type;
 
     /* Create an annex B bitstream buffer with only slice NAL and finalize slice */
-    if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
-                                              DXVA2_BitStreamDateBufferType,
-                                              &dxva_data_ptr, &dxva_size)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
+        if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
+                                                       D3D11VA_CONTEXT(ctx)->decoder,
+                                                       type,
+                                                       &dxva_size, &dxva_data_ptr)))
+            return -1;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        type = DXVA2_BitStreamDateBufferType;
+        if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
+                                                  type,
+                                                  &dxva_data_ptr, &dxva_size)))
+            return -1;
+    }
+#endif
 
     dxva_data = dxva_data_ptr;
     current = dxva_data;
@@ -326,7 +342,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
         assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) ==
                offsetof(DXVA_Slice_H264_Long,  SliceBytesInBuffer));
 
-        if (is_slice_short(ctx))
+        if (is_slice_short(avctx, ctx))
             slice = &ctx_pic->slice_short[i];
         else
             slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i];
@@ -341,7 +357,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
         slice->BSNALunitDataLocation = current - dxva_data;
         slice->SliceBytesInBuffer    = start_code_size + size;
 
-        if (!is_slice_short(ctx)) {
+        if (!is_slice_short(avctx, ctx)) {
             DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice;
             if (i < ctx_pic->slice_count - 1)
                 slice_long->NumMbsForSlice =
@@ -363,18 +379,43 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
 
         slice->SliceBytesInBuffer += padding;
     }
-    if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
-                                                  DXVA2_BitStreamDateBufferType)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
     if (i < ctx_pic->slice_count)
         return -1;
 
-    memset(bs, 0, sizeof(*bs));
-    bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
-    bs->DataSize             = current - dxva_data;
-    bs->NumMBsInBuffer       = mb_count;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
+        memset(dsc11, 0, sizeof(*dsc11));
+        dsc11->BufferType           = type;
+        dsc11->DataSize             = current - dxva_data;
+        dsc11->NumMBsInBuffer       = mb_count;
 
-    if (is_slice_short(ctx)) {
+        type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        DXVA2_DecodeBufferDesc *dsc2 = bs;
+        memset(dsc2, 0, sizeof(*dsc2));
+        dsc2->CompressedBufferType = type;
+        dsc2->DataSize             = current - dxva_data;
+        dsc2->NumMBsInBuffer       = mb_count;
+
+        type = DXVA2_SliceControlBufferType;
+    }
+#endif
+
+    if (is_slice_short(avctx, ctx)) {
         slice_data = ctx_pic->slice_short;
         slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
     } else {
@@ -383,7 +424,7 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     }
     assert((bs->DataSize & 127) == 0);
     return ff_dxva2_commit_buffer(avctx, ctx, sc,
-                                  DXVA2_SliceControlBufferType,
+                                  type,
                                   slice_data, slice_size, mb_count);
 }
 
@@ -393,18 +434,20 @@ static int dxva2_h264_start_frame(AVCodecContext *avctx,
                                   av_unused uint32_t size)
 {
     const H264Context *h = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private;
 
-    if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+    if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_CFG(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_COUNT(avctx, ctx) <= 0)
         return -1;
     assert(ctx_pic);
 
     /* Fill up DXVA_PicParams_H264 */
-    fill_picture_parameters(ctx, h, &ctx_pic->pp);
+    fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp);
 
     /* Fill up DXVA_Qmatrix_H264 */
-    fill_scaling_lists(ctx, h, &ctx_pic->qm);
+    fill_scaling_lists(avctx, ctx, h, &ctx_pic->qm);
 
     ctx_pic->slice_count    = 0;
     ctx_pic->bitstream_size = 0;
@@ -418,7 +461,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx,
 {
     const H264Context *h = avctx->priv_data;
     const H264SliceContext *sl = &h->slice_ctx[0];
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     const H264Picture *current_picture = h->cur_pic_ptr;
     struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
     unsigned position;
@@ -431,7 +474,7 @@ static int dxva2_h264_decode_slice(AVCodecContext *avctx,
     ctx_pic->bitstream_size += size;
 
     position = buffer - ctx_pic->bitstream;
-    if (is_slice_short(ctx))
+    if (is_slice_short(avctx, ctx))
         fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count],
                          position, size);
     else
@@ -463,6 +506,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx)
     return ret;
 }
 
+#if CONFIG_H264_DXVA2_HWACCEL
 AVHWAccel ff_h264_dxva2_hwaccel = {
     .name           = "h264_dxva2",
     .type           = AVMEDIA_TYPE_VIDEO,
@@ -473,3 +517,17 @@ AVHWAccel ff_h264_dxva2_hwaccel = {
     .end_frame      = dxva2_h264_end_frame,
     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
 };
+#endif
+
+#if CONFIG_H264_D3D11VA_HWACCEL
+AVHWAccel ff_h264_d3d11va_hwaccel = {
+    .name           = "h264_d3d11va",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
+    .start_frame    = dxva2_h264_start_frame,
+    .decode_slice   = dxva2_h264_decode_slice,
+    .end_frame      = dxva2_h264_end_frame,
+    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
+#endif
diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
index 257bee7..9d130d9 100644
--- a/libavcodec/dxva2_hevc.c
+++ b/libavcodec/dxva2_hevc.c
@@ -53,7 +53,7 @@ static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index)
     return 0xff;
 }
 
-static void fill_picture_parameters(struct dxva_context *ctx, const HEVCContext *h,
+static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const HEVCContext *h,
                                     DXVA_PicParams_HEVC *pp)
 {
     const HEVCFrame *current_picture = h->ref;
@@ -73,7 +73,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const HEVCContext
                                       (0                                  << 14) |
                                       (0                                  << 15);
 
-    fill_picture_entry(&pp->CurrPic, ff_dxva2_get_surface_index(ctx, current_picture->frame), 0);
+    fill_picture_entry(&pp->CurrPic, ff_dxva2_get_surface_index(avctx, ctx, current_picture->frame), 0);
 
     pp->sps_max_dec_pic_buffering_minus1         = h->sps->temporal_layer[h->sps->max_sub_layers - 1].max_dec_pic_buffering - 1;
     pp->log2_min_luma_coding_block_size_minus3   = h->sps->log2_min_cb_size - 3;
@@ -165,7 +165,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const HEVCContext
     for (i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
         const HEVCFrame *frame = &h->DPB[i];
         if (frame != current_picture && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
-            fill_picture_entry(&pp->RefPicList[j], ff_dxva2_get_surface_index(ctx, frame->frame), !!(frame->flags & HEVC_FRAME_FLAG_LONG_REF));
+            fill_picture_entry(&pp->RefPicList[j], ff_dxva2_get_surface_index(avctx, ctx, frame->frame), !!(frame->flags & HEVC_FRAME_FLAG_LONG_REF));
             pp->PicOrderCntValList[j] = frame->poc;
             j++;
         }
@@ -176,7 +176,7 @@ static void fill_picture_parameters(struct dxva_context *ctx, const HEVCContext
         av_assert0(rpl->nb_refs <= FF_ARRAY_ELEMS(pp->ref_list)); \
         for (j = 0, k = 0; j < rpl->nb_refs; j++) { \
             if (rpl->ref[j]) { \
-                pp->ref_list[k] = get_refpic_index(pp, ff_dxva2_get_surface_index(ctx, rpl->ref[j]->frame)); \
+                pp->ref_list[k] = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, rpl->ref[j]->frame)); \
                 k++; \
             } \
         } \
@@ -187,10 +187,10 @@ static void fill_picture_parameters(struct dxva_context *ctx, const HEVCContext
     DO_REF_LIST(ST_CURR_AFT, RefPicSetStCurrAfter);
     DO_REF_LIST(LT_CURR, RefPicSetLtCurr);
 
-    pp->StatusReportFeedbackNumber = 1 + ctx->report_id++;
+    pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
 }
 
-static void fill_scaling_lists(struct dxva_context *ctx, const HEVCContext *h, DXVA_Qmatrix_HEVC *qm)
+static void fill_scaling_lists(AVDXVAContext *ctx, const HEVCContext *h, DXVA_Qmatrix_HEVC *qm)
 {
     unsigned i, j, pos;
     const ScalingList *sl = h->pps->scaling_list_data_present_flag ?
@@ -228,11 +228,11 @@ static void fill_slice_short(DXVA_Slice_HEVC_Short *slice,
 }
 
 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
-                                             DXVA2_DecodeBufferDesc *bs,
-                                             DXVA2_DecodeBufferDesc *sc)
+                                             DECODER_BUFFER_DESC *bs,
+                                             DECODER_BUFFER_DESC *sc)
 {
     const HEVCContext *h = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     const HEVCFrame *current_picture = h->ref;
     struct hevc_dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
     DXVA_Slice_HEVC_Short *slice = NULL;
@@ -243,12 +243,28 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     unsigned slice_size;
     unsigned padding;
     unsigned i;
+    unsigned type;
 
     /* Create an annex B bitstream buffer with only slice NAL and finalize slice */
-    if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
-                                              DXVA2_BitStreamDateBufferType,
-                                              &dxva_data_ptr, &dxva_size)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
+        if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
+                                                       D3D11VA_CONTEXT(ctx)->decoder,
+                                                       type,
+                                                       &dxva_size, &dxva_data_ptr)))
+            return -1;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        type = DXVA2_BitStreamDateBufferType;
+        if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
+                                                  type,
+                                                  &dxva_data_ptr, &dxva_size)))
+            return -1;
+    }
+#endif
 
     dxva_data = dxva_data_ptr;
     current = dxva_data;
@@ -284,23 +300,48 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
 
         slice->SliceBytesInBuffer += padding;
     }
-    if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
-                                                  DXVA2_BitStreamDateBufferType)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
     if (i < ctx_pic->slice_count)
         return -1;
 
-    memset(bs, 0, sizeof(*bs));
-    bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
-    bs->DataSize             = current - dxva_data;
-    bs->NumMBsInBuffer       = 0;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
+        memset(dsc11, 0, sizeof(*dsc11));
+        dsc11->BufferType           = type;
+        dsc11->DataSize             = current - dxva_data;
+        dsc11->NumMBsInBuffer       = 0;
+
+        type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        DXVA2_DecodeBufferDesc *dsc2 = bs;
+        memset(dsc2, 0, sizeof(*dsc2));
+        dsc2->CompressedBufferType = type;
+        dsc2->DataSize             = current - dxva_data;
+        dsc2->NumMBsInBuffer       = 0;
+
+        type = DXVA2_SliceControlBufferType;
+    }
+#endif
 
     slice_data = ctx_pic->slice_short;
     slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
 
-    av_assert0((bs->DataSize & 127) == 0);
+    av_assert0(((current - dxva_data) & 127) == 0);
     return ff_dxva2_commit_buffer(avctx, ctx, sc,
-                                  DXVA2_SliceControlBufferType,
+                                  type,
                                   slice_data, slice_size, 0);
 }
 
@@ -310,15 +351,17 @@ static int dxva2_hevc_start_frame(AVCodecContext *avctx,
                                   av_unused uint32_t size)
 {
     const HEVCContext *h = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     struct hevc_dxva2_picture_context *ctx_pic = h->ref->hwaccel_picture_private;
 
-    if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+    if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_CFG(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_COUNT(avctx, ctx) <= 0)
         return -1;
     av_assert0(ctx_pic);
 
     /* Fill up DXVA_PicParams_HEVC */
-    fill_picture_parameters(ctx, h, &ctx_pic->pp);
+    fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp);
 
     /* Fill up DXVA_Qmatrix_HEVC */
     fill_scaling_lists(ctx, h, &ctx_pic->qm);
@@ -369,6 +412,7 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx)
     return ret;
 }
 
+#if CONFIG_HEVC_DXVA2_HWACCEL
 AVHWAccel ff_hevc_dxva2_hwaccel = {
     .name           = "hevc_dxva2",
     .type           = AVMEDIA_TYPE_VIDEO,
@@ -379,3 +423,17 @@ AVHWAccel ff_hevc_dxva2_hwaccel = {
     .end_frame      = dxva2_hevc_end_frame,
     .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
 };
+#endif
+
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+AVHWAccel ff_hevc_d3d11va_hwaccel = {
+    .name           = "hevc_d3d11va",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_HEVC,
+    .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
+    .start_frame    = dxva2_hevc_start_frame,
+    .decode_slice   = dxva2_hevc_decode_slice,
+    .end_frame      = dxva2_hevc_end_frame,
+    .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
+};
+#endif
diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
index b775e6c..23be2c3 100644
--- a/libavcodec/dxva2_internal.h
+++ b/libavcodec/dxva2_internal.h
@@ -28,6 +28,7 @@
 #include "config.h"
 
 #include "dxva2.h"
+#include "d3d11va.h"
 #if HAVE_DXVA_H
 #include <dxva.h>
 #endif
@@ -35,13 +36,34 @@
 #include "avcodec.h"
 #include "mpegvideo.h"
 
+typedef void DECODER_BUFFER_DESC;
+
+typedef union {
+    struct AVD3D11VAContext  d3d11va;
+    struct dxva_context      dxva2;
+} AVDXVAContext;
+
+#define D3D11VA_CONTEXT(ctx) (&ctx->d3d11va)
+#define DXVA2_CONTEXT(ctx)   (&ctx->dxva2)
+
+#define DXVA_CONTEXT_WORKAROUND(avctx, ctx)     (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.workaround : ctx->dxva2.workaround)
+#define DXVA_CONTEXT_COUNT(avctx, ctx)          (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.surface_count : ctx->dxva2.surface_count)
+#define DXVA_CONTEXT_SURFACE(avctx, ctx, i)     (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.surface[i] : ctx->dxva2.surface[i])
+#define DXVA_CONTEXT_DECODER(avctx, ctx)        (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.decoder : ctx->dxva2.decoder)
+#define DXVA_CONTEXT_REPORT_ID(avctx, ctx)      (*(avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? &ctx->d3d11va.report_id : &ctx->dxva2.report_id))
+#define DXVA_CONTEXT_CFG(avctx, ctx)            (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg : ctx->dxva2.cfg)
+#define DXVA_CONTEXT_CFG_BITSTREAM(avctx, ctx)  (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigBitstreamRaw : ctx->dxva2.cfg->ConfigBitstreamRaw)
+#define DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigIntraResidUnsigned : ctx->dxva2.cfg->ConfigIntraResidUnsigned)
+#define DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ? ctx->d3d11va.cfg->ConfigResidDiffAccelerator : ctx->dxva2.cfg->ConfigResidDiffAccelerator)
+
 void *ff_dxva2_get_surface(const AVFrame *frame);
 
-unsigned ff_dxva2_get_surface_index(const struct dxva_context *,
+unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
+                                    const AVDXVAContext *,
                                     const AVFrame *frame);
 
-int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *,
-                           DXVA2_DecodeBufferDesc *,
+int ff_dxva2_commit_buffer(AVCodecContext *, AVDXVAContext *,
+                           DECODER_BUFFER_DESC *,
                            unsigned type, const void *data, unsigned size,
                            unsigned mb_count);
 
@@ -50,7 +72,7 @@ int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *,
                               const void *pp, unsigned pp_size,
                               const void *qm, unsigned qm_size,
                               int (*commit_bs_si)(AVCodecContext *,
-                                                  DXVA2_DecodeBufferDesc *bs,
-                                                  DXVA2_DecodeBufferDesc *slice));
+                                                  DECODER_BUFFER_DESC *bs,
+                                                  DECODER_BUFFER_DESC *slice));
 
 #endif /* AVCODEC_DXVA_INTERNAL_H */
diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c
index 65624e3..99a0787 100644
--- a/libavcodec/dxva2_mpeg2.c
+++ b/libavcodec/dxva2_mpeg2.c
@@ -36,7 +36,7 @@ struct dxva2_picture_context {
 };
 
 static void fill_picture_parameters(AVCodecContext *avctx,
-                                    struct dxva_context *ctx,
+                                    AVDXVAContext *ctx,
                                     const struct MpegEncContext *s,
                                     DXVA_PictureParameters *pp)
 {
@@ -44,14 +44,14 @@ static void fill_picture_parameters(AVCodecContext *avctx,
     int is_field = s->picture_structure != PICT_FRAME;
 
     memset(pp, 0, sizeof(*pp));
-    pp->wDecodedPictureIndex         = ff_dxva2_get_surface_index(ctx, current_picture->f);
+    pp->wDecodedPictureIndex         = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f);
     pp->wDeblockedPictureIndex       = 0;
     if (s->pict_type != AV_PICTURE_TYPE_I)
-        pp->wForwardRefPictureIndex  = ff_dxva2_get_surface_index(ctx, s->last_picture.f);
+        pp->wForwardRefPictureIndex  = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f);
     else
         pp->wForwardRefPictureIndex  = 0xffff;
     if (s->pict_type == AV_PICTURE_TYPE_B)
-        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f);
+        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f);
     else
         pp->wBackwardRefPictureIndex = 0xffff;
     pp->wPicWidthInMBminus1          = s->mb_width  - 1;
@@ -102,7 +102,7 @@ static void fill_picture_parameters(AVCodecContext *avctx,
 }
 
 static void fill_quantization_matrices(AVCodecContext *avctx,
-                                       struct dxva_context *ctx,
+                                       AVDXVAContext *ctx,
                                        const struct MpegEncContext *s,
                                        DXVA_QmatrixData *qm)
 {
@@ -147,11 +147,11 @@ static void fill_slice(AVCodecContext *avctx,
     slice->wMBbitOffset        = 4 * 8 + get_bits_count(&gb);
 }
 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
-                                             DXVA2_DecodeBufferDesc *bs,
-                                             DXVA2_DecodeBufferDesc *sc)
+                                             DECODER_BUFFER_DESC *bs,
+                                             DECODER_BUFFER_DESC *sc)
 {
     const struct MpegEncContext *s = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     struct dxva2_picture_context *ctx_pic =
         s->current_picture_ptr->hwaccel_picture_private;
     const int is_field = s->picture_structure != PICT_FRAME;
@@ -160,11 +160,27 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     uint8_t  *dxva_data, *current, *end;
     unsigned dxva_size;
     unsigned i;
+    unsigned type;
 
-    if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
-                                              DXVA2_BitStreamDateBufferType,
-                                              &dxva_data_ptr, &dxva_size)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
+        if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
+                                                       D3D11VA_CONTEXT(ctx)->decoder,
+                                                       type,
+                                                       &dxva_size, &dxva_data_ptr)))
+            return -1;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        type = DXVA2_BitStreamDateBufferType;
+        if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
+                                                  type,
+                                                  &dxva_data_ptr, &dxva_size)))
+            return -1;
+    }
+#endif
 
     dxva_data = dxva_data_ptr;
     current = dxva_data;
@@ -190,19 +206,44 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
         memcpy(current, &ctx_pic->bitstream[position], size);
         current += size;
     }
-    if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
-                                                  DXVA2_BitStreamDateBufferType)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
     if (i < ctx_pic->slice_count)
         return -1;
 
-    memset(bs, 0, sizeof(*bs));
-    bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
-    bs->DataSize             = current - dxva_data;
-    bs->NumMBsInBuffer       = mb_count;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
+        memset(dsc11, 0, sizeof(*dsc11));
+        dsc11->BufferType           = type;
+        dsc11->DataSize             = current - dxva_data;
+        dsc11->NumMBsInBuffer       = mb_count;
+
+        type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        DXVA2_DecodeBufferDesc *dsc2 = bs;
+        memset(dsc2, 0, sizeof(*dsc2));
+        dsc2->CompressedBufferType = type;
+        dsc2->DataSize             = current - dxva_data;
+        dsc2->NumMBsInBuffer       = mb_count;
+
+        type = DXVA2_SliceControlBufferType;
+    }
+#endif
 
     return ff_dxva2_commit_buffer(avctx, ctx, sc,
-                                  DXVA2_SliceControlBufferType,
+                                  type,
                                   ctx_pic->slice,
                                   ctx_pic->slice_count * sizeof(*ctx_pic->slice),
                                   mb_count);
@@ -213,11 +254,13 @@ static int dxva2_mpeg2_start_frame(AVCodecContext *avctx,
                                    av_unused uint32_t size)
 {
     const struct MpegEncContext *s = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     struct dxva2_picture_context *ctx_pic =
         s->current_picture_ptr->hwaccel_picture_private;
 
-    if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+    if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_CFG(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_COUNT(avctx, ctx) <= 0)
         return -1;
     assert(ctx_pic);
 
@@ -271,6 +314,7 @@ static int dxva2_mpeg2_end_frame(AVCodecContext *avctx)
     return ret;
 }
 
+#if CONFIG_MPEG2_DXVA2_HWACCEL
 AVHWAccel ff_mpeg2_dxva2_hwaccel = {
     .name           = "mpeg2_dxva2",
     .type           = AVMEDIA_TYPE_VIDEO,
@@ -281,3 +325,17 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = {
     .end_frame      = dxva2_mpeg2_end_frame,
     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
 };
+#endif
+
+#if CONFIG_MPEG2_D3D11VA_HWACCEL
+AVHWAccel ff_mpeg2_d3d11va_hwaccel = {
+    .name           = "mpeg2_d3d11va",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_MPEG2VIDEO,
+    .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
+    .start_frame    = dxva2_mpeg2_start_frame,
+    .decode_slice   = dxva2_mpeg2_decode_slice,
+    .end_frame      = dxva2_mpeg2_end_frame,
+    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
+#endif
diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c
index 1524b51..73f9fb4 100644
--- a/libavcodec/dxva2_vc1.c
+++ b/libavcodec/dxva2_vc1.c
@@ -34,7 +34,7 @@ struct dxva2_picture_context {
 };
 
 static void fill_picture_parameters(AVCodecContext *avctx,
-                                    struct dxva_context *ctx, const VC1Context *v,
+                                    AVDXVAContext *ctx, const VC1Context *v,
                                     DXVA_PictureParameters *pp)
 {
     const MpegEncContext *s = &v->s;
@@ -42,13 +42,13 @@ static void fill_picture_parameters(AVCodecContext *avctx,
 
     memset(pp, 0, sizeof(*pp));
     pp->wDecodedPictureIndex    =
-    pp->wDeblockedPictureIndex  = ff_dxva2_get_surface_index(ctx, current_picture->f);
+    pp->wDeblockedPictureIndex  = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f);
     if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type)
-        pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->last_picture.f);
+        pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f);
     else
         pp->wForwardRefPictureIndex = 0xffff;
     if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type)
-        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, s->next_picture.f);
+        pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f);
     else
         pp->wBackwardRefPictureIndex = 0xffff;
     if (v->profile == PROFILE_ADVANCED) {
@@ -73,8 +73,8 @@ static void fill_picture_parameters(AVCodecContext *avctx,
     pp->bPicIntra               = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type;
     pp->bPicBackwardPrediction  = s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type;
     pp->bBidirectionalAveragingMode = (1                                           << 7) |
-                                      ((ctx->cfg->ConfigIntraResidUnsigned != 0)   << 6) |
-                                      ((ctx->cfg->ConfigResidDiffAccelerator != 0) << 5) |
+                                      ((DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) != 0) << 6) |
+                                      ((DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) != 0) << 5) |
                                       ((v->lumscale != 32 || v->lumshift != 0)     << 4) |
                                       ((v->profile == PROFILE_ADVANCED)            << 3);
     pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) |
@@ -82,11 +82,11 @@ static void fill_picture_parameters(AVCodecContext *avctx,
                                         (0                                       << 1) |
                                         (!s->quarter_sample                          );
     pp->bChromaFormat           = v->chromaformat;
-    ctx->report_id++;
-    if (ctx->report_id >= (1 << 16))
-        ctx->report_id = 1;
-    pp->bPicScanFixed           = ctx->report_id >> 8;
-    pp->bPicScanMethod          = ctx->report_id & 0xff;
+    DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
+    if (DXVA_CONTEXT_REPORT_ID(avctx, ctx) >= (1 << 16))
+        DXVA_CONTEXT_REPORT_ID(avctx, ctx) = 1;
+    pp->bPicScanFixed           = DXVA_CONTEXT_REPORT_ID(avctx, ctx) >> 8;
+    pp->bPicScanMethod          = DXVA_CONTEXT_REPORT_ID(avctx, ctx) & 0xff;
     pp->bPicReadbackRequests    = 0;
     pp->bRcontrol               = v->rnd;
     pp->bPicSpatialResid8       = (v->panscanflag  << 7) |
@@ -157,11 +157,11 @@ static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice,
 }
 
 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
-                                             DXVA2_DecodeBufferDesc *bs,
-                                             DXVA2_DecodeBufferDesc *sc)
+                                             DECODER_BUFFER_DESC *bs,
+                                             DECODER_BUFFER_DESC *sc)
 {
     const VC1Context *v = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     const MpegEncContext *s = &v->s;
     struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private;
 
@@ -177,11 +177,27 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
     uint8_t  *dxva_data;
     unsigned dxva_size;
     int result;
+    unsigned type;
 
-    if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
-                                              DXVA2_BitStreamDateBufferType,
-                                              &dxva_data_ptr, &dxva_size)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
+        if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
+                                                       D3D11VA_CONTEXT(ctx)->decoder,
+                                                       type,
+                                                       &dxva_size, &dxva_data_ptr)))
+            return -1;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        type = DXVA2_BitStreamDateBufferType;
+        if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
+                                                  type,
+                                                  &dxva_data_ptr, &dxva_size)))
+            return -1;
+    }
+#endif
 
     dxva_data = dxva_data_ptr;
     result = data_size <= dxva_size ? 0 : -1;
@@ -194,21 +210,46 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
             memset(dxva_data + start_code_size + slice_size, 0, padding);
         slice->dwSliceBitsInBuffer = 8 * data_size;
     }
-    if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
-                                                  DXVA2_BitStreamDateBufferType)))
-        return -1;
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+        if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+        if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
+            return -1;
+#endif
     if (result)
         return result;
 
-    memset(bs, 0, sizeof(*bs));
-    bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
-    bs->DataSize             = data_size;
-    bs->NumMBsInBuffer       = s->mb_width * s->mb_height;
-    assert((bs->DataSize & 127) == 0);
+#if CONFIG_D3D11VA
+    if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
+        D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
+        memset(dsc11, 0, sizeof(*dsc11));
+        dsc11->BufferType           = type;
+        dsc11->DataSize             = data_size;
+        dsc11->NumMBsInBuffer       = s->mb_width * s->mb_height;
+
+        type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
+    }
+#endif
+#if CONFIG_DXVA2
+    if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+        DXVA2_DecodeBufferDesc *dsc2 = bs;
+        memset(dsc2, 0, sizeof(*dsc2));
+        dsc2->CompressedBufferType = type;
+        dsc2->DataSize             = data_size;
+        dsc2->NumMBsInBuffer       = s->mb_width * s->mb_height;
+
+        type = DXVA2_SliceControlBufferType;
+    }
+#endif
+    assert((data_size & 127) == 0);
 
     return ff_dxva2_commit_buffer(avctx, ctx, sc,
-                                  DXVA2_SliceControlBufferType,
-                                  slice, sizeof(*slice), bs->NumMBsInBuffer);
+                                  type,
+                                  slice, sizeof(*slice), s->mb_width * s->mb_height);
 }
 
 static int dxva2_vc1_start_frame(AVCodecContext *avctx,
@@ -216,10 +257,12 @@ static int dxva2_vc1_start_frame(AVCodecContext *avctx,
                                  av_unused uint32_t size)
 {
     const VC1Context *v = avctx->priv_data;
-    struct dxva_context *ctx = avctx->hwaccel_context;
+    AVDXVAContext *ctx = avctx->hwaccel_context;
     struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
 
-    if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+    if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_CFG(avctx, ctx) == NULL ||
+        DXVA_CONTEXT_COUNT(avctx, ctx) <= 0)
         return -1;
     assert(ctx_pic);
 
@@ -285,6 +328,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = {
 };
 #endif
 
+#if CONFIG_VC1_DXVA2_HWACCEL
 AVHWAccel ff_vc1_dxva2_hwaccel = {
     .name           = "vc1_dxva2",
     .type           = AVMEDIA_TYPE_VIDEO,
@@ -295,3 +339,30 @@ AVHWAccel ff_vc1_dxva2_hwaccel = {
     .end_frame      = dxva2_vc1_end_frame,
     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
 };
+#endif
+
+#if CONFIG_WMV3_D3D11VA_HWACCEL
+AVHWAccel ff_wmv3_d3d11va_hwaccel = {
+    .name           = "wmv3_d3d11va",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_WMV3,
+    .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
+    .start_frame    = dxva2_vc1_start_frame,
+    .decode_slice   = dxva2_vc1_decode_slice,
+    .end_frame      = dxva2_vc1_end_frame,
+    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
+#endif
+
+#if CONFIG_VC1_D3D11VA_HWACCEL
+AVHWAccel ff_vc1_d3d11va_hwaccel = {
+    .name           = "vc1_d3d11va",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_VC1,
+    .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
+    .start_frame    = dxva2_vc1_start_frame,
+    .decode_slice   = dxva2_vc1_decode_slice,
+    .end_frame      = dxva2_vc1_end_frame,
+    .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
+#endif
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index a250237..1cee634 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -861,6 +861,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h)
 #if CONFIG_H264_DXVA2_HWACCEL
             *fmt++ = AV_PIX_FMT_DXVA2_VLD;
 #endif
+#if CONFIG_H264_D3D11VA_HWACCEL
+            *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
 #if CONFIG_H264_VAAPI_HWACCEL
             *fmt++ = AV_PIX_FMT_VAAPI_VLD;
 #endif
diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c
index 1b5e2ed..62768aa 100644
--- a/libavcodec/hevc.c
+++ b/libavcodec/hevc.c
@@ -446,6 +446,9 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps)
 #if CONFIG_HEVC_DXVA2_HWACCEL
         *fmt++ = AV_PIX_FMT_DXVA2_VLD;
 #endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+        *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
     }
 
     *fmt++ = sps->pix_fmt;
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index c6847ec..c66d6aa 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1173,6 +1173,9 @@ static const enum AVPixelFormat mpeg12_hwaccel_pixfmt_list_420[] = {
 #if CONFIG_MPEG2_DXVA2_HWACCEL
     AV_PIX_FMT_DXVA2_VLD,
 #endif
+#if CONFIG_MPEG2_D3D11VA_HWACCEL
+    AV_PIX_FMT_D3D11VA_VLD,
+#endif
 #if CONFIG_MPEG2_VAAPI_HWACCEL
     AV_PIX_FMT_VAAPI_VLD,
 #endif
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index ac31c94..2a252d3 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -954,6 +954,9 @@ static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = {
 #if CONFIG_VC1_DXVA2_HWACCEL
     AV_PIX_FMT_DXVA2_VLD,
 #endif
+#if CONFIG_VC1_D3D11VA_HWACCEL
+    AV_PIX_FMT_D3D11VA_VLD,
+#endif
 #if CONFIG_VC1_VAAPI_HWACCEL
     AV_PIX_FMT_VAAPI_VLD,
 #endif
diff --git a/libavcodec/version.h b/libavcodec/version.h
index c478ca3..c57bd85 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 56
-#define LIBAVCODEC_VERSION_MINOR 24
+#define LIBAVCODEC_VERSION_MINOR 25
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
index ea432f9..c2c0157 100644
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
@@ -1333,6 +1333,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
         },
         .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR,
     },
+    [AV_PIX_FMT_D3D11VA_VLD] = {
+        .name = "d3d11va_vld",
+        .log2_chroma_w = 1,
+        .log2_chroma_h = 1,
+        .flags = AV_PIX_FMT_FLAG_HWACCEL,
+    },
     [AV_PIX_FMT_DXVA2_VLD] = {
         .name = "dxva2_vld",
         .log2_chroma_w = 1,
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index e21100f..360015c 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -220,6 +220,8 @@ enum AVPixelFormat {
      */
     AV_PIX_FMT_MMAL,
 
+    AV_PIX_FMT_D3D11VA_VLD,  ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
+
     AV_PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
 
 #if FF_API_PIX_FMT
diff --git a/libavutil/version.h b/libavutil/version.h
index 9c45e0e..13bb6f0 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -54,7 +54,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR 54
-#define LIBAVUTIL_VERSION_MINOR 12
+#define LIBAVUTIL_VERSION_MINOR 13
 #define LIBAVUTIL_VERSION_MICRO  1
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \



More information about the ffmpeg-cvslog mailing list