[vlc-devel] [RFC 1/6] libvlc: add rendering callbacks for D3D11 and D3D9

Steve Lhomme robux4 at ycbcr.xyz
Tue Apr 30 11:34:33 CEST 2019


---
 include/vlc/libvlc_media_player.h | 143 ++++++++++++++++++++++++++++++
 lib/libvlc.sym                    |   1 +
 lib/media_player.c                |  39 ++++++++
 3 files changed, 183 insertions(+)

diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index ca72a550d3..51dd964600 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -557,6 +557,149 @@ int libvlc_video_set_output_callbacks( libvlc_media_player_t *mp,
                                         libvlc_video_getProcAddress_cb getProcAddress_cb,
                                         void* opaque );
 
+
+/**
+ * Enumeration of the Video engine to be used on output.
+ * can be passed to @a libvlc_video_set_rendering_callbacks
+ */
+typedef enum libvlc_video_rendering_t {
+    /** Direct3D11 rendering engine */
+    libvlc_video_rendering_direct3d11,
+    /** Direct3D9 rendering engine */
+    libvlc_video_rendering_direct3d9,
+} libvlc_video_rendering_t;
+
+typedef struct
+{
+    unsigned width;     /** rendering video width in pixel */
+    unsigned height;    /** rendering video height in pixel */
+} libvlc_video_callback_setup_t;
+
+/**
+ * List of control passed to the @a libvlc_video_control_cb callback
+ */
+typedef enum libvlc_video_callback_control_t {
+    /** Setup the rendering environment.
+     *
+     * \ref input ignored
+     * \ref output pointer depending on the type of the engine
+     *
+     * For \ref libvlc_video_rendering_direct3d9 the output must be a IDirect3DDevice9*.
+     * A reference to this object is held until the \ref LIBVLC_VIDEO_DEVICE_CLEANUP is called.
+     * the device must be created with D3DPRESENT_PARAMETERS.hDeviceWindow set to 0.
+     *
+     * For \ref libvlc_video_rendering_direct3d11 the output must be a ID3D11DeviceContext*.
+     * A reference to this object is held until the \ref LIBVLC_VIDEO_DEVICE_CLEANUP is called.
+     * The ID3D11Device used to create ID3D11DeviceContext must have multithreading enabled.
+     */
+    LIBVLC_VIDEO_DEVICE_SETUP,
+
+    /** Cleanup the rendering environment initialized during \ref LIBVLC_VIDEO_DEVICE_SETUP.
+     *
+     * \ref input ignored
+     * \ref output ignored
+     */
+    LIBVLC_VIDEO_DEVICE_CLEANUP,
+
+    /** Update the rendering output setup.
+     *
+     * \ref input const libvlc_video_callback_setup_t* with the new setup
+     * \ref output ignored
+     */
+    LIBVLC_VIDEO_UPDATE_OUTPUT,
+
+    /** Callback prototype called after performing drawing calls.
+     *
+     * \ref input ignored
+     * \ref output ignored
+     */
+    LIBVLC_VIDEO_SWAP,
+
+    /** Tell the host the rendering is about to start.
+     *
+     * \ref input ignored
+     * \ref output ignored
+     *
+     * Between \ref LIBVLC_VIDEO_START_RENDERING and \ref LIBVLC_VIDEO_FINISHED_RENDERING
+     * of Direct3D9 the following may change on the provided IDirect3DDevice9*:
+     * - D3DSAMP_ADDRESSU
+     * - D3DSAMP_ADDRESSV
+     * - D3DSAMP_MINFILTER
+     * - D3DSAMP_MAGFILTER
+     * - D3DRS_AMBIENT
+     * - D3DRS_CULLMODE
+     * - D3DRS_ZENABLE
+     * - D3DRS_LIGHTING
+     * - D3DRS_DITHERENABLE
+     * - D3DRS_STENCILENABLE
+     * - D3DRS_ALPHABLENDENABLE
+     * - D3DRS_SRCBLEND,D3DBLEND_SRCALPHA
+     * - D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA
+     * - D3DPCMPCAPS_GREATER
+     * - D3DRS_ALPHATESTENABLE
+     * - D3DRS_ALPHAREF
+     * - D3DRS_ALPHAFUNC
+     * - D3DTSS_COLOROP
+     * - D3DTSS_COLORARG1
+     * - D3DTSS_ALPHAOP
+     * - D3DTSS_ALPHAARG1
+     * - D3DTSS_ALPHAARG2
+     *
+     * Between \ref LIBVLC_VIDEO_START_RENDERING and \ref LIBVLC_VIDEO_FINISHED_RENDERING
+     * of Direct3D11 the following may change on the provided ID3D11DeviceContext*:
+     * - IASetPrimitiveTopology()
+     * - IASetInputLayout()
+     * - IASetVertexBuffers()
+     * - IASetIndexBuffer()
+     * - VSSetConstantBuffers()
+     * - VSSetShader()
+     * - PSSetSamplers()
+     * - PSSetConstantBuffers()
+     * - PSSetShaderResources()
+     * - PSSetShader()
+     * - RSSetViewports()
+     * - DrawIndexed()
+     */
+    LIBVLC_VIDEO_START_RENDERING,
+
+    /** Tell the host the rendering has ended.
+     *
+     * \ref input ignored
+     * \ref output ignored
+     */
+    LIBVLC_VIDEO_FINISHED_RENDERING,
+} libvlc_video_callback_control_t;
+
+/**
+ * Callback prototype for the @a libvlc_video_set_surface_callbacks callback.
+ *
+ * \param opaque private pointer passed to the @a libvlc_video_set_surface_callbacks() [IN]
+ * \version LibVLC 4.0.0 or later
+ */
+typedef int (*libvlc_video_control_cb)(void* opaque,
+                                       libvlc_video_callback_control_t control,
+                                       const void *input,
+                                       void **output);
+
+/**
+ * Set callbacks and data to render decoded video to a custom Direct3D output
+ *
+ * \warning VLC will perform video rendering in its own thread and at its own rate,
+ * You need to provide your own synchronisation mechanism.
+ *
+ * \param mp the media player
+ * \param engine the GPU engine to use
+ * \param control_cb callback that receives all the \ref libvlc_video_callback_control_t
+ * \param opaque private pointer passed to the control callback
+ * \libvlc_return_bool
+ * \version LibVLC 4.0.0 or later
+ */
+LIBVLC_API
+int libvlc_video_set_rendering_callbacks( libvlc_media_player_t *mp,
+                                          libvlc_video_rendering_t engine,
+                                          libvlc_video_control_cb control_cb,
+                                          void* opaque );
+
 /**
  * Set the NSView handler where the media player should render its video output.
  *
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index ef132c37e4..f212088b30 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -244,6 +244,7 @@ libvlc_video_set_deinterlace
 libvlc_video_set_format
 libvlc_video_set_format_callbacks
 libvlc_video_set_output_callbacks
+libvlc_video_set_rendering_callbacks
 libvlc_video_set_key_input
 libvlc_video_set_logo_int
 libvlc_video_set_logo_string
diff --git a/lib/media_player.c b/lib/media_player.c
index 106e7d26b0..e04f1dab19 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-control", VLC_VAR_ADDRESS );
 
     var_Create (mp, "avcodec-hw", VLC_VAR_STRING);
     var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
@@ -1202,6 +1203,31 @@ int libvlc_video_set_output_callbacks( libvlc_media_player_t *mp,
 }
 
 
+int libvlc_video_set_rendering_callbacks( libvlc_media_player_t *mp,
+                                        libvlc_video_rendering_t engine,
+                                        libvlc_video_control_cb control_cb,
+                                        void* opaque )
+{
+    var_SetString( mp, "window", "wdummy");
+
+    if ( engine == libvlc_video_rendering_direct3d11 )
+    {
+        var_SetString ( mp, "vout", "direct3d11" );
+        var_SetString ( mp, "avcodec-hw", "d3d11va");
+    }
+    else if ( engine == libvlc_video_rendering_direct3d9 )
+    {
+        var_SetString ( mp, "vout", "direct3d9" );
+        var_SetString ( mp, "avcodec-hw", "dxva2");
+    }
+    else
+        return 0;
+
+    var_SetAddress( mp, "vout-cb-opaque", opaque );
+    var_SetAddress( mp, "vout-cb-control", control_cb );
+    return 1;
+}
+
 /**************************************************************************
  * set_nsobject
  **************************************************************************/
@@ -2049,3 +2075,16 @@ int libvlc_media_player_get_role(libvlc_media_player_t *mp)
     free(str);
     return ret;
 }
+
+#include <vlc_vout_display.h>
+
+static_assert(VLC_VIDEO_SURFACE_DEVICE_SETUP       == LIBVLC_VIDEO_DEVICE_SETUP &&
+              VLC_VIDEO_SURFACE_DEVICE_CLEANUP     == LIBVLC_VIDEO_DEVICE_CLEANUP &&
+              VLC_VIDEO_SURFACE_UPDATE_OUTPUT      == LIBVLC_VIDEO_UPDATE_OUTPUT &&
+              VLC_VIDEO_SURFACE_SWAP               == LIBVLC_VIDEO_SWAP &&
+              VLC_VIDEO_SURFACE_START_RENDERING    == LIBVLC_VIDEO_START_RENDERING &&
+              VLC_VIDEO_SURFACE_FINISHED_RENDERING == LIBVLC_VIDEO_FINISHED_RENDERING &&
+              sizeof(vlc_video_surface_cfg_t)           == sizeof(libvlc_video_callback_setup_t) &&
+              offsetof(vlc_video_surface_cfg_t, width)  == offsetof(libvlc_video_callback_setup_t, width) &&
+              offsetof(vlc_video_surface_cfg_t, height) == offsetof(libvlc_video_callback_setup_t, height)
+              , "video surface mismatch");
-- 
2.17.1



More information about the vlc-devel mailing list