[vlc-devel] [PATCH 5/6] d3d11va: attempt to get the decoding buffer slices from the decoder pool

Steve Lhomme robux4 at videolabs.io
Tue Oct 4 17:40:27 CEST 2016


Only works if the slice indices start from 0 which is not the case because
of the reserved pictures in the pool
---
 modules/codec/avcodec/d3d11va.c | 141 +++++++++++++++++++++++++++++++---------
 1 file changed, 111 insertions(+), 30 deletions(-)

diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index 5132e56..89e9b4a 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -43,6 +43,7 @@
 #include <vlc_charset.h>
 #include <vlc_filter.h>
 #include <vlc_modules.h>
+#include <vlc_codec.h>
 
 #include "directx_va.h"
 
@@ -118,6 +119,10 @@ struct vlc_va_sys_t
     ID3D11DeviceContext          *d3dctx;
     HANDLE                       context_mutex;
 
+    /* pool */
+    bool                         b_extern_pool;
+    picture_t                    *extern_pics[MAX_SURFACE_COUNT];
+
     /* Video decoder */
     D3D11_VIDEO_DECODER_CONFIG   cfg;
 
@@ -454,6 +459,7 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
 
             sys->d3dctx = p_sys->context;
             sys->d3dvidctx = d3dvidctx;
+            sys->b_extern_pool = true;
 
             assert(p_sys->texture != NULL);
             D3D11_TEXTURE2D_DESC dstDesc;
@@ -954,45 +960,117 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma
         ID3D10Multithread_Release(pMultithread);
     }
 
-    D3D11_TEXTURE2D_DESC texDesc;
-    ZeroMemory(&texDesc, sizeof(texDesc));
-    texDesc.Width = dx_sys->surface_width;
-    texDesc.Height = dx_sys->surface_height;
-    texDesc.MipLevels = 1;
-    texDesc.Format = sys->render;
-    texDesc.SampleDesc.Count = 1;
-    texDesc.MiscFlags = 0;
-    texDesc.ArraySize = dx_sys->surface_count;
-    texDesc.Usage = D3D11_USAGE_DEFAULT;
-    texDesc.BindFlags = D3D11_BIND_DECODER;
-    texDesc.CPUAccessFlags = 0;
-
-    ID3D11Texture2D *p_texture;
-    hr = ID3D11Device_CreateTexture2D( (ID3D11Device*) dx_sys->d3ddev, &texDesc, NULL, &p_texture );
-    if (FAILED(hr)) {
-        msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr);
-        dx_sys->surface_count = 0;
-        return VLC_EGENERIC;
-    }
-
     D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
     ZeroMemory(&viewDesc, sizeof(viewDesc));
     viewDesc.DecodeProfile = dx_sys->input;
     viewDesc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D;
 
-    int surface_count = dx_sys->surface_count;
-    for (dx_sys->surface_count = 0; dx_sys->surface_count < surface_count; dx_sys->surface_count++) {
-        viewDesc.Texture2D.ArraySlice = dx_sys->surface_count;
+    if (sys->b_extern_pool)
+    {
+        size_t surface_idx;
+        for (surface_idx = 0; surface_idx < dx_sys->surface_count; surface_idx++) {
+            picture_t *pic = decoder_NewPicture( (decoder_t*) va->obj.parent );
+            sys->extern_pics[surface_idx] = pic;
+            dx_sys->hw_surface[surface_idx] = NULL;
+            if (pic==NULL)
+            {
+                msg_Warn(va, "not enough decoder pictures %d out of %d", surface_idx, dx_sys->surface_count);
+                sys->b_extern_pool = false;
+                break;
+            }
 
-        hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec,
-                                                             (ID3D11Resource*) p_texture,
-                                                             &viewDesc,
-                                                             (ID3D11VideoDecoderOutputView**) &dx_sys->hw_surface[dx_sys->surface_count] );
+            D3D11_TEXTURE2D_DESC texDesc;
+            ID3D11Texture2D_GetDesc(pic->p_sys->texture, &texDesc);
+            if (texDesc.ArraySize < dx_sys->surface_count)
+            {
+                msg_Warn(va, "not enough decoding slices in the texture (%d/%d)",
+                         texDesc.ArraySize, dx_sys->surface_count);
+                sys->b_extern_pool = false;
+                break;
+            }
+            assert(texDesc.Format == sys->render);
+            assert(texDesc.BindFlags & D3D11_BIND_DECODER);
+
+            if (pic->p_sys->slice_index != surface_idx)
+            {
+                msg_Warn(va, "d3d11va requires decoding slices to be the first in the texture (%d/%d)",
+                         pic->p_sys->slice_index, surface_idx);
+                sys->b_extern_pool = false;
+                break;
+            }
+
+            viewDesc.Texture2D.ArraySlice = pic->p_sys->slice_index;
+            hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec,
+                                                                 (ID3D11Resource*) pic->p_sys->texture,
+                                                                 &viewDesc,
+                                                                 &pic->p_sys->decoder );
+            if (FAILED(hr)) {
+                msg_Warn(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", surface_idx, hr);
+                sys->b_extern_pool = false;
+                break;
+            }
+            sys->dx_sys.hw_surface[surface_idx] = pic->p_sys->decoder;
+        }
+
+        if (!sys->b_extern_pool)
+        {
+            for (size_t i = 0; i < surface_idx; ++i)
+            {
+                if (dx_sys->hw_surface[i])
+                {
+                    ID3D11VideoDecoderOutputView_Release(dx_sys->hw_surface[i]);
+                    dx_sys->hw_surface[i] = NULL;
+                }
+                if (sys->extern_pics[i])
+                {
+                    sys->extern_pics[i]->p_sys->decoder = NULL;
+                    picture_Release(sys->extern_pics[i]);
+                    sys->extern_pics[i] = NULL;
+                }
+            }
+        }
+        else
+            msg_Dbg(va, "using external surface pool");
+    }
+
+    if (!sys->b_extern_pool)
+    {
+        D3D11_TEXTURE2D_DESC texDesc;
+        ZeroMemory(&texDesc, sizeof(texDesc));
+        texDesc.Width = dx_sys->surface_width;
+        texDesc.Height = dx_sys->surface_height;
+        texDesc.MipLevels = 1;
+        texDesc.Format = sys->render;
+        texDesc.SampleDesc.Count = 1;
+        texDesc.MiscFlags = 0;
+        texDesc.ArraySize = dx_sys->surface_count;
+        texDesc.Usage = D3D11_USAGE_DEFAULT;
+        texDesc.BindFlags = D3D11_BIND_DECODER;
+        texDesc.CPUAccessFlags = 0;
+
+        ID3D11Texture2D *p_texture;
+        hr = ID3D11Device_CreateTexture2D( (ID3D11Device*) dx_sys->d3ddev, &texDesc, NULL, &p_texture );
         if (FAILED(hr)) {
-            msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr);
-            ID3D11Texture2D_Release(p_texture);
+            msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr);
+            dx_sys->surface_count = 0;
             return VLC_EGENERIC;
         }
+
+        int surface_count = dx_sys->surface_count;
+        for (dx_sys->surface_count = 0; dx_sys->surface_count < surface_count; dx_sys->surface_count++) {
+            sys->extern_pics[dx_sys->surface_count] = NULL;
+            viewDesc.Texture2D.ArraySlice = dx_sys->surface_count;
+
+            hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec,
+                                                                 (ID3D11Resource*) p_texture,
+                                                                 &viewDesc,
+                                                                 (ID3D11VideoDecoderOutputView**) &dx_sys->hw_surface[dx_sys->surface_count] );
+            if (FAILED(hr)) {
+                msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr);
+                ID3D11Texture2D_Release(p_texture);
+                return VLC_EGENERIC;
+            }
+        }
     }
     msg_Dbg(va, "ID3D11VideoDecoderOutputView succeed with %d surfaces (%dx%d)",
             dx_sys->surface_count, dx_sys->surface_width, dx_sys->surface_height);
@@ -1092,6 +1170,9 @@ static void DestroyPicture(picture_t *picture)
 static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsigned index)
 {
     vlc_va_sys_t *sys = va->sys;
+    if (sys->b_extern_pool)
+        return sys->extern_pics[index];
+
     video_format_t src_fmt = *fmt;
     src_fmt.i_chroma = sys->i_chroma;
     picture_sys_t *pic_sys = calloc(1, sizeof(*pic_sys));
-- 
2.8.2



More information about the vlc-devel mailing list