diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2015-05-25 22:02:00 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-05-25 22:24:34 +0200 |
commit | 947b74ee7da7984b666a478164917e42d4f4592d (patch) | |
tree | c2de5e9e2059cf14329979e77981819cc5cee7d3 | |
parent | 9aabc926ca14faf240d078c7e428045b62018c8b (diff) | |
parent | d8039ef8d221ea273aa4f1e62e5df21bf618c772 (diff) | |
download | ffmpeg-947b74ee7da7984b666a478164917e42d4f4592d.tar.gz |
Merge commit 'd8039ef8d221ea273aa4f1e62e5df21bf618c772'
* commit 'd8039ef8d221ea273aa4f1e62e5df21bf618c772':
D3D11va: add a Direct3D11 video decoder similar to DXVA2
Conflicts:
Changelog
configure
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/dxva2_vc1.c
libavcodec/version.h
libavutil/pixdesc.c
libavutil/pixfmt.h
libavutil/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | Changelog | 1 | ||||
-rwxr-xr-x | configure | 31 | ||||
-rw-r--r-- | libavcodec/Makefile | 7 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 5 | ||||
-rw-r--r-- | libavcodec/d3d11va.h | 98 | ||||
-rw-r--r-- | libavcodec/dxva2.c | 161 | ||||
-rw-r--r-- | libavcodec/dxva2_h264.c | 138 | ||||
-rw-r--r-- | libavcodec/dxva2_hevc.c | 108 | ||||
-rw-r--r-- | libavcodec/dxva2_internal.h | 32 | ||||
-rw-r--r-- | libavcodec/dxva2_mpeg2.c | 102 | ||||
-rw-r--r-- | libavcodec/dxva2_vc1.c | 131 | ||||
-rw-r--r-- | libavcodec/h264_slice.c | 3 | ||||
-rw-r--r-- | libavcodec/hevc.c | 3 | ||||
-rw-r--r-- | libavcodec/mpeg12dec.c | 3 | ||||
-rw-r--r-- | libavcodec/vc1dec.c | 3 | ||||
-rw-r--r-- | libavcodec/version.h | 2 | ||||
-rw-r--r-- | libavutil/pixdesc.c | 6 | ||||
-rw-r--r-- | libavutil/pixfmt.h | 2 | ||||
-rw-r--r-- | libavutil/version.h | 4 |
19 files changed, 683 insertions, 157 deletions
@@ -22,6 +22,7 @@ version <next>: - improved Quickdraw compatibility - VP9 high bit-depth and extended colorspaces decoding support - WebPAnimEncoder API when available for encoding and muxing WebP +- Direct3D11-accelerated decoding version 2.6: @@ -149,6 +149,7 @@ Component options: --disable-pixelutils disable pixel utils in libavutil Hardware accelerators: + --enable-d3d11va enable D3D11VA code --disable-dxva2 disable DXVA2 code [autodetect] --disable-vaapi disable VAAPI code [autodetect] --disable-vda disable VDA code [autodetect] @@ -1448,6 +1449,7 @@ FEATURE_LIST=" " HWACCEL_LIST=" + d3d11va dxva2 vaapi vda @@ -1670,6 +1672,7 @@ HEADERS_LIST=" dev_video_meteor_ioctl_meteor_h direct_h dlfcn_h + d3d11_h dxva_h ES2_gl_h gsm_h @@ -1845,6 +1848,8 @@ HAVE_LIST=" $TYPES_LIST atomics_native dos_paths + d3d11_cobj + d3d11va_lib dxva2api_cobj dxva2_lib libc_msvcrt @@ -2314,6 +2319,7 @@ zmbv_encoder_select="zlib" # hardware accelerators crystalhd_deps="libcrystalhd_libcrystalhd_if_h" +d3d11va_deps="d3d11_h dxva_h" dxva2_deps="dxva2api_h" vaapi_deps="va_va_h" vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" @@ -2326,6 +2332,8 @@ h263_vaapi_hwaccel_select="h263_decoder" h263_vdpau_hwaccel_deps="vdpau" h263_vdpau_hwaccel_select="h263_decoder" h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" +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" @@ -2345,6 +2353,8 @@ h264_vdpau_decoder_deps="vdpau" h264_vdpau_decoder_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" mpeg_vdpau_decoder_deps="vdpau" @@ -2358,6 +2368,8 @@ mpeg1_vdpau_hwaccel_select="mpeg1video_decoder" mpeg1_xvmc_hwaccel_deps="xvmc" mpeg1_xvmc_hwaccel_select="mpeg1video_decoder" mpeg2_crystalhd_decoder_select="crystalhd" +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" @@ -2375,6 +2387,8 @@ mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" msmpeg4_crystalhd_decoder_select="crystalhd" vc1_crystalhd_decoder_select="crystalhd" +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" @@ -2384,6 +2398,7 @@ vc1_vdpau_decoder_select="vc1_decoder" vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_select="vc1_decoder" wmv3_crystalhd_decoder_select="crystalhd" +wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_decoder_select="vc1_vdpau_decoder" @@ -2814,7 +2829,7 @@ sws_max_filter_size_default=256 set_default sws_max_filter_size # Enable hwaccels by default. -enable dxva2 vaapi vda vdpau xvmc +enable d3d11va dxva2 vaapi vda vdpau xvmc enable xlib # build settings @@ -4945,6 +4960,7 @@ enabled xlib && check_header direct.h check_header dlfcn.h +check_header d3d11.h check_header dxva.h check_header dxva2api.h -D_WIN32_WINNT=0x0600 check_header io.h @@ -5293,6 +5309,15 @@ enabled dxva2api_h && int main(void) { IDirectXVideoDecoder *o = NULL; IDirectXVideoDecoder_Release(o); return 0; } EOF +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 && check_lib va/va.h vaInitialize -lva || disable vaapi @@ -5550,6 +5575,10 @@ if test $target_os = "haiku"; then disable posix_memalign fi +enabled_all d3d11va d3d11_cobj CoTaskMemFree && + prepend ffmpeg_libs $($ldflags_filter "-lole32") && + enable d3d11va_lib + enabled_all dxva2 dxva2api_cobj CoTaskMemFree && prepend ffmpeg_libs $($ldflags_filter "-lole32" "-luser32") && enable dxva2_lib diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 02aa61e682..8bbf78c9cf 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -5,6 +5,7 @@ NAME = avcodec HEADERS = avcodec.h \ avfft.h \ dv_profile.h \ + d3d11va.h \ dxva2.h \ old_codec_ids.h \ qsv.h \ @@ -671,6 +672,7 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_VIMA_DECODER) += vima.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 @@ -678,19 +680,23 @@ 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_MPEG1_XVMC_HWACCEL) += mpegvideo_xvmc.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_MPEG2_XVMC_HWACCEL) += mpegvideo_xvmc.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 @@ -872,6 +878,7 @@ SKIPHEADERS += %_tablegen.h \ tableprint_vlc.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_LIBUTVIDEO) += libutvideo.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index fe79d0bb3b..a94d1dc8f6 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,18 +84,22 @@ 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_XVMC, mpeg1_xvmc); REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); REGISTER_HWACCEL(MPEG2_XVMC, mpeg2_xvmc); + 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 0000000000..d51e2ff8f5 --- /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 FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; 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 FFmpeg 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 FFmpeg AVHWAccel implementation + */ + unsigned report_id; +}; + +/** + * @} + */ + +#endif /* AVCODEC_D3D11VA_H */ diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index c1c7681402..477607957c 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 8915e47a6c..fe252bbae8 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 FFmpeg */ } -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 4fba3ad648..dae990dd8f 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 427c1ffdf8..5a30bc6aef 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 7ef4a6ceb9..89c43e7f9c 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) { @@ -146,11 +146,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; @@ -159,11 +159,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; @@ -189,19 +205,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); @@ -212,11 +253,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); @@ -270,6 +313,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, @@ -280,3 +324,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 3beeb9f751..1eb425383e 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; @@ -51,13 +51,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) { @@ -82,8 +82,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) | (intcomp << 4) | ((v->profile == PROFILE_ADVANCED) << 3); pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) | @@ -91,11 +91,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) | @@ -176,11 +176,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; @@ -196,11 +196,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; @@ -216,21 +232,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, @@ -238,10 +279,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); @@ -307,6 +350,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { }; #endif +#if CONFIG_VC1_DXVA2_HWACCEL AVHWAccel ff_vc1_dxva2_hwaccel = { .name = "vc1_dxva2", .type = AVMEDIA_TYPE_VIDEO, @@ -317,3 +361,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 2064496775..738c359701 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -935,6 +935,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #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 df6cce6f8a..028ece82f9 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -343,6 +343,9 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps, enum AVPixelFormat pix_fm #if CONFIG_HEVC_DXVA2_HWACCEL *fmt++ = AV_PIX_FMT_DXVA2_VLD; #endif +#if CONFIG_HEVC_D3D11VA_HWACCEL + *fmt++ = AV_PIX_FMT_D3D11VA_VLD; +#endif } if (pix_fmt == AV_PIX_FMT_NONE) { diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 3bb736f87c..f180c3d62b 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -1204,6 +1204,9 @@ static const enum AVPixelFormat mpeg2_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 d39f344102..eab6792f36 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1074,6 +1074,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 b9f99d7181..74a1b3048e 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 40 +#define LIBAVCODEC_VERSION_MINOR 41 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 5086edc5e7..32dc4b80ab 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -1586,6 +1586,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 b1056d9504..3ddd30f0d8 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -258,6 +258,8 @@ enum AVPixelFormat { */ AV_PIX_FMT_MMAL, + AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer + #ifndef AV_PIX_FMT_ABI_GIT_MASTER AV_PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian diff --git a/libavutil/version.h b/libavutil/version.h index 18a22952e0..eeafcfab6c 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -56,8 +56,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 54 -#define LIBAVUTIL_VERSION_MINOR 23 -#define LIBAVUTIL_VERSION_MICRO 101 +#define LIBAVUTIL_VERSION_MINOR 24 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ |