[vlc-devel] [PATCH 14/36] dxa9: create the output video context for CPU to D3D9 converters

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


Use the d3d9_device_t from the decoder device.
---
 modules/hw/d3d9/dxa9.c | 155 ++++++++++++++++++++++++++---------------
 1 file changed, 97 insertions(+), 58 deletions(-)

diff --git a/modules/hw/d3d9/dxa9.c b/modules/hw/d3d9/dxa9.c
index 2ff00276bb3..0797a67b63b 100644
--- a/modules/hw/d3d9/dxa9.c
+++ b/modules/hw/d3d9/dxa9.c
@@ -47,8 +47,6 @@ typedef struct
     copy_cache_t      cache;
 
     /* CPU to GPU */
-    d3d9_handle_t     hd3d;
-    d3d9_device_t     d3d_dev;
     filter_t          *filter;
     picture_t         *staging;
 } filter_sys_t;
@@ -257,10 +255,12 @@ static void YV12_D3D9(filter_t *p_filter, picture_t *src, picture_t *dst)
 
     IDirect3DSurface9_UnlockRect(p_staging_sys->surface);
 
+    d3d9_decoder_device_t *d3d9_decoder = GetD3D9OpaqueContext(p_filter->vctx_out);
+
     RECT visibleSource = {
         .right = dst->format.i_width, .bottom = dst->format.i_height,
     };
-    IDirect3DDevice9_StretchRect( sys->d3d_dev.dev,
+    IDirect3DDevice9_StretchRect( d3d9_decoder->d3ddev.dev,
                                   p_staging_sys->surface, &visibleSource,
                                   p_sys->surface, &visibleSource,
                                   D3DTEXF_NONE );
@@ -336,13 +336,6 @@ int D3D9OpenConverter( vlc_object_t *obj )
         return VLC_ENOMEM;
     }
 
-    if (unlikely(D3D9_Create( p_filter, &p_sys->hd3d ) != VLC_SUCCESS)) {
-        msg_Warn(p_filter, "cannot load d3d9.dll, aborting");
-        CopyCleanCache(&p_sys->cache);
-        free(p_sys);
-        return VLC_EGENERIC;
-    }
-
     p_filter->p_sys = p_sys;
     return VLC_SUCCESS;
 }
@@ -375,65 +368,114 @@ int D3D9OpenCPUConverter( vlc_object_t *obj )
         return VLC_EGENERIC;
     }
 
+    vlc_decoder_device *dec_device = filter_HoldDecoderDevice( p_filter );
+    if (dec_device == NULL)
+    {
+        msg_Err(p_filter, "Missing decoder device");
+        return VLC_EGENERIC;
+    }
+    d3d9_decoder_device_t *devsys = GetD3D9OpaqueDevice(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;
+    }
+
     filter_sys_t *p_sys = calloc(1, sizeof(filter_sys_t));
     if (!p_sys)
-         return VLC_ENOMEM;
+    {
+        vlc_decoder_device_Release(dec_device);
+        return VLC_ENOMEM;
+    }
 
     video_format_Init(&fmt_staging, 0);
-    if (unlikely(D3D9_Create( p_filter, &p_sys->hd3d ) != VLC_SUCCESS)) {
-        msg_Warn(p_filter, "cannot load d3d9.dll, aborting");
-        free(p_sys);
-        return VLC_EGENERIC;
-    }
 
-    D3DSURFACE_DESC texDesc;
-    D3D9_FilterHoldInstance(p_filter, &p_sys->d3d_dev, &texDesc);
-    if (!p_sys->d3d_dev.dev)
+    p_filter->vctx_out = vlc_video_context_Create( dec_device, VLC_VIDEO_CONTEXT_DXVA2, sizeof(d3d9_video_context_t),
+                                                   &d3d9_vctx_ops );
+    vlc_decoder_device_Release(dec_device);
+
+    if ( p_filter->vctx_out == NULL )
     {
-        msg_Dbg(p_filter, "Filter without a context");
+        msg_Err(p_filter, "Failed to create the video context");
         goto done;
     }
-    if (texDesc.Format == 0)
-        goto done;
 
-    if ( p_filter->fmt_in.video.i_chroma != texDesc.Format )
-    {
-        picture_resource_t res = {
-            .pf_destroy = DestroyPicture,
-        };
-        picture_sys_d3d9_t *res_sys = calloc(1, sizeof(picture_sys_d3d9_t));
-        if (res_sys == NULL) {
-            err = VLC_ENOMEM;
-            goto done;
-        }
-        res.p_sys = res_sys;
-
-        video_format_Copy(&fmt_staging, &p_filter->fmt_out.video);
-        fmt_staging.i_chroma = texDesc.Format;
-        fmt_staging.i_height = texDesc.Height;
-        fmt_staging.i_width  = texDesc.Width;
+    d3d9_video_context_t *vctx_sys = GetD3D9ContextPrivate( p_filter->vctx_out );
 
-        p_dst = picture_NewFromResource(&fmt_staging, &res);
-        if (p_dst == NULL) {
-            msg_Err(p_filter, "Failed to map create the temporary picture.");
-            goto done;
-        }
-        picture_Setup(p_dst, &p_dst->format);
+    static const D3DFORMAT outputFormats8[] = {
+        MAKEFOURCC('I','4','2','0'),
+        MAKEFOURCC('Y','V','1','2'),
+        MAKEFOURCC('N','V','1','2'),
+        D3DFMT_UNKNOWN
+    };
+    static const D3DFORMAT outputFormats10[] = {
+        MAKEFOURCC('P','0','1','0'),
+        MAKEFOURCC('I','4','2','0'),
+        MAKEFOURCC('Y','V','1','2'),
+        MAKEFOURCC('N','V','1','2'),
+        D3DFMT_UNKNOWN
+    };
 
-        HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_sys->d3d_dev.dev,
-                                                          p_dst->format.i_width,
-                                                          p_dst->format.i_height,
-                                                          texDesc.Format,
+    vctx_sys->format = D3DFMT_UNKNOWN;
+    const D3DFORMAT *list;
+    switch( p_filter->fmt_in.video.i_chroma ) {
+    case VLC_CODEC_I420:
+    case VLC_CODEC_YV12:
+        list = outputFormats8;
+        break;
+    case VLC_CODEC_I420_10L:
+    case VLC_CODEC_P010:
+        list = outputFormats10;
+        break;
+    default:
+        vlc_assert_unreachable();
+    }
+    while (*list != D3DFMT_UNKNOWN)
+    {
+        HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(devsys->d3ddev.dev,
+                                                          p_filter->fmt_out.video.i_width,
+                                                          p_filter->fmt_out.video.i_height,
+                                                          *list,
                                                           D3DPOOL_DEFAULT,
                                                           &texture,
                                                           NULL);
-        if (FAILED(hr)) {
-            msg_Err(p_filter, "Failed to create a %4.4s staging texture to extract surface pixels (hr=0x%lX)", (char *)texDesc.Format, hr );
-            goto done;
+        if (SUCCEEDED(hr)) {
+            vctx_sys->format = *list;
+            msg_Dbg(p_filter, "using pixel format %4.4s", (char*)&vctx_sys->format);
+            break;
         }
-        res_sys->surface = texture;
-        IDirect3DSurface9_AddRef(texture);
+        list++;
+    }
+    if (vctx_sys->format == D3DFMT_UNKNOWN)
+    {
+        msg_Err(p_filter, "Failed to find a usable pixel format");
+        goto done;
+    }
 
+    picture_resource_t res = {
+        .pf_destroy = DestroyPicture,
+    };
+    picture_sys_d3d9_t *res_sys = calloc(1, sizeof(picture_sys_d3d9_t));
+    if (res_sys == NULL) {
+        err = VLC_ENOMEM;
+        goto done;
+    }
+    res.p_sys = res_sys;
+    res_sys->surface = texture;
+
+    video_format_Copy(&fmt_staging, &p_filter->fmt_out.video);
+    fmt_staging.i_chroma = vctx_sys->format;
+
+    p_dst = picture_NewFromResource(&fmt_staging, &res);
+    if (p_dst == NULL) {
+        msg_Err(p_filter, "Failed to map create the temporary picture.");
+        goto done;
+    }
+    picture_Setup(p_dst, &p_dst->format);
+
+    if ( p_filter->fmt_in.video.i_chroma != vctx_sys->format )
+    {
         p_cpu_filter = CreateFilter(p_filter, &p_filter->fmt_in, p_dst->format.i_chroma);
         if (!p_cpu_filter)
             goto done;
@@ -450,8 +492,7 @@ done:
     {
         if (texture)
             IDirect3DSurface9_Release(texture);
-        D3D9_FilterReleaseInstance(&p_sys->d3d_dev);
-        D3D9_Destroy( &p_sys->hd3d );
+        vlc_video_context_Release(p_filter->vctx_out);
         free(p_sys);
     }
     return err;
@@ -462,7 +503,6 @@ void D3D9CloseConverter( vlc_object_t *obj )
     filter_t *p_filter = (filter_t *)obj;
     filter_sys_t *p_sys = p_filter->p_sys;
     CopyCleanCache( &p_sys->cache );
-    D3D9_Destroy( &p_sys->hd3d );
     free( p_sys );
     p_filter->p_sys = NULL;
 }
@@ -473,8 +513,7 @@ void D3D9CloseCPUConverter( vlc_object_t *obj )
     filter_sys_t *p_sys = p_filter->p_sys;
     DeleteFilter(p_sys->filter);
     picture_Release(p_sys->staging);
-    D3D9_FilterReleaseInstance(&p_sys->d3d_dev);
-    D3D9_Destroy( &p_sys->hd3d );
+    vlc_video_context_Release(p_filter->vctx_out);
     free( p_sys );
     p_filter->p_sys = NULL;
 }
-- 
2.17.1



More information about the vlc-devel mailing list