[vlc-devel] [PATCH 6/6] contrib: ffmpeg/libav: fix the D3D11 slice index used by the decoder

Steve Lhomme robux4 at videolabs.io
Wed Oct 5 10:02:00 CEST 2016


This allows arbitrary slice index in the output buffer we provide the decoder.

--
replaces https://patches.videolan.org/patch/14626/
* clean libavcodec patch
---
 .../0001-d3d11va-use-the-proper-slice-index.patch  | 89 ++++++++++++++++++++++
 ...d3d11va-use-the-proper-slice-index.patch.ffmpeg | 89 ++++++++++++++++++++++
 contrib/src/ffmpeg/rules.mak                       |  2 +
 modules/codec/avcodec/d3d11va.c                    |  2 +
 4 files changed, 182 insertions(+)
 create mode 100644 contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch
 create mode 100644 contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch.ffmpeg

diff --git a/contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch b/contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch
new file mode 100644
index 0000000..9f682a7
--- /dev/null
+++ b/contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch
@@ -0,0 +1,89 @@
+From f71e0b2d9dc1c6a8b357fa43b811875e57ea1881 Mon Sep 17 00:00:00 2001
+From: Steve Lhomme <robux4 at videolabs.io>
+Date: Tue, 4 Oct 2016 16:41:22 +0200
+Subject: [PATCH] d3d11va: use the proper slice index
+
+The slice index expected by D3D11VA is the one from the texture not from the
+array or texture/slices.
+
+In VLC the slices we provide the decoder don't start from 0 and thus pictures
+appear in bogus order. With possible crashes and corruptions when using an
+invalid index.
+
+--
+* forgot to bump the micro version
+* get rid of DXVA_CONTEXT_SURFACE
+---
+ libavcodec/dxva2.c          | 12 +++++++++++-
+ libavcodec/dxva2_internal.h |  3 ---
+ libavcodec/version.h        |  2 +-
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
+index 9157094..2fc5f47 100644
+--- a/libavcodec/dxva2.c
++++ b/libavcodec/dxva2.c
+@@ -42,8 +42,18 @@ unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
+     unsigned i;
+ 
+     for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++)
+-        if (DXVA_CONTEXT_SURFACE(avctx, ctx, i) == surface)
++#if CONFIG_D3D11VA
++        if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD && ctx->d3d11va.surface[i] == surface)
++        {
++            D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
++            ID3D11VideoDecoderOutputView_GetDesc(ctx->d3d11va.surface[i], &viewDesc);
++            return viewDesc.Texture2D.ArraySlice;
++        }
++#endif
++#if CONFIG_DXVA2
++        if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface)
+             return i;
++#endif
+ 
+     assert(0);
+     return 0;
+diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
+index 30aec8b..f0fe3d6 100644
+--- a/libavcodec/dxva2_internal.h
++++ b/libavcodec/dxva2_internal.h
+@@ -69,7 +69,6 @@ typedef union {
+ #if CONFIG_D3D11VA && CONFIG_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)
+@@ -79,7 +78,6 @@ typedef union {
+ #elif CONFIG_DXVA2
+ #define DXVA_CONTEXT_WORKAROUND(avctx, ctx)     (ctx->dxva2.workaround)
+ #define DXVA_CONTEXT_COUNT(avctx, ctx)          (ctx->dxva2.surface_count)
+-#define DXVA_CONTEXT_SURFACE(avctx, ctx, i)     (ctx->dxva2.surface[i])
+ #define DXVA_CONTEXT_DECODER(avctx, ctx)        (ctx->dxva2.decoder)
+ #define DXVA_CONTEXT_REPORT_ID(avctx, ctx)      (*(&ctx->dxva2.report_id))
+ #define DXVA_CONTEXT_CFG(avctx, ctx)            (ctx->dxva2.cfg)
+@@ -89,7 +87,6 @@ typedef union {
+ #elif CONFIG_D3D11VA
+ #define DXVA_CONTEXT_WORKAROUND(avctx, ctx)     (ctx->d3d11va.workaround)
+ #define DXVA_CONTEXT_COUNT(avctx, ctx)          (ctx->d3d11va.surface_count)
+-#define DXVA_CONTEXT_SURFACE(avctx, ctx, i)     (ctx->d3d11va.surface[i])
+ #define DXVA_CONTEXT_DECODER(avctx, ctx)        (ctx->d3d11va.decoder)
+ #define DXVA_CONTEXT_REPORT_ID(avctx, ctx)      (*(&ctx->d3d11va.report_id))
+ #define DXVA_CONTEXT_CFG(avctx, ctx)            (ctx->d3d11va.cfg)
+diff --git a/libavcodec/version.h b/libavcodec/version.h
+index 71ec9ce..6f439c0 100644
+--- a/libavcodec/version.h
++++ b/libavcodec/version.h
+@@ -28,7 +28,7 @@
+ #include "libavutil/version.h"
+ 
+ #define LIBAVCODEC_VERSION_MAJOR 57
+-#define LIBAVCODEC_VERSION_MINOR 27
++#define LIBAVCODEC_VERSION_MINOR 28
+ #define LIBAVCODEC_VERSION_MICRO  1
+ 
+ #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
+-- 
+2.7.2.windows.1
+
diff --git a/contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch.ffmpeg b/contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch.ffmpeg
new file mode 100644
index 0000000..dc52750
--- /dev/null
+++ b/contrib/src/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch.ffmpeg
@@ -0,0 +1,89 @@
+From c5d58c2efb4c8d017b51de5d12d17866563416bb Mon Sep 17 00:00:00 2001
+From: Steve Lhomme <robux4 at videolabs.io>
+Date: Tue, 4 Oct 2016 16:40:54 +0200
+Subject: [PATCH] d3d11va: use the proper slice index
+
+The slice index expected by D3D11VA is the one from the texture not from the
+array or texture/slices.
+
+In VLC the slices we provide the decoder don't start from 0 and thus pictures
+appear in bogus order. With possible crashes and corruptions when using an
+invalid index.
+
+--
+* forgot to bump the micro version
+* get rid of DXVA_CONTEXT_SURFACE
+---
+ libavcodec/dxva2.c          | 12 +++++++++++-
+ libavcodec/dxva2_internal.h |  3 ---
+ libavcodec/version.h        |  2 +-
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
+index f68df86..e168233 100644
+--- a/libavcodec/dxva2.c
++++ b/libavcodec/dxva2.c
+@@ -42,8 +42,18 @@ unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx,
+     unsigned i;
+ 
+     for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++)
+-        if (DXVA_CONTEXT_SURFACE(avctx, ctx, i) == surface)
++#if CONFIG_D3D11VA
++        if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD && ctx->d3d11va.surface[i] == surface)
++        {
++            D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
++            ID3D11VideoDecoderOutputView_GetDesc(ctx->d3d11va.surface[i], &viewDesc);
++            return viewDesc.Texture2D.ArraySlice;
++        }
++#endif
++#if CONFIG_DXVA2
++        if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface)
+             return i;
++#endif
+ 
+     assert(0);
+     return 0;
+diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
+index ad89f82..24adb99 100644
+--- a/libavcodec/dxva2_internal.h
++++ b/libavcodec/dxva2_internal.h
+@@ -70,7 +70,6 @@ typedef union {
+ #if CONFIG_D3D11VA && CONFIG_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)
+@@ -80,7 +79,6 @@ typedef union {
+ #elif CONFIG_DXVA2
+ #define DXVA_CONTEXT_WORKAROUND(avctx, ctx)     (ctx->dxva2.workaround)
+ #define DXVA_CONTEXT_COUNT(avctx, ctx)          (ctx->dxva2.surface_count)
+-#define DXVA_CONTEXT_SURFACE(avctx, ctx, i)     (ctx->dxva2.surface[i])
+ #define DXVA_CONTEXT_DECODER(avctx, ctx)        (ctx->dxva2.decoder)
+ #define DXVA_CONTEXT_REPORT_ID(avctx, ctx)      (*(&ctx->dxva2.report_id))
+ #define DXVA_CONTEXT_CFG(avctx, ctx)            (ctx->dxva2.cfg)
+@@ -90,7 +88,6 @@ typedef union {
+ #elif CONFIG_D3D11VA
+ #define DXVA_CONTEXT_WORKAROUND(avctx, ctx)     (ctx->d3d11va.workaround)
+ #define DXVA_CONTEXT_COUNT(avctx, ctx)          (ctx->d3d11va.surface_count)
+-#define DXVA_CONTEXT_SURFACE(avctx, ctx, i)     (ctx->d3d11va.surface[i])
+ #define DXVA_CONTEXT_DECODER(avctx, ctx)        (ctx->d3d11va.decoder)
+ #define DXVA_CONTEXT_REPORT_ID(avctx, ctx)      (*(&ctx->d3d11va.report_id))
+ #define DXVA_CONTEXT_CFG(avctx, ctx)            (ctx->d3d11va.cfg)
+diff --git a/libavcodec/version.h b/libavcodec/version.h
+index de7280f..7e30a16 100644
+--- a/libavcodec/version.h
++++ b/libavcodec/version.h
+@@ -28,7 +28,7 @@
+ #include "libavutil/version.h"
+ 
+ #define LIBAVCODEC_VERSION_MAJOR  57
+-#define LIBAVCODEC_VERSION_MINOR  60
++#define LIBAVCODEC_VERSION_MINOR  61
+ #define LIBAVCODEC_VERSION_MICRO 101
+ 
+ #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
+-- 
+2.7.2.windows.1
+
diff --git a/contrib/src/ffmpeg/rules.mak b/contrib/src/ffmpeg/rules.mak
index e4178c6..e82b652 100644
--- a/contrib/src/ffmpeg/rules.mak
+++ b/contrib/src/ffmpeg/rules.mak
@@ -8,6 +8,7 @@ ifdef USE_FFMPEG
 FFMPEG_HASH=HEAD
 FFMPEG_SNAPURL := http://git.videolan.org/?p=ffmpeg.git;a=snapshot;h=$(FFMPEG_HASH);sf=tgz
 FFMPEG_GITURL := git://git.videolan.org/ffmpeg.git
+PATCH_SUFFIX =.ffmpeg
 else
 FFMPEG_HASH=HEAD
 FFMPEG_SNAPURL := http://git.libav.org/?p=libav.git;a=snapshot;h=$(FFMPEG_HASH);sf=tgz
@@ -216,6 +217,7 @@ ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.xz .sum-ffmpeg
 	rm -Rf $@ $@-$(FFMPEG_HASH)
 	mkdir -p $@-$(FFMPEG_HASH)
 	$(XZCAT) "$<" | (cd $@-$(FFMPEG_HASH) && tar xv --strip-components=1)
+	$(APPLY) $(SRC)/ffmpeg/0001-d3d11va-use-the-proper-slice-index.patch$(PATCH_SUFFIX)
 	$(MOVE)
 
 .ffmpeg: ffmpeg
diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index 98e9e03..dffe253 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -1007,6 +1007,7 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
             assert(texDesc.Format == sys->render);
             assert(texDesc.BindFlags & D3D11_BIND_DECODER);
 
+#if !LIBAVCODEC_VERSION_CHECK( 57, 28 ,0, 61 ,100 )
             if (pic->p_sys->slice_index != surface_idx)
             {
                 msg_Warn(va, "d3d11va requires decoding slices to be the first in the texture (%d/%d)",
@@ -1014,6 +1015,7 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
                 sys->b_extern_pool = false;
                 break;
             }
+#endif
 
             viewDesc.Texture2D.ArraySlice = pic->p_sys->slice_index;
             hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec,
-- 
2.7.2.windows.1



More information about the vlc-devel mailing list