summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rw-r--r--avtools/Makefile1
-rw-r--r--avtools/avconv.h1
-rw-r--r--avtools/avconv_dxva2.c440
-rw-r--r--avtools/avconv_opt.c10
-rwxr-xr-xconfigure19
-rw-r--r--doc/APIchanges6
-rw-r--r--libavcodec/allcodecs.c5
-rw-r--r--libavcodec/dxva2.c663
-rw-r--r--libavcodec/dxva2_h264.c22
-rw-r--r--libavcodec/dxva2_hevc.c22
-rw-r--r--libavcodec/dxva2_internal.h43
-rw-r--r--libavcodec/dxva2_mpeg2.c22
-rw-r--r--libavcodec/dxva2_vc1.c44
-rw-r--r--libavcodec/h264_slice.c3
-rw-r--r--libavcodec/hevcdec.c3
-rw-r--r--libavcodec/mpeg12dec.c1
-rw-r--r--libavcodec/vc1dec.c1
-rw-r--r--libavcodec/version.h4
-rw-r--r--libavutil/hwcontext_dxva2.h3
20 files changed, 853 insertions, 461 deletions
diff --git a/Changelog b/Changelog
index 6fd30fd..e44df54 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/Makefile b/avtools/Makefile
index c23a605..d95e2d9 100644
--- a/avtools/Makefile
+++ b/avtools/Makefile
@@ -12,7 +12,6 @@ OBJS-avconv += avtools/avconv_opt.o avtools/avconv_filter.o \
avtools/avconv_hw.o
OBJS-avconv-$(CONFIG_LIBMFX) += avtools/avconv_qsv.o
OBJS-avconv-$(CONFIG_VDA) += avtools/avconv_vda.o
-OBJS-avconv-$(HAVE_DXVA2_LIB) += avtools/avconv_dxva2.o
define DOAVTOOL
OBJS-$(1) += avtools/cmdutils.o avtools/$(1).o $(OBJS-$(1)-yes)
diff --git a/avtools/avconv.h b/avtools/avconv.h
index 3354c50..4c69933 100644
--- a/avtools/avconv.h
+++ b/avtools/avconv.h
@@ -57,6 +57,7 @@ enum HWAccelID {
HWACCEL_VDA,
HWACCEL_QSV,
HWACCEL_VAAPI,
+ HWACCEL_D3D11VA,
};
typedef struct HWAccel {
diff --git a/avtools/avconv_dxva2.c b/avtools/avconv_dxva2.c
deleted file mode 100644
index 7578c3f..0000000
--- a/avtools/avconv_dxva2.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * 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
- */
-
-#include <windows.h>
-
-#ifdef _WIN32_WINNT
-#undef _WIN32_WINNT
-#endif
-#define _WIN32_WINNT 0x0600
-#define DXVA2API_USE_BITFIELDS
-#define COBJMACROS
-
-#include <stdint.h>
-
-#include <d3d9.h>
-#include <dxva2api.h>
-
-#include "avconv.h"
-
-#include "libavcodec/dxva2.h"
-
-#include "libavutil/avassert.h"
-#include "libavutil/buffer.h"
-#include "libavutil/frame.h"
-#include "libavutil/imgutils.h"
-#include "libavutil/pixfmt.h"
-
-#include "libavutil/hwcontext.h"
-#include "libavutil/hwcontext_dxva2.h"
-
-/* define all the GUIDs used directly here,
- to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
-#include <initguid.h>
-DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
-
-DEFINE_GUID(DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
-DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
-DEFINE_GUID(DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
-DEFINE_GUID(DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
-DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
-DEFINE_GUID(DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
-DEFINE_GUID(DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
-DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
-DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13);
-DEFINE_GUID(DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
-DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
-
-typedef struct dxva2_mode {
- const GUID *guid;
- enum AVCodecID codec;
-} dxva2_mode;
-
-static const dxva2_mode dxva2_modes[] = {
- /* MPEG-2 */
- { &DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO },
- { &DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO },
-
- /* H.264 */
- { &DXVA2_ModeH264_F, AV_CODEC_ID_H264 },
- { &DXVA2_ModeH264_E, AV_CODEC_ID_H264 },
- /* Intel specific H.264 mode */
- { &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 },
-
- /* VC-1 / WMV3 */
- { &DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 },
- { &DXVA2_ModeVC1_D2010, AV_CODEC_ID_WMV3 },
- { &DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 },
- { &DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 },
-
- /* HEVC/H.265 */
- { &DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC },
- { &DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC },
-
- { NULL, 0 },
-};
-
-typedef struct DXVA2Context {
- IDirectXVideoDecoder *decoder;
-
- GUID decoder_guid;
- DXVA2_ConfigPictureDecode decoder_config;
- IDirectXVideoDecoderService *decoder_service;
-
- AVFrame *tmp_frame;
-
- AVBufferRef *hw_device_ctx;
- AVBufferRef *hw_frames_ctx;
-} DXVA2Context;
-
-static void dxva2_uninit(AVCodecContext *s)
-{
- InputStream *ist = s->opaque;
- DXVA2Context *ctx = ist->hwaccel_ctx;
-
- ist->hwaccel_uninit = NULL;
- ist->hwaccel_get_buffer = NULL;
- ist->hwaccel_retrieve_data = NULL;
-
- if (ctx->decoder_service)
- IDirectXVideoDecoderService_Release(ctx->decoder_service);
-
- av_buffer_unref(&ctx->hw_frames_ctx);
- av_buffer_unref(&ctx->hw_device_ctx);
-
- av_frame_free(&ctx->tmp_frame);
-
- av_freep(&ist->hwaccel_ctx);
- av_freep(&s->hwaccel_context);
-}
-
-static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
-{
- InputStream *ist = s->opaque;
- DXVA2Context *ctx = ist->hwaccel_ctx;
-
- return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0);
-}
-
-static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame)
-{
- InputStream *ist = s->opaque;
- DXVA2Context *ctx = ist->hwaccel_ctx;
- int ret;
-
- ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0);
- if (ret < 0)
- return ret;
-
- ret = av_frame_copy_props(ctx->tmp_frame, frame);
- if (ret < 0) {
- av_frame_unref(ctx->tmp_frame);
- return ret;
- }
-
- av_frame_unref(frame);
- av_frame_move_ref(frame, ctx->tmp_frame);
-
- return 0;
-}
-
-static int dxva2_alloc(AVCodecContext *s)
-{
- InputStream *ist = s->opaque;
- int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
- DXVA2Context *ctx;
- HANDLE device_handle;
- HRESULT hr;
-
- AVHWDeviceContext *device_ctx;
- AVDXVA2DeviceContext *device_hwctx;
- int ret;
-
- ctx = av_mallocz(sizeof(*ctx));
- if (!ctx)
- return AVERROR(ENOMEM);
-
- ist->hwaccel_ctx = ctx;
- ist->hwaccel_uninit = dxva2_uninit;
- ist->hwaccel_get_buffer = dxva2_get_buffer;
- ist->hwaccel_retrieve_data = dxva2_retrieve_data;
-
- ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, AV_HWDEVICE_TYPE_DXVA2,
- ist->hwaccel_device, NULL, 0);
- if (ret < 0)
- goto fail;
- device_ctx = (AVHWDeviceContext*)ctx->hw_device_ctx->data;
- device_hwctx = device_ctx->hwctx;
-
- hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
- &device_handle);
- if (FAILED(hr)) {
- av_log(NULL, loglevel, "Failed to open a device handle\n");
- goto fail;
- }
-
- hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle,
- &IID_IDirectXVideoDecoderService,
- (void **)&ctx->decoder_service);
- IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle);
- if (FAILED(hr)) {
- av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n");
- goto fail;
- }
-
- ctx->tmp_frame = av_frame_alloc();
- if (!ctx->tmp_frame)
- goto fail;
-
- s->hwaccel_context = av_mallocz(sizeof(struct dxva_context));
- if (!s->hwaccel_context)
- goto fail;
-
- return 0;
-fail:
- dxva2_uninit(s);
- return AVERROR(EINVAL);
-}
-
-static int dxva2_get_decoder_configuration(AVCodecContext *s, const GUID *device_guid,
- const DXVA2_VideoDesc *desc,
- DXVA2_ConfigPictureDecode *config)
-{
- InputStream *ist = s->opaque;
- int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
- DXVA2Context *ctx = ist->hwaccel_ctx;
- unsigned cfg_count = 0, best_score = 0;
- DXVA2_ConfigPictureDecode *cfg_list = NULL;
- DXVA2_ConfigPictureDecode best_cfg = {{0}};
- HRESULT hr;
- int i;
-
- hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->decoder_service, device_guid, desc, NULL, &cfg_count, &cfg_list);
- if (FAILED(hr)) {
- av_log(NULL, loglevel, "Unable to retrieve decoder configurations\n");
- return AVERROR(EINVAL);
- }
-
- for (i = 0; i < cfg_count; i++) {
- DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
-
- unsigned score;
- if (cfg->ConfigBitstreamRaw == 1)
- score = 1;
- else if (s->codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2)
- score = 2;
- else
- continue;
- if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt))
- score += 16;
- if (score > best_score) {
- best_score = score;
- best_cfg = *cfg;
- }
- }
- CoTaskMemFree(cfg_list);
-
- if (!best_score) {
- av_log(NULL, loglevel, "No valid decoder configuration available\n");
- return AVERROR(EINVAL);
- }
-
- *config = best_cfg;
- return 0;
-}
-
-static int dxva2_create_decoder(AVCodecContext *s)
-{
- InputStream *ist = s->opaque;
- int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
- DXVA2Context *ctx = ist->hwaccel_ctx;
- struct dxva_context *dxva_ctx = s->hwaccel_context;
- GUID *guid_list = NULL;
- unsigned guid_count = 0, i, j;
- GUID device_guid = GUID_NULL;
- const D3DFORMAT surface_format = s->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
- MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2');
- D3DFORMAT target_format = 0;
- DXVA2_VideoDesc desc = { 0 };
- DXVA2_ConfigPictureDecode config;
- HRESULT hr;
- int surface_alignment, num_surfaces;
- int ret;
-
- AVDXVA2FramesContext *frames_hwctx;
- AVHWFramesContext *frames_ctx;
-
- hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list);
- if (FAILED(hr)) {
- av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n");
- goto fail;
- }
-
- for (i = 0; dxva2_modes[i].guid; i++) {
- D3DFORMAT *target_list = NULL;
- unsigned target_count = 0;
- const dxva2_mode *mode = &dxva2_modes[i];
- if (mode->codec != s->codec_id)
- continue;
-
- for (j = 0; j < guid_count; j++) {
- if (IsEqualGUID(mode->guid, &guid_list[j]))
- break;
- }
- if (j == guid_count)
- continue;
-
- hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->decoder_service, mode->guid, &target_count, &target_list);
- if (FAILED(hr)) {
- continue;
- }
- for (j = 0; j < target_count; j++) {
- const D3DFORMAT format = target_list[j];
- if (format == surface_format) {
- target_format = format;
- break;
- }
- }
- CoTaskMemFree(target_list);
- if (target_format) {
- device_guid = *mode->guid;
- break;
- }
- }
- CoTaskMemFree(guid_list);
-
- if (IsEqualGUID(&device_guid, &GUID_NULL)) {
- av_log(NULL, loglevel, "No decoder device for codec found\n");
- goto fail;
- }
-
- desc.SampleWidth = s->coded_width;
- desc.SampleHeight = s->coded_height;
- desc.Format = target_format;
-
- ret = dxva2_get_decoder_configuration(s, &device_guid, &desc, &config);
- if (ret < 0) {
- goto fail;
- }
-
- /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
- but it causes issues for H.264 on certain AMD GPUs..... */
- if (s->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 (s->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 (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC)
- num_surfaces += 16;
- else
- num_surfaces += 2;
-
- /* add extra surfaces for frame threading */
- if (s->active_thread_type & FF_THREAD_FRAME)
- num_surfaces += s->thread_count;
-
- ctx->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->hw_device_ctx);
- if (!ctx->hw_frames_ctx)
- goto fail;
- frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
- frames_hwctx = frames_ctx->hwctx;
-
- frames_ctx->format = AV_PIX_FMT_DXVA2_VLD;
- frames_ctx->sw_format = s->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
- AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
- frames_ctx->width = FFALIGN(s->coded_width, surface_alignment);
- frames_ctx->height = FFALIGN(s->coded_height, surface_alignment);
- frames_ctx->initial_pool_size = num_surfaces;
-
- frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
-
- ret = av_hwframe_ctx_init(ctx->hw_frames_ctx);
- if (ret < 0) {
- av_log(NULL, loglevel, "Failed to initialize the HW frames context\n");
- goto fail;
- }
-
- hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid,
- &desc, &config, frames_hwctx->surfaces,
- frames_hwctx->nb_surfaces, &frames_hwctx->decoder_to_release);
- if (FAILED(hr)) {
- av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n");
- goto fail;
- }
-
- ctx->decoder_guid = device_guid;
- ctx->decoder_config = config;
-
- dxva_ctx->cfg = &ctx->decoder_config;
- dxva_ctx->decoder = frames_hwctx->decoder_to_release;
- dxva_ctx->surface = frames_hwctx->surfaces;
- dxva_ctx->surface_count = frames_hwctx->nb_surfaces;
-
- if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E))
- dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
-
- return 0;
-fail:
- av_buffer_unref(&ctx->hw_frames_ctx);
- return AVERROR(EINVAL);
-}
-
-int dxva2_init(AVCodecContext *s)
-{
- InputStream *ist = s->opaque;
- int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
- DXVA2Context *ctx;
- int ret;
-
- if (!ist->hwaccel_ctx) {
- ret = dxva2_alloc(s);
- if (ret < 0)
- return ret;
- }
- ctx = ist->hwaccel_ctx;
-
- if (s->codec_id == AV_CODEC_ID_H264 &&
- (s->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) {
- av_log(NULL, loglevel, "Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->profile);
- return AVERROR(EINVAL);
- }
-
- if (s->codec_id == AV_CODEC_ID_HEVC &&
- s->profile != FF_PROFILE_HEVC_MAIN && s->profile != FF_PROFILE_HEVC_MAIN_10) {
- av_log(NULL, loglevel, "Unsupported HEVC profile for DXVA2 HWAccel: %d\n", s->profile);
- return AVERROR(EINVAL);
- }
-
- av_buffer_unref(&ctx->hw_frames_ctx);
-
- ret = dxva2_create_decoder(s);
- if (ret < 0) {
- av_log(NULL, loglevel, "Error creating the DXVA2 decoder\n");
- return ret;
- }
-
- return 0;
-}
diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c
index 9839a22..575ce12 100644
--- a/avtools/avconv_opt.c
+++ b/avtools/avconv_opt.c
@@ -60,9 +60,13 @@ const HWAccel hwaccels[] = {
{ "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU,
AV_HWDEVICE_TYPE_VDPAU },
#endif
-#if HAVE_DXVA2_LIB
- { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
- AV_HWDEVICE_TYPE_NONE },
+#if CONFIG_D3D11VA
+ { "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11,
+ AV_HWDEVICE_TYPE_D3D11VA },
+#endif
+#if CONFIG_DXVA2
+ { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
+ AV_HWDEVICE_TYPE_DXVA2 },
#endif
#if CONFIG_VDA
{ "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA,
diff --git a/configure b/configure
index 0281f54..019902c 100755
--- a/configure
+++ b/configure
@@ -1713,7 +1713,6 @@ HAVE_LIST="
$TOOLCHAIN_FEATURES
$TYPES_LIST
dos_paths
- dxva2_lib
libc_msvcrt
MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
sdl
@@ -2166,8 +2165,7 @@ zmbv_encoder_deps="zlib"
# hardware accelerators
d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder"
-dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode"
-dxva2_lib_deps="dxva2"
+dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32"
vda_deps="VideoDecodeAcceleration_VDADecoder_h blocks_extension pthreads"
vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore"
@@ -2175,6 +2173,8 @@ h263_vaapi_hwaccel_deps="vaapi"
h263_vaapi_hwaccel_select="h263_decoder"
h264_d3d11va_hwaccel_deps="d3d11va"
h264_d3d11va_hwaccel_select="h264_decoder"
+h264_d3d11va2_hwaccel_deps="d3d11va"
+h264_d3d11va2_hwaccel_select="h264_decoder"
h264_dxva2_hwaccel_deps="dxva2"
h264_dxva2_hwaccel_select="h264_decoder"
h264_mmal_hwaccel_deps="mmal"
@@ -2189,6 +2189,8 @@ 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_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC"
+hevc_d3d11va2_hwaccel_select="hevc_decoder"
hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
hevc_dxva2_hwaccel_select="hevc_decoder"
hevc_qsv_hwaccel_deps="libmfx"
@@ -2200,6 +2202,8 @@ mpeg1_vdpau_hwaccel_deps="vdpau"
mpeg1_vdpau_hwaccel_select="mpeg1video_decoder"
mpeg2_d3d11va_hwaccel_deps="d3d11va"
mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder"
+mpeg2_d3d11va2_hwaccel_deps="d3d11va"
+mpeg2_d3d11va2_hwaccel_select="mpeg2video_decoder"
mpeg2_dxva2_hwaccel_deps="dxva2"
mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
mpeg2_mmal_hwaccel_deps="mmal"
@@ -2214,6 +2218,8 @@ mpeg4_vdpau_hwaccel_deps="vdpau"
mpeg4_vdpau_hwaccel_select="mpeg4_decoder"
vc1_d3d11va_hwaccel_deps="d3d11va"
vc1_d3d11va_hwaccel_select="vc1_decoder"
+vc1_d3d11va2_hwaccel_deps="d3d11va"
+vc1_d3d11va2_hwaccel_select="vc1_decoder"
vc1_dxva2_hwaccel_deps="dxva2"
vc1_dxva2_hwaccel_select="vc1_decoder"
vc1_mmal_hwaccel_deps="mmal"
@@ -2226,6 +2232,7 @@ vp8_qsv_hwaccel_deps="libmfx"
vp8_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferVP8"
vp8_vaapi_hwaccel_select="vp8_decoder"
wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel"
+wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel"
wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
@@ -2544,7 +2551,7 @@ avconv_deps="avcodec avfilter avformat avresample swscale"
avconv_select="aformat_filter anull_filter asyncts_filter atrim_filter format_filter
fps_filter null_filter resample_filter scale_filter
trim_filter"
-avconv_suggest="dxva2_lib ole32 psapi shell32"
+avconv_suggest="psapi shell32"
avplay_deps="avcodec avfilter avformat avresample sdl"
avplay_select="rdft format_filter transpose_filter hflip_filter vflip_filter"
avplay_suggest="shell32"
@@ -4670,6 +4677,7 @@ check_header windows.h
# so we also check that atomics actually work here
check_builtin stdatomic_h stdatomic.h "atomic_int foo; atomic_store(&foo, 0)"
+check_lib ole32 "windows.h" CoTaskMemFree -lole32
check_lib shell32 "windows.h shellapi.h" CommandLineToArgvW -lshell32
check_lib wincrypt "windows.h wincrypt.h" CryptGenRandom -ladvapi32
check_lib psapi "windows.h psapi.h" GetProcessMemoryInfo -lpsapi
@@ -4877,9 +4885,6 @@ if enabled libxcb; then
check_pkg_config libxcb_xfixes xcb-xfixes xcb/xfixes.h xcb_xfixes_get_cursor_image
fi
-enabled dxva2 &&
- check_lib dxva2_lib windows.h CoTaskMemFree -lole32
-
enabled vaapi && require vaapi va/va.h vaInitialize -lva
enabled vaapi &&
diff --git a/doc/APIchanges b/doc/APIchanges
index a81e418..0f7c839 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,12 @@ libavutil: 2017-03-23
API changes, most recent first:
+2017-xx-xx - xxxxxxx - lavc 58.4.0 - avcodec.h
+ DXVA2 and D3D11 hardware accelerated decoding now supports the new hwaccel API,
+ which can create the decoder context and allocate hardware frame automatically.
+ See AVCodecContext.hw_device_ctx and AVCodecContext.hw_frames_ctx. For D3D11,
+ the new AV_PIX_FMT_D3D11 pixfmt must be used with the new API.
+
2017-xx-xx - xxxxxxx - lavu 56.2.0 - hwcontext.h
Add AV_HWDEVICE_TYPE_D3D11VA and AV_PIX_FMT_D3D11.
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index dc9a961..70c35e9 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -69,6 +69,7 @@ void avcodec_register_all(void)
/* hardware accelerators */
REGISTER_HWACCEL(H263_VAAPI, h263_vaapi);
REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va);
+ REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2);
REGISTER_HWACCEL(H264_DXVA2, h264_dxva2);
REGISTER_HWACCEL(H264_MMAL, h264_mmal);
REGISTER_HWACCEL(H264_QSV, h264_qsv);
@@ -77,12 +78,14 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old);
REGISTER_HWACCEL(H264_VDPAU, h264_vdpau);
REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va);
+ REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2);
REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2);
REGISTER_HWACCEL(HEVC_QSV, hevc_qsv);
REGISTER_HWACCEL(HEVC_VAAPI, hevc_vaapi);
REGISTER_HWACCEL(HEVC_VDPAU, hevc_vdpau);
REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va);
+ REGISTER_HWACCEL(MPEG2_D3D11VA2, mpeg2_d3d11va2);
REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2);
REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal);
REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv);
@@ -91,6 +94,7 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi);
REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau);
REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va);
+ REGISTER_HWACCEL(VC1_D3D11VA2, vc1_d3d11va2);
REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
REGISTER_HWACCEL(VC1_QSV, vc1_qsv);
REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
@@ -99,6 +103,7 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(VP8_QSV, vp8_qsv);
REGISTER_HWACCEL(VP8_VAAPI, vp8_vaapi);
REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va);
+ REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2);
REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2);
REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi);
REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau);
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index 5bc9b30..e0c5406 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -22,20 +22,446 @@
#include <assert.h>
#include <string.h>
+#include <initguid.h>
+#include "libavutil/common.h"
#include "libavutil/log.h"
#include "libavutil/time.h"
#include "avcodec.h"
#include "dxva2_internal.h"
+/* define all the GUIDs used directly here,
+ to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
+DEFINE_GUID(ff_DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
+DEFINE_GUID(ff_DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
+DEFINE_GUID(ff_DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
+DEFINE_GUID(ff_DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
+DEFINE_GUID(ff_DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
+DEFINE_GUID(ff_DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
+DEFINE_GUID(ff_DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13);
+DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
+DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
+DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
+
+typedef struct dxva_mode {
+ const GUID *guid;
+ enum AVCodecID codec;
+} dxva_mode;
+
+static const dxva_mode dxva_modes[] = {
+ /* MPEG-2 */
+ { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO },
+ { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO },
+
+ /* H.264 */
+ { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264 },
+ { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264 },
+ /* Intel specific H.264 mode */
+ { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 },
+
+ /* VC-1 / WMV3 */
+ { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 },
+ { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_WMV3 },
+ { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 },
+ { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 },
+
+ /* HEVC/H.265 */
+ { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC },
+ { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC },
+
+ { NULL, 0 },
+};
+
+static int dxva_get_decoder_configuration(AVCodecContext *avctx,
+ const void *cfg_list,
+ unsigned cfg_count)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ unsigned i, best_score = 0;
+ int best_cfg = -1;
+
+ for (i = 0; i < cfg_count; i++) {
+ unsigned score;
+ UINT ConfigBitstreamRaw;
+ GUID guidConfigBitstreamEncryption;
+
+#if CONFIG_D3D11VA
+ if (sctx->pix_fmt == AV_PIX_FMT_D3D11) {
+ D3D11_VIDEO_DECODER_CONFIG *cfg = &((D3D11_VIDEO_DECODER_CONFIG *)cfg_list)[i];
+ ConfigBitstreamRaw = cfg->ConfigBitstreamRaw;
+ guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption;
+ }
+#endif
+#if CONFIG_DXVA2
+ if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
+ DXVA2_ConfigPictureDecode *cfg = &((DXVA2_ConfigPictureDecode *)cfg_list)[i];
+ ConfigBitstreamRaw = cfg->ConfigBitstreamRaw;
+ guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption;
+ }
+#endif
+
+ if (ConfigBitstreamRaw == 1)
+ score = 1;
+ else if (avctx->codec_id == AV_CODEC_ID_H264 && ConfigBitstreamRaw == 2)
+ score = 2;
+ else
+ continue;
+ if (IsEqualGUID(&guidConfigBitstreamEncryption, &ff_DXVA2_NoEncrypt))
+ score += 16;
+ if (score > best_score) {
+ best_score = score;
+ best_cfg = i;
+ }
+ }
+
+ if (!best_score) {
+ av_log(avctx, AV_LOG_VERBOSE, "No valid decoder configuration available\n");
+ return AVERROR(EINVAL);
+ }
+
+ return best_cfg;
+}
+
+#if CONFIG_D3D11VA
+static int d3d11va_validate_output(void *service, GUID guid, void *surface_format)
+{
+ HRESULT hr;
+ BOOL is_supported = FALSE;
+ hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice *)service,
+ &guid,
+ *(DXGI_FORMAT *)surface_format,
+ &is_supported);
+ return SUCCEEDED(hr) && is_supported;
+}
+#endif
+
+#if CONFIG_DXVA2
+static int dxva2_validate_output(void *decoder_service, GUID guid, void *surface_format)
+{
+ HRESULT hr;
+ int ret = 0;
+ unsigned j, target_count;
+ D3DFORMAT *target_list;
+ hr = IDirectXVideoDecoderService_GetDecoderRenderTargets((IDirectXVideoDecoderService *)decoder_service, &guid, &target_count, &target_list);
+ if (SUCCEEDED(hr)) {
+ for (j = 0; j < target_count; j++) {
+ const D3DFORMAT format = target_list[j];
+ if (format == *(D3DFORMAT *)surface_format) {
+ ret = 1;
+ break;
+ }
+ }
+ CoTaskMemFree(target_list);
+ }
+ return ret;
+}
+#endif
+
+static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format,
+ unsigned guid_count, const GUID *guid_list, GUID *decoder_guid)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ unsigned i, j;
+
+ *decoder_guid = ff_GUID_NULL;
+ for (i = 0; dxva_modes[i].guid; i++) {
+ const dxva_mode *mode = &dxva_modes[i];
+ int validate;
+ if (mode->codec != avctx->codec_id)
+ continue;
+
+ for (j = 0; j < guid_count; j++) {
+ if (IsEqualGUID(mode->guid, &guid_list[j]))
+ break;
+ }
+ if (j == guid_count)
+ continue;
+
+#if CONFIG_D3D11VA
+ if (sctx->pix_fmt == AV_PIX_FMT_D3D11)
+ validate = d3d11va_validate_output(service, *mode->guid, surface_format);
+#endif
+#if CONFIG_DXVA2
+ if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
+ validate = dxva2_validate_output(service, *mode->guid, surface_format);
+#endif
+ if (validate) {
+ *decoder_guid = *mode->guid;
+ break;
+ }
+ }
+
+ if (IsEqualGUID(decoder_guid, &ff_GUID_NULL)) {
+ av_log(avctx, AV_LOG_VERBOSE, "No decoder device for codec found\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E))
+ sctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
+
+ return 0;
+}
+
+static void bufref_free_interface(void *opaque, uint8_t *data)
+{
+ IUnknown_Release((IUnknown *)opaque);
+}
+
+static AVBufferRef *bufref_wrap_interface(IUnknown *iface)
+{
+ return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0);
+}
+
+#if CONFIG_DXVA2
+
+static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *device_guid,
+ const DXVA2_VideoDesc *desc,
+ DXVA2_ConfigPictureDecode *config)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ unsigned cfg_count;
+ DXVA2_ConfigPictureDecode *cfg_list;
+ HRESULT hr;
+ int ret;
+
+ hr = IDirectXVideoDecoderService_GetDecoderConfigurations(sctx->dxva2_service, device_guid, desc, NULL, &cfg_count, &cfg_list);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n");
+ return AVERROR(EINVAL);
+ }
+
+ ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count);
+ if (ret >= 0)
+ *config = cfg_list[ret];
+ CoTaskMemFree(cfg_list);
+ return ret;
+}
+
+static int dxva2_create_decoder(AVCodecContext *avctx)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ GUID *guid_list;
+ unsigned guid_count;
+ GUID device_guid;
+ D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
+ MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2');
+ DXVA2_VideoDesc desc = { 0 };
+ DXVA2_ConfigPictureDecode config;
+ HRESULT hr;
+ int ret;
+ HANDLE device_handle;
+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+ AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
+ AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
+
+ hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
+ &device_handle);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to open a device handle\n");
+ goto fail;
+ }
+
+ hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle,
+ &ff_IID_IDirectXVideoDecoderService,
+ (void **)&sctx->dxva2_service);
+ IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to create IDirectXVideoDecoderService\n");
+ goto fail;
+ }
+
+ hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(sctx->dxva2_service, &guid_count, &guid_list);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder device GUIDs\n");
+ goto fail;
+ }
+
+ ret = dxva_get_decoder_guid(avctx, sctx->dxva2_service, &surface_format,
+ guid_count, guid_list, &device_guid);
+ CoTaskMemFree(guid_list);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ desc.SampleWidth = avctx->coded_width;
+ desc.SampleHeight = avctx->coded_height;
+ desc.Format = surface_format;
+
+ ret = dxva2_get_decoder_configuration(avctx, &device_guid, &desc, &config);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ hr = IDirectXVideoDecoderService_CreateVideoDecoder(sctx->dxva2_service, &device_guid,
+ &desc, &config, frames_hwctx->surfaces,
+ frames_hwctx->nb_surfaces, &sctx->dxva2_decoder);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to create DXVA2 video decoder\n");
+ goto fail;
+ }
+
+ sctx->dxva2_config = config;
+
+ sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->dxva2_decoder);
+ if (!sctx->decoder_ref)
+ return AVERROR(ENOMEM);
+
+ return 0;
+fail:
+ return AVERROR(EINVAL);
+}
+
+#endif
+
+#if CONFIG_D3D11VA
+
+static int d3d11va_get_decoder_configuration(AVCodecContext *avctx,
+ ID3D11VideoDevice *video_device,
+ const D3D11_VIDEO_DECODER_DESC *desc,
+ D3D11_VIDEO_DECODER_CONFIG *config)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ unsigned cfg_count = 0;
+ D3D11_VIDEO_DECODER_CONFIG *cfg_list = NULL;
+ HRESULT hr;
+ int i, ret;
+
+ hr = ID3D11VideoDevice_GetVideoDecoderConfigCount(video_device, desc, &cfg_count);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n");
+ return AVERROR(EINVAL);
+ }
+
+ cfg_list = av_malloc_array(cfg_count, sizeof(D3D11_VIDEO_DECODER_CONFIG));
+ if (cfg_list == NULL)
+ return AVERROR(ENOMEM);
+ for (i = 0; i < cfg_count; i++) {
+ hr = ID3D11VideoDevice_GetVideoDecoderConfig(video_device, desc, i, &cfg_list[i]);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations. (hr=0x%lX)\n", hr);
+ av_free(cfg_list);
+ return AVERROR(EINVAL);
+ }
+ }
+
+ ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count);
+ if (ret >= 0)
+ *config = cfg_list[ret];
+ av_free(cfg_list);
+ return ret;
+}
+
+static int d3d11va_create_decoder(AVCodecContext *avctx)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ GUID *guid_list;
+ unsigned guid_count, i;
+ GUID decoder_guid;
+ DXGI_FORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
+ DXGI_FORMAT_P010 : DXGI_FORMAT_NV12;
+ D3D11_VIDEO_DECODER_DESC desc = { 0 };
+ D3D11_VIDEO_DECODER_CONFIG config;
+ AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
+ AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
+ AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
+ D3D11_TEXTURE2D_DESC texdesc;
+ HRESULT hr;
+ int ret;
+
+ if (!frames_hwctx->texture) {
+ av_log(avctx, AV_LOG_ERROR, "AVD3D11VAFramesContext.texture not set.\n");
+ return AVERROR(EINVAL);
+ }
+ ID3D11Texture2D_GetDesc(frames_hwctx->texture, &texdesc);
+
+ guid_count = ID3D11VideoDevice_GetVideoDecoderProfileCount(device_hwctx->video_device);
+ guid_list = av_malloc_array(guid_count, sizeof(*guid_list));
+ if (guid_list == NULL || guid_count == 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to get the decoder GUIDs\n");
+ av_free(guid_list);
+ return AVERROR(EINVAL);
+ }
+ for (i = 0; i < guid_count; i++) {
+ hr = ID3D11VideoDevice_GetVideoDecoderProfile(device_hwctx->video_device, i, &guid_list[i]);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder GUID %d\n", i);
+ av_free(guid_list);
+ return AVERROR(EINVAL);
+ }
+ }
+
+ ret = dxva_get_decoder_guid(avctx, device_hwctx->video_device, &surface_format,
+ guid_count, guid_list, &decoder_guid);
+ av_free(guid_list);
+ if (ret < 0)
+ return AVERROR(EINVAL);
+
+ desc.SampleWidth = avctx->coded_width;
+ desc.SampleHeight = avctx->coded_height;
+ desc.OutputFormat = surface_format;
+ desc.Guid = decoder_guid;
+
+ ret = d3d11va_get_decoder_configuration(avctx, device_hwctx->video_device, &desc, &config);
+ if (ret < 0)
+ return AVERROR(EINVAL);
+
+ sctx->d3d11_views = av_mallocz_array(texdesc.ArraySize, sizeof(sctx->d3d11_views[0]));
+ if (!sctx->d3d11_views)
+ return AVERROR(ENOMEM);
+ sctx->nb_d3d11_views = texdesc.ArraySize;
+
+ for (i = 0; i < sctx->nb_d3d11_views; i++) {
+ D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = {
+ .DecodeProfile = decoder_guid,
+ .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D,
+ .Texture2D = {
+ .ArraySlice = i,
+ }
+ };
+ hr = ID3D11VideoDevice_CreateVideoDecoderOutputView(device_hwctx->video_device,
+ (ID3D11Resource*) frames_hwctx->texture,
+ &viewDesc,
+ (ID3D11VideoDecoderOutputView**) &sctx->d3d11_views[i]);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Could not create the decoder output view %d\n", i);
+ return AVERROR_UNKNOWN;
+ }
+ }
+
+ hr = ID3D11VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &desc,
+ &config, &sctx->d3d11_decoder);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to create D3D11VA video decoder\n");
+ return AVERROR(EINVAL);
+ }
+
+ sctx->d3d11_config = config;
+ sctx->d3d11_texture = frames_hwctx->texture;
+
+ sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->d3d11_decoder);
+ if (!sctx->decoder_ref)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+#endif
+
static void ff_dxva2_lock(AVCodecContext *avctx)
{
#if CONFIG_D3D11VA
if (ff_dxva2_is_d3d11(avctx)) {
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE);
+ if (sctx->device_ctx) {
+ AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx;
+ hwctx->lock(hwctx->lock_ctx);
+ }
}
#endif
}
@@ -44,15 +470,216 @@ static void ff_dxva2_unlock(AVCodecContext *avctx)
{
#if CONFIG_D3D11VA
if (ff_dxva2_is_d3d11(avctx)) {
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
AVDXVAContext *ctx = DXVA_CONTEXT(avctx);
if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
+ if (sctx->device_ctx) {
+ AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx;
+ hwctx->unlock(hwctx->lock_ctx);
+ }
+ }
+#endif
+}
+
+// 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 CONFIG_DXVA2
+ if (frames_ctx->format == AV_PIX_FMT_DXVA2_VLD) {
+ AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
+
+ frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
+ }
+#endif
+
+#if CONFIG_D3D11VA
+ if (frames_ctx->format == AV_PIX_FMT_D3D11) {
+ AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
+
+ frames_hwctx->BindFlags |= D3D11_BIND_DECODER;
}
#endif
}
-static void *get_surface(const AVFrame *frame)
+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;
+
+ ff_dxva2_lock(avctx);
+ ret = d3d11va_create_decoder(avctx);
+ ff_dxva2_unlock(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;
+
+ ff_dxva2_lock(avctx);
+ ret = dxva2_create_decoder(avctx);
+ ff_dxva2_unlock(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;
+}
+
+int ff_dxva2_decode_uninit(AVCodecContext *avctx)
+{
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ int i;
+
+ av_buffer_unref(&sctx->decoder_ref);
+
+#if CONFIG_D3D11VA
+ for (i = 0; i < sctx->nb_d3d11_views; i++) {
+ if (sctx->d3d11_views[i])
+ ID3D11VideoDecoderOutputView_Release(sctx->d3d11_views[i]);
+ }
+ av_freep(&sctx->d3d11_views);
+#endif
+
+#if CONFIG_DXVA2
+ if (sctx->dxva2_service)
+ IDirectXVideoDecoderService_Release(sctx->dxva2_service);
+#endif
+
+ return 0;
+}
+
+static void *get_surface(AVCodecContext *avctx, const AVFrame *frame)
+{
+#if CONFIG_D3D11VA
+ if (frame->format == AV_PIX_FMT_D3D11) {
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+ intptr_t index = (intptr_t)frame->data[1];
+ if (index < 0 || index >= sctx->nb_d3d11_views ||
+ sctx->d3d11_texture != (ID3D11Texture2D *)frame->data[0]) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer frame is invalid!\n");
+ return NULL;
+ }
+ return sctx->d3d11_views[index];
+ }
+#endif
return frame->data[3];
}
@@ -60,10 +687,12 @@ unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
const AVDXVAContext *ctx,
const AVFrame *frame)
{
- void *surface = get_surface(frame);
+ void *surface = get_surface(avctx, frame);
unsigned i;
#if CONFIG_D3D11VA
+ if (avctx->pix_fmt == AV_PIX_FMT_D3D11)
+ return (intptr_t)frame->data[1];
if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*) surface, &viewDesc);
@@ -154,6 +783,22 @@ int ff_dxva2_commit_buffer(AVCodecContext *avctx,
return result;
}
+static int frame_add_buf(AVFrame *frame, AVBufferRef *ref)
+{
+ int i;
+
+ for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
+ if (!frame->buf[i]) {
+ frame->buf[i] = av_buffer_ref(ref);
+ return frame->buf[i] ? 0 : AVERROR(ENOMEM);
+ }
+ }
+
+ // For now we expect that the caller does not use more than
+ // AV_NUM_DATA_POINTERS-1 buffers if the user uses a custom pool.
+ return AVERROR(EINVAL);
+}
+
int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
const void *pp, unsigned pp_size,
const void *qm, unsigned qm_size,
@@ -173,19 +818,26 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
int result, runs = 0;
HRESULT hr;
unsigned type;
+ FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
+
+ if (sctx->decoder_ref) {
+ result = frame_add_buf(frame, sctx->decoder_ref);
+ if (result < 0)
+ return result;
+ }
do {
ff_dxva2_lock(avctx);
#if CONFIG_D3D11VA
if (ff_dxva2_is_d3d11(avctx))
hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder,
- get_surface(frame),
+ get_surface(avctx, frame),
0, NULL);
#endif
#if CONFIG_DXVA2
if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder,
- get_surface(frame),
+ get_surface(avctx, frame),
NULL);
#endif
if (hr != E_PENDING || ++runs > 50)
@@ -315,7 +967,8 @@ end:
int ff_dxva2_is_d3d11(const AVCodecContext *avctx)
{
if (CONFIG_D3D11VA)
- return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD;
+ return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD ||
+ avctx->pix_fmt == AV_PIX_FMT_D3D11;
else
return 0;
}
diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
index f58a458..de08850 100644
--- a/libavcodec/dxva2_h264.c
+++ b/libavcodec/dxva2_h264.c
@@ -518,10 +518,13 @@ AVHWAccel ff_h264_dxva2_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
@@ -531,9 +534,28 @@ AVHWAccel ff_h264_d3d11va_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.pix_fmt = AV_PIX_FMT_D3D11VA_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
+};
+#endif
+
+#if CONFIG_H264_D3D11VA2_HWACCEL
+AVHWAccel ff_h264_d3d11va2_hwaccel = {
+ .name = "h264_d3d11va2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_H264,
+ .pix_fmt = AV_PIX_FMT_D3D11,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
+ .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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
index f2bb8b2..4bff26d 100644
--- a/libavcodec/dxva2_hevc.c
+++ b/libavcodec/dxva2_hevc.c
@@ -427,10 +427,13 @@ AVHWAccel ff_hevc_dxva2_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HEVC,
.pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
@@ -440,9 +443,28 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HEVC,
.pix_fmt = AV_PIX_FMT_D3D11VA_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
+};
+#endif
+
+#if CONFIG_HEVC_D3D11VA2_HWACCEL
+AVHWAccel ff_hevc_d3d11va2_hwaccel = {
+ .name = "hevc_d3d11va2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_HEVC,
+ .pix_fmt = AV_PIX_FMT_D3D11,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
+ .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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
index af0d607..901cc11 100644
--- a/libavcodec/dxva2_internal.h
+++ b/libavcodec/dxva2_internal.h
@@ -32,9 +32,11 @@
#if CONFIG_DXVA2
#include "dxva2.h"
+#include "libavutil/hwcontext_dxva2.h"
#endif
#if CONFIG_D3D11VA
#include "d3d11va.h"
+#include "libavutil/hwcontext_d3d11va.h"
#endif
#if HAVE_DXVA_H
/* When targeting WINAPI_FAMILY_PHONE_APP or WINAPI_FAMILY_APP, dxva.h
@@ -46,7 +48,10 @@
#include <dxva.h>
#endif
+#include "libavutil/hwcontext.h"
+
#include "avcodec.h"
+#include "internal.h"
typedef void DECODER_BUFFER_DESC;
@@ -59,7 +64,39 @@ typedef union {
#endif
} AVDXVAContext;
-#define DXVA_CONTEXT(avctx) ((AVDXVAContext *)(avctx)->hwaccel_context)
+typedef struct FFDXVASharedContext {
+ AVBufferRef *decoder_ref;
+
+ // FF_DXVA2_WORKAROUND_* flags
+ uint64_t workaround;
+
+ // E.g. AV_PIX_FMT_D3D11 (same as AVCodecContext.pix_fmt, except during init)
+ enum AVPixelFormat pix_fmt;
+
+ AVHWDeviceContext *device_ctx;
+
+#if CONFIG_D3D11VA
+ ID3D11VideoDecoder *d3d11_decoder;
+ D3D11_VIDEO_DECODER_CONFIG d3d11_config;
+ ID3D11VideoDecoderOutputView **d3d11_views;
+ int nb_d3d11_views;
+ ID3D11Texture2D *d3d11_texture;
+#endif
+
+#if CONFIG_DXVA2
+ IDirectXVideoDecoder *dxva2_decoder;
+ IDirectXVideoDecoderService *dxva2_service;
+ DXVA2_ConfigPictureDecode dxva2_config;
+#endif
+
+ // Legacy (but used by code outside of setup)
+ // In generic mode, DXVA_CONTEXT() will return a pointer to this.
+ AVDXVAContext ctx;
+} FFDXVASharedContext;
+
+#define DXVA_SHARED_CONTEXT(avctx) ((FFDXVASharedContext *)((avctx)->internal->hwaccel_priv_data))
+
+#define DXVA_CONTEXT(avctx) (AVDXVAContext *)((avctx)->hwaccel_context ? (avctx)->hwaccel_context : (&(DXVA_SHARED_CONTEXT(avctx)->ctx)))
#define D3D11VA_CONTEXT(ctx) (&ctx->d3d11va)
#define DXVA2_CONTEXT(ctx) (&ctx->dxva2)
@@ -115,6 +152,10 @@ int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *,
DECODER_BUFFER_DESC *bs,
DECODER_BUFFER_DESC *slice));
+int ff_dxva2_decode_init(AVCodecContext *avctx);
+
+int ff_dxva2_decode_uninit(AVCodecContext *avctx);
+
int ff_dxva2_is_d3d11(const AVCodecContext *avctx);
#endif /* AVCODEC_DXVA2_INTERNAL_H */
diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c
index 6ae30a5..ab80ca3 100644
--- a/libavcodec/dxva2_mpeg2.c
+++ b/libavcodec/dxva2_mpeg2.c
@@ -323,10 +323,13 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_MPEG2VIDEO,
.pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
@@ -336,9 +339,28 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_MPEG2VIDEO,
.pix_fmt = AV_PIX_FMT_D3D11VA_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
+};
+#endif
+
+#if CONFIG_MPEG2_D3D11VA2_HWACCEL
+AVHWAccel ff_mpeg2_d3d11va2_hwaccel = {
+ .name = "mpeg2_d3d11va2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_MPEG2VIDEO,
+ .pix_fmt = AV_PIX_FMT_D3D11,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
+ .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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c
index b63580e..22d3d29 100644
--- a/libavcodec/dxva2_vc1.c
+++ b/libavcodec/dxva2_vc1.c
@@ -323,10 +323,13 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_WMV3,
.pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
@@ -336,10 +339,13 @@ AVHWAccel ff_vc1_dxva2_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_VC1,
.pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
@@ -349,10 +355,29 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_WMV3,
.pix_fmt = AV_PIX_FMT_D3D11VA_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
+};
+#endif
+
+#if CONFIG_WMV3_D3D11VA2_HWACCEL
+AVHWAccel ff_wmv3_d3d11va2_hwaccel = {
+ .name = "wmv3_d3d11va2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_WMV3,
+ .pix_fmt = AV_PIX_FMT_D3D11,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
+ .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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
@@ -362,9 +387,28 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = {
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_VC1,
.pix_fmt = AV_PIX_FMT_D3D11VA_VLD,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
+ .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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
+};
+#endif
+
+#if CONFIG_VC1_D3D11VA2_HWACCEL
+AVHWAccel ff_vc1_d3d11va2_hwaccel = {
+ .name = "vc1_d3d11va2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_VC1,
+ .pix_fmt = AV_PIX_FMT_D3D11,
+ .init = ff_dxva2_decode_init,
+ .uninit = ff_dxva2_decode_uninit,
.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),
+ .priv_data_size = sizeof(FFDXVASharedContext),
};
#endif
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 95e3666..c9f1dbb 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -717,7 +717,7 @@ static void init_scan_tables(H264Context *h)
static enum AVPixelFormat get_pixel_format(H264Context *h)
{
#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
- CONFIG_H264_D3D11VA_HWACCEL + \
+ (CONFIG_H264_D3D11VA_HWACCEL * 2) + \
CONFIG_H264_VAAPI_HWACCEL + \
(CONFIG_H264_VDA_HWACCEL * 2) + \
CONFIG_H264_VDPAU_HWACCEL)
@@ -769,6 +769,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h)
#endif
#if CONFIG_H264_D3D11VA_HWACCEL
*fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+ *fmt++ = AV_PIX_FMT_D3D11;
#endif
#if CONFIG_H264_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 69d5908..7a9182a 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -383,7 +383,7 @@ static void export_stream_params(AVCodecContext *avctx, const HEVCParamSets *ps,
static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
{
- #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL + \
+ #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \
CONFIG_HEVC_VAAPI_HWACCEL + CONFIG_HEVC_VDPAU_HWACCEL)
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
@@ -391,6 +391,7 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
sps->pix_fmt == AV_PIX_FMT_YUV420P10) {
#if CONFIG_HEVC_D3D11VA_HWACCEL
*fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+ *fmt++ = AV_PIX_FMT_D3D11;
#endif
#if CONFIG_HEVC_DXVA2_HWACCEL
*fmt++ = AV_PIX_FMT_DXVA2_VLD;
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 6702ad1..9a9a927 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1111,6 +1111,7 @@ static const enum AVPixelFormat mpeg12_hwaccel_pixfmt_list_420[] = {
#endif
#if CONFIG_MPEG2_D3D11VA_HWACCEL
AV_PIX_FMT_D3D11VA_VLD,
+ AV_PIX_FMT_D3D11,
#endif
#if CONFIG_MPEG2_VAAPI_HWACCEL
AV_PIX_FMT_VAAPI,
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 51745c1..5e00a33 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -962,6 +962,7 @@ static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = {
#endif
#if CONFIG_VC1_D3D11VA_HWACCEL
AV_PIX_FMT_D3D11VA_VLD,
+ AV_PIX_FMT_D3D11,
#endif
#if CONFIG_VC1_VAAPI_HWACCEL
AV_PIX_FMT_VAAPI,
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 88f17a1..bc5b830 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,8 +28,8 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 58
-#define LIBAVCODEC_VERSION_MINOR 3
-#define LIBAVCODEC_VERSION_MICRO 1
+#define LIBAVCODEC_VERSION_MINOR 4
+#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
index 2290c26..c8e7a5c 100644
--- a/libavutil/hwcontext_dxva2.h
+++ b/libavutil/hwcontext_dxva2.h
@@ -65,6 +65,9 @@ typedef struct AVDXVA2FramesContext {
*
* If it is non-NULL, libavutil will call IDirectXVideoDecoder_Release() on
* it just before the internal surface pool is freed.
+ *
+ * This is for convenience only. Some code uses other methods to manage the
+ * decoder reference.
*/
IDirectXVideoDecoder *decoder_to_release;
} AVDXVA2FramesContext;
OpenPOWER on IntegriCloud