[vlc-devel] [PATCH 13/36] d3d11_surface: create the output video context for CPU to D3D11 converters

Steve Lhomme robux4 at ycbcr.xyz
Thu Nov 21 15:14:04 CET 2019


---
 modules/hw/d3d11/d3d11_surface.c | 82 ++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 21 deletions(-)

diff --git a/modules/hw/d3d11/d3d11_surface.c b/modules/hw/d3d11/d3d11_surface.c
index 8b24f34bdfb..da33473ef91 100644
--- a/modules/hw/d3d11/d3d11_surface.c
+++ b/modules/hw/d3d11/d3d11_surface.c
@@ -697,18 +697,63 @@ int D3D11OpenCPUConverter( vlc_object_t *obj )
         return VLC_EGENERIC;
     }
 
-    d3d11_device_t d3d_dev;
-    D3D11_TEXTURE2D_DESC texDesc;
-    D3D11_FilterHoldInstance(p_filter, &d3d_dev, &texDesc);
-    if (unlikely(!d3d_dev.d3dcontext))
+    vlc_decoder_device *dec_device = filter_HoldDecoderDevice( p_filter );
+    if (dec_device == NULL)
+    {
+        msg_Err(p_filter, "Missing decoder device");
+        return VLC_EGENERIC;
+    }
+    d3d11_decoder_device_t *devsys = GetD3D11OpaqueDevice(dec_device);
+    if (devsys == NULL)
+    {
+        msg_Err(p_filter, "Incompatible decoder device %d", dec_device->type);
+        vlc_decoder_device_Release(dec_device);
+        return VLC_EGENERIC;
+    }
+
+    p_sys = vlc_obj_calloc(obj, 1, sizeof(filter_sys_t));
+    if (!p_sys) {
+        vlc_decoder_device_Release(dec_device);
+        return VLC_ENOMEM;
+    }
+
+    HRESULT hr = D3D11_CreateDeviceExternal(p_filter, devsys->device, true, &p_sys->d3d_dev);
+    if (FAILED(hr) || unlikely(!p_sys->d3d_dev.d3dcontext))
     {
         msg_Dbg(p_filter, "D3D11 opaque without a texture");
+        vlc_decoder_device_Release(dec_device);
         return VLC_EGENERIC;
     }
 
     video_format_Init(&fmt_staging, 0);
 
-    vlc_fourcc_t d3d_fourcc = DxgiFormatFourcc(texDesc.Format);
+    p_filter->vctx_out = vlc_video_context_Create(dec_device, VLC_VIDEO_CONTEXT_D3D11VA,
+                                          sizeof(d3d11_video_context_t), &d3d11_vctx_ops);
+    vlc_decoder_device_Release(dec_device);
+
+    if ( p_filter->vctx_out == NULL )
+    {
+        msg_Dbg(p_filter, "no video context");
+        goto done;
+    }
+
+    d3d11_video_context_t *vctx_sys = GetD3D11ContextPrivate( p_filter->vctx_out );
+    switch( p_filter->fmt_in.video.i_chroma ) {
+    case VLC_CODEC_I420:
+    case VLC_CODEC_YV12:
+    case VLC_CODEC_NV12:
+        vctx_sys->format = DXGI_FORMAT_NV12;
+        break;
+    case VLC_CODEC_I420_10L:
+    case VLC_CODEC_P010:
+        vctx_sys->format = DXGI_FORMAT_P010;
+        break;
+    default:
+        vlc_assert_unreachable();
+    }
+    vctx_sys->device = p_sys->d3d_dev.d3dcontext;
+
+    vlc_fourcc_t d3d_fourcc = DxgiFormatFourcc(vctx_sys->format);
     if (d3d_fourcc == 0)
         goto done;
 
@@ -721,13 +766,11 @@ int D3D11OpenCPUConverter( vlc_object_t *obj )
         goto done;
     }
     res.p_sys = res_sys;
-    res_sys->context = d3d_dev.d3dcontext;
-    res_sys->formatTexture = texDesc.Format;
+    res_sys->context = p_sys->d3d_dev.d3dcontext;
+    res_sys->formatTexture = vctx_sys->format;
 
     video_format_Copy(&fmt_staging, &p_filter->fmt_out.video);
     fmt_staging.i_chroma = d3d_fourcc;
-    fmt_staging.i_height = texDesc.Height;
-    fmt_staging.i_width  = texDesc.Width;
 
     picture_t *p_dst = picture_NewFromResource(&fmt_staging, &res);
     if (p_dst == NULL) {
@@ -737,16 +780,20 @@ int D3D11OpenCPUConverter( vlc_object_t *obj )
     picture_sys_d3d11_t *p_dst_sys = p_dst->p_sys;
     picture_Setup(p_dst, &p_dst->format);
 
+    D3D11_TEXTURE2D_DESC texDesc;
+    texDesc.Format = vctx_sys->format;
     texDesc.MipLevels = 1;
     texDesc.SampleDesc.Count = 1;
+    texDesc.SampleDesc.Quality = 0;
     texDesc.MiscFlags = 0;
     texDesc.ArraySize = 1;
     texDesc.Usage = D3D11_USAGE_STAGING;
     texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
     texDesc.BindFlags = 0;
+    texDesc.Width  = p_dst->format.i_width;
     texDesc.Height = p_dst->format.i_height; /* make sure we match picture_Setup() */
 
-    HRESULT hr = ID3D11Device_CreateTexture2D( d3d_dev.d3ddevice, &texDesc, NULL, &texture);
+    hr = ID3D11Device_CreateTexture2D( p_sys->d3d_dev.d3ddevice, &texDesc, NULL, &texture);
     if (FAILED(hr)) {
         msg_Err(p_filter, "Failed to create a %s staging texture to extract surface pixels (hr=0x%lX)", DxgiFormatToStr(texDesc.Format), hr );
         goto done;
@@ -762,12 +809,6 @@ int D3D11OpenCPUConverter( vlc_object_t *obj )
             goto done;
     }
 
-    p_sys = vlc_obj_calloc(obj, 1, sizeof(filter_sys_t));
-    if (!p_sys) {
-         err = VLC_ENOMEM;
-         goto done;
-    }
-
     if (D3D11_Create(p_filter, &p_sys->hd3d, false) != VLC_SUCCESS)
     {
         msg_Warn(p_filter, "cannot load d3d11.dll, aborting");
@@ -787,11 +828,8 @@ done:
             DeleteFilter( p_cpu_filter );
         if (texture)
             ID3D11Texture2D_Release(texture);
-        D3D11_FilterReleaseInstance(&d3d_dev);
-    }
-    else
-    {
-        p_sys->d3d_dev = d3d_dev;
+        vlc_video_context_Release(p_filter->vctx_out);
+        D3D11_ReleaseDevice(&p_sys->d3d_dev);
     }
     return err;
 }
@@ -819,5 +857,7 @@ void D3D11CloseCPUConverter( vlc_object_t *obj )
     filter_sys_t *p_sys = p_filter->p_sys;
     DeleteFilter(p_sys->filter);
     picture_Release(p_sys->staging_pic);
+    vlc_video_context_Release(p_filter->vctx_out);
+    D3D11_ReleaseDevice(&p_sys->d3d_dev);
     D3D11_Destroy(&p_sys->hd3d);
 }
-- 
2.17.1



More information about the vlc-devel mailing list