[vlc-devel] [PATCH 8/8] libvlc: use a callback to select the plane to render to

Steve Lhomme robux4 at ycbcr.xyz
Thu May 9 16:28:07 CEST 2019


In Direct3D11
When rendering to NV12 we use 2 planes in the same texture
When rendering to I420 we use 3 planes in different textures
---
 doc/libvlc/d3d11_player.cpp             | 11 +++++++++-
 doc/libvlc/d3d9_player.c                |  2 +-
 include/vlc/libvlc_media_player.h       | 17 ++++++++++++++++
 lib/media_player.c                      |  3 +++
 modules/video_output/win32/d3d11_quad.c |  9 ++++-----
 modules/video_output/win32/d3d11_quad.h |  4 +++-
 modules/video_output/win32/direct3d11.c | 27 ++++++++++++++++++++-----
 7 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/doc/libvlc/d3d11_player.cpp b/doc/libvlc/d3d11_player.cpp
index a1aca891ab..48613fc5e9 100644
--- a/doc/libvlc/d3d11_player.cpp
+++ b/doc/libvlc/d3d11_player.cpp
@@ -172,6 +172,15 @@ static bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_dire
     return true;
 }
 
+static bool SelectPlane_cb( void *opaque, size_t plane )
+{
+    struct render_context *ctx = static_cast<struct render_context *>( opaque );
+    if ( plane != 0 ) // we only support one packed RGBA plane (DXGI_FORMAT_R8G8B8A8_UNORM)
+        return false;
+    ctx->d3dctx->OMSetRenderTargets( 1, &ctx->textureRenderTarget, NULL );
+    return true;
+}
+
 static bool Setup_cb( void *opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
 {
     struct render_context *ctx = static_cast<struct render_context *>(opaque);
@@ -442,7 +451,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
 
     /* Tell VLC to render into our D3D11 environment */
     libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d11,
-                                        Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb,
+                                        Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, SelectPlane_cb,
                                         &Context );
 
     libvlc_media_player_play( p_mp );
diff --git a/doc/libvlc/d3d9_player.c b/doc/libvlc/d3d9_player.c
index 1472885779..c943289d62 100644
--- a/doc/libvlc/d3d9_player.c
+++ b/doc/libvlc/d3d9_player.c
@@ -349,7 +349,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
 
     /* Tell VLC to render into our D3D9 environment */
     libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d9,
-                                        Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb,
+                                        Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, NULL, 
                                         &Context );
 
     libvlc_media_player_play( p_mp );
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index cebe81f9fa..cb6816797a 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -736,6 +736,22 @@ typedef struct
  */
 typedef bool( *libvlc_video_direct3d_start_end_rendering_cb )( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 );
 
+/** Tell the host the rendering for the given plane is about to start
+ *
+ * \param opaque private pointer passed to the @a libvlc_video_direct3d_set_callbacks() [IN]
+ * \param plane number of the rendering plane to select
+ * \return true on success
+ * \version LibVLC 4.0.0 or later
+ *
+ * \note This is only used with \ref libvlc_video_rendering_direct3d11.
+ *
+ * The host should call OMSetRenderTargets for Direct3D11.
+ *
+ * The number of planes depend on the DXGI_FORMAT returned during the
+ * \ref LIBVLC_VIDEO_UPDATE_OUTPUT call. It's usually one plane except for
+ * semi-planar formats like DXGI_FORMAT_NV12 or DXGI_FORMAT_P010.
+ */
+typedef bool( *libvlc_video_direct3d_select_plane_cb )( void *opaque, size_t plane );
 
 /**
  * Set callbacks and data to render decoded video to a custom Direct3D output
@@ -758,6 +774,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
                                         libvlc_video_direct3d_update_output_cb update_output_cb,
                                         libvlc_video_swap_cb swap_cb,
                                         libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb,
+                                        libvlc_video_direct3d_select_plane_cb select_plane_cb,
                                         void* opaque );
 
 /**
diff --git a/lib/media_player.c b/lib/media_player.c
index 1172055a14..fb18da1893 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -646,6 +646,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     var_Create( mp, "vout-cb-swap", VLC_VAR_ADDRESS );
     var_Create( mp, "vout-cb-get-proc-address", VLC_VAR_ADDRESS );
     var_Create( mp, "vout-cb-make-current", VLC_VAR_ADDRESS );
+    var_Create( mp, "vout-cb-select-plane", VLC_VAR_ADDRESS );
 
     var_Create (mp, "avcodec-hw", VLC_VAR_STRING);
     var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
@@ -1209,6 +1210,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
                                         libvlc_video_direct3d_update_output_cb update_output_cb,
                                         libvlc_video_swap_cb swap_cb,
                                         libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb,
+                                        libvlc_video_direct3d_select_plane_cb select_plane_cb,
                                         void* opaque )
 {
     var_SetString( mp, "window", "wdummy");
@@ -1232,6 +1234,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
     var_SetAddress( mp, "vout-cb-update-output", update_output_cb );
     var_SetAddress( mp, "vout-cb-swap", swap_cb );
     var_SetAddress( mp, "vout-cb-make-current", makeCurrent_cb );
+    var_SetAddress( mp, "vout-cb-select-plane", select_plane_cb );
     return 1;
 }
 
diff --git a/modules/video_output/win32/d3d11_quad.c b/modules/video_output/win32/d3d11_quad.c
index d51781fc96..9ee7661027 100644
--- a/modules/video_output/win32/d3d11_quad.c
+++ b/modules/video_output/win32/d3d11_quad.c
@@ -44,7 +44,7 @@
 
 void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vshader_t *vsshader,
                       ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW],
-                      ID3D11RenderTargetView *d3drenderTargetView[D3D11_MAX_RENDER_TARGET])
+                      d3d11_select_plane_t selectPlane, void *selectOpaque)
 {
     UINT offset = 0;
 
@@ -73,14 +73,13 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vshader_t *
         if (!quad->d3dpixelShader[i])
             break;
 
+        if (unlikely(!selectPlane(selectOpaque, i)))
+            continue;
+
         ID3D11DeviceContext_PSSetShader(d3d_dev->d3dcontext, quad->d3dpixelShader[i], NULL, 0);
 
         ID3D11DeviceContext_RSSetViewports(d3d_dev->d3dcontext, 1, &quad->cropViewport[i]);
 
-        if (d3drenderTargetView[0])
-            /* TODO: handle outside selection of the render sub-target */
-            ID3D11DeviceContext_OMSetRenderTargets(d3d_dev->d3dcontext, 1, &d3drenderTargetView[i], NULL);
-
         ID3D11DeviceContext_DrawIndexed(d3d_dev->d3dcontext, quad->indexCount, 0, 0);
     }
 
diff --git a/modules/video_output/win32/d3d11_quad.h b/modules/video_output/win32/d3d11_quad.h
index 3e8e82b59a..b0d04aef7e 100644
--- a/modules/video_output/win32/d3d11_quad.h
+++ b/modules/video_output/win32/d3d11_quad.h
@@ -45,9 +45,11 @@ typedef struct d3d_vertex_t {
     } texture;
 } d3d_vertex_t;
 
+typedef bool (*d3d11_select_plane_t)(void *opaque, size_t plane_index);
+
 void D3D11_RenderQuad(d3d11_device_t *, d3d_quad_t *, d3d_vshader_t *,
                       ID3D11ShaderResourceView *resourceViews[D3D11_MAX_SHADER_VIEW],
-                      ID3D11RenderTargetView *renderTarget[D3D11_MAX_RENDER_TARGET]);
+                      d3d11_select_plane_t selectPlane, void *selectOpaque);
 
 int D3D11_AllocateQuad(vlc_object_t *, d3d11_device_t *, video_projection_mode_t, d3d_quad_t *);
 #define D3D11_AllocateQuad(a,b,c,d)  D3D11_AllocateQuad(VLC_OBJECT(a),b,c,d)
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 9f5f9f4de2..f10599fe9b 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -167,6 +167,7 @@ struct vout_display_sys_t
     libvlc_video_direct3d_update_output_cb   updateOutputCb;
     libvlc_video_swap_cb                     swapCb;
     libvlc_video_direct3d_start_end_rendering_cb startEndRenderingCb;
+    libvlc_video_direct3d_select_plane_cb    selectPlaneCb;
 };
 
 static picture_pool_t *Pool(vout_display_t *, unsigned);
@@ -634,6 +635,16 @@ static bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const lib
     return true;
 }
 
+static bool LocalSwapchainSelectPlane( void *opaque, size_t plane )
+{
+    struct d3d11_local_swapchain *display = opaque;
+    if (!display->swapchainTargetView[plane])
+        return false;
+    ID3D11DeviceContext_OMSetRenderTargets(display->d3d_dev.d3dcontext, 1,
+                                            &display->swapchainTargetView[plane], NULL);
+    return true;
+}
+
 static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
                 video_format_t *fmtp, vlc_video_context *context)
 {
@@ -664,9 +675,10 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
     sys->updateOutputCb      = var_InheritAddress( vd, "vout-cb-update-output" );
     sys->swapCb              = var_InheritAddress( vd, "vout-cb-swap" );
     sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" );
+    sys->selectPlaneCb       = var_InheritAddress( vd, "vout-cb-select-plane" );
 
     bool uses_external_callbacks = true;
-    if (sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL)
+    if (sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL || sys->selectPlaneCb == NULL )
     {
         sys->internal_swapchain.obj = VLC_OBJECT(vd);
         sys->internal_swapchain.hd3d =  &sys->hd3d;
@@ -676,6 +688,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
         sys->updateOutputCb      = LocalSwapchainUpdateOutput;
         sys->swapCb              = LocalSwapchainSwap;
         sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
+        sys->selectPlaneCb       = LocalSwapchainSelectPlane;
         uses_external_callbacks = false;
     }
 
@@ -958,6 +971,12 @@ static int Control(vout_display_t *vd, int query, va_list args)
     return res;
 }
 
+static bool SelectRenderPlane(void *opaque, size_t plane)
+{
+    vout_display_sys_t *sys = opaque;
+    return sys->selectPlaneCb(sys->outside_opaque, plane);
+}
+
 static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
 {
     vout_display_sys_t *sys = vd->sys;
@@ -1070,8 +1089,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
     }
     D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad,
                      vd->source.projection_mode == PROJECTION_MODE_RECTANGULAR ? &sys->flatVShader : &sys->projectionVShader,
-                     renderSrc,
-                     sys->internal_swapchain.swapchainTargetView); /* NULL with external rendering */
+                     renderSrc, SelectRenderPlane, sys);
 
     if (subpicture) {
         // draw the additional vertices
@@ -1080,8 +1098,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
             {
                 d3d_quad_t *quad = (d3d_quad_t *) sys->d3dregions[i]->p_sys;
                 D3D11_RenderQuad(&sys->d3d_dev, quad, &sys->flatVShader,
-                                 quad->picSys.renderSrc,
-                                 sys->internal_swapchain.swapchainTargetView); /* NULL with external rendering */
+                                 quad->picSys.renderSrc, SelectRenderPlane, sys);
             }
         }
     }
-- 
2.17.1



More information about the vlc-devel mailing list