[vlc-devel] [PATCH 09/11] d3d11_deinterlace: make use of the global context when there's none in the picture

Steve Lhomme robux4 at videolabs.io
Thu Nov 16 11:38:55 CET 2017


When mixed with another D3D11 filter the peeked picture_t comes from a pool that
is (currently) not created by the vout and thus doesn't have a picture_sys_t.
---
 modules/video_output/win32/d3d11_deinterlace.c | 131 ++++++++++++++++++++-----
 1 file changed, 109 insertions(+), 22 deletions(-)

diff --git a/modules/video_output/win32/d3d11_deinterlace.c b/modules/video_output/win32/d3d11_deinterlace.c
index 438c4b836e..aba2b91602 100644
--- a/modules/video_output/win32/d3d11_deinterlace.c
+++ b/modules/video_output/win32/d3d11_deinterlace.c
@@ -199,12 +199,20 @@ static int RenderPic( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic,
     if (FAILED(hr))
         return VLC_EGENERIC;
 
+    D3D11_BOX box = {
+        .top = 0,
+        .bottom = p_outpic->format.i_visible_height,
+        .left = 0,
+        .right = p_outpic->format.i_visible_width,
+        .back = 1,
+    };
+
     ID3D11DeviceContext_CopySubresourceRegion(p_outpic->p_sys->context,
                                               p_outpic->p_sys->resource[KNOWN_DXGI_INDEX],
                                               p_outpic->p_sys->slice_index,
                                               0, 0, 0,
                                               p_sys->outResource,
-                                              0, NULL);
+                                              0, &box);
     return VLC_SUCCESS;
 }
 
@@ -266,8 +274,65 @@ static picture_t *NewOutputPicture( filter_t *p_filter )
     picture_t *pic = p_filter->p_sys->buffer_new( p_filter );
     if ( !pic->context )
     {
+        d3d11_handle_t hd3d11 = {0};
+        bool b_local_texture = false;
+
+        if ( !pic->p_sys )
+        {
+            pic->p_sys = calloc(1, sizeof(*pic->p_sys));
+            if (unlikely(pic->p_sys == NULL))
+                return NULL;
+
+            HRESULT hr;
+            hr = ID3D11VideoDevice_QueryInterface(p_filter->p_sys->d3dviddev, &IID_ID3D11Device, (void **)&hd3d11.d3ddevice);
+            if (FAILED(hr)) {
+                msg_Err(p_filter, "no global context found");
+                free(pic->p_sys);
+                return NULL;
+            }
+
+            hr = ID3D11VideoContext_QueryInterface(p_filter->p_sys->d3dvidctx, &IID_ID3D11DeviceContext, (void **)&hd3d11.d3dcontext);
+            if (FAILED(hr)) {
+                msg_Err(p_filter, "no global context found");
+                free(pic->p_sys);
+                ID3D11Device_Release(hd3d11.d3ddevice);
+                return NULL;
+            }
+
+            D3D11_TEXTURE2D_DESC dstDesc;
+            ID3D11Texture2D_GetDesc(p_filter->p_sys->outTexture, &dstDesc);
+
+            const d3d_format_t *cfg = NULL;
+            for (const d3d_format_t *output_format = GetRenderFormatList();
+                 output_format->name != NULL; ++output_format)
+            {
+                if (output_format->formatTexture == dstDesc.Format &&
+                    is_d3d11_opaque(output_format->fourcc))
+                {
+                    cfg = output_format;
+                    break;
+                }
+            }
+
+            /* create the texture that's missing */
+            video_format_t fmt = p_filter->fmt_out.video;
+            fmt.i_width  = dstDesc.Width;
+            fmt.i_height = dstDesc.Height;
+            if (AllocateTextures(VLC_OBJECT(p_filter), &hd3d11, cfg,
+                                 &fmt, 1, pic->p_sys->texture) != VLC_SUCCESS)
+            {
+                free(pic->p_sys);
+                ID3D11Device_Release(hd3d11.d3ddevice);
+                ID3D11DeviceContext_Release(hd3d11.d3dcontext);
+                return NULL;
+            }
+            b_local_texture = true;
+
+            pic->p_sys->context = hd3d11.d3dcontext;
+            pic->p_sys->formatTexture = dstDesc.Format;
+
+        }
         /* the picture might be duplicated for snapshots so it needs a context */
-        assert( pic->p_sys != NULL ); /* this opaque picture is wrong */
         struct va_pic_context *pic_ctx = calloc(1, sizeof(*pic_ctx));
         if (likely(pic_ctx!=NULL))
         {
@@ -277,6 +342,14 @@ static picture_t *NewOutputPicture( filter_t *p_filter )
             AcquirePictureSys( &pic_ctx->picsys );
             pic->context = &pic_ctx->s;
         }
+        if (b_local_texture) {
+            for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++) {
+                if (pic->p_sys->texture[i])
+                    ID3D11Texture2D_Release(pic->p_sys->texture[i]);
+            }
+            ID3D11Device_Release(hd3d11.d3ddevice);
+            ID3D11DeviceContext_Release(hd3d11.d3dcontext);
+        }
     }
     return pic;
 }
@@ -286,6 +359,7 @@ static int Open(vlc_object_t *obj)
     filter_t *filter = (filter_t *)obj;
     HRESULT hr;
     ID3D11Device *d3ddevice = NULL;
+    ID3D11DeviceContext *d3dcontext = NULL;
     ID3D11VideoProcessorEnumerator *processorEnumerator = NULL;
 
     if (filter->fmt_in.video.i_chroma != VLC_CODEC_D3D11_OPAQUE
@@ -294,35 +368,48 @@ static int Open(vlc_object_t *obj)
     if (!video_format_IsSimilar(&filter->fmt_in.video, &filter->fmt_out.video))
         return VLC_EGENERIC;
 
+    filter_sys_t *sys = malloc(sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+    memset(sys, 0, sizeof (*sys));
+
     picture_t *dst = filter_NewPicture(filter);
     if (dst == NULL)
         return VLC_EGENERIC;
+
+    D3D11_TEXTURE2D_DESC dstDesc;
     if (!dst->p_sys)
     {
-        msg_Dbg(filter, "D3D11 opaque without a texture");
-        picture_Release(dst);
-        return VLC_EGENERIC;
+        d3dcontext = var_InheritAddress(filter, D3D11_GLOBAL_CONTEXT_NAME);
+        if (d3dcontext == NULL)
+        {
+            msg_Err(filter, "D3D11 opaque without a texture or context");
+            goto error;
+        }
+        msg_Warn(filter, "D3D11 opaque without a texture");
+        if (filter->fmt_in.video.i_chroma == VLC_CODEC_D3D11_OPAQUE_10B)
+            dstDesc.Format = DXGI_FORMAT_P010;
+        else
+            dstDesc.Format = DXGI_FORMAT_NV12;
+        dstDesc.Width  = filter->fmt_out.video.i_width;
+        dstDesc.Height = filter->fmt_out.video.i_height;
+    }
+    else
+    {
+        ID3D11Texture2D_GetDesc(dst->p_sys->texture[KNOWN_DXGI_INDEX], &dstDesc);
+        d3dcontext = dst->p_sys->context;
     }
 
-    D3D11_TEXTURE2D_DESC dstDesc;
-    ID3D11Texture2D_GetDesc(dst->p_sys->texture[KNOWN_DXGI_INDEX], &dstDesc);
-
-    filter_sys_t *sys = malloc(sizeof (*sys));
-    if (unlikely(sys == NULL))
-        goto error;
-    memset(sys, 0, sizeof (*sys));
-
-    ID3D11DeviceContext_GetDevice(dst->p_sys->context, &d3ddevice);
-
-    hr = ID3D11Device_QueryInterface(d3ddevice, &IID_ID3D11VideoDevice, (void **)&sys->d3dviddev);
+    ID3D11DeviceContext_GetDevice(d3dcontext, &d3ddevice);
+    hr = ID3D11DeviceContext_QueryInterface(d3dcontext, &IID_ID3D11VideoContext, (void **)&sys->d3dvidctx);
     if (FAILED(hr)) {
-       msg_Err(filter, "Could not Query ID3D11VideoDevice Interface. (hr=0x%lX)", hr);
+       msg_Err(filter, "Could not Query ID3D11VideoContext Interface from the picture. (hr=0x%lX)", hr);
        goto error;
     }
 
-    hr = ID3D11DeviceContext_QueryInterface(dst->p_sys->context, &IID_ID3D11VideoContext, (void **)&sys->d3dvidctx);
+    hr = ID3D11Device_QueryInterface(d3ddevice, &IID_ID3D11VideoDevice, (void **)&sys->d3dviddev);
     if (FAILED(hr)) {
-       msg_Err(filter, "Could not Query ID3D11VideoContext Interface from the picture. (hr=0x%lX)", hr);
+       msg_Err(filter, "Could not Query ID3D11VideoDevice Interface. (hr=0x%lX)", hr);
        goto error;
     }
 
@@ -368,16 +455,16 @@ static int Open(vlc_object_t *obj)
             msg_Dbg(filter, "processor format %s (%d) is supported for output", DxgiFormatToStr(format),format);
     }
 #endif
-    hr = ID3D11VideoProcessorEnumerator_CheckVideoProcessorFormat(processorEnumerator, dst->p_sys->formatTexture, &flags);
+    hr = ID3D11VideoProcessorEnumerator_CheckVideoProcessorFormat(processorEnumerator, dstDesc.Format, &flags);
     if (!SUCCEEDED(hr))
     {
-        msg_Dbg(filter, "can't read processor support for %s", DxgiFormatToStr(dst->p_sys->formatTexture));
+        msg_Dbg(filter, "can't read processor support for %s", DxgiFormatToStr(dstDesc.Format));
         goto error;
     }
     if ( !(flags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT) ||
          !(flags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT) )
     {
-        msg_Dbg(filter, "deinterlacing %s is not supported", DxgiFormatToStr(dst->p_sys->formatTexture));
+        msg_Dbg(filter, "deinterlacing %s is not supported", DxgiFormatToStr(dstDesc.Format));
         goto error;
     }
 
-- 
2.14.2



More information about the vlc-devel mailing list