[vlc-devel] [RFC v2 2/8] libvlc: add rendering callbacks for D3D11 and D3D9
Steve Lhomme
robux4 at ycbcr.xyz
Thu May 2 15:28:45 CEST 2019
---
include/vlc/libvlc_media_player.h | 153 ++++++++++++++++++++++++++++++
include/vlc_vout_display.h | 10 +-
lib/libvlc.sym | 1 +
lib/media_player.c | 50 ++++++++++
4 files changed, 209 insertions(+), 5 deletions(-)
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index ca72a550d3..a9d8199728 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -557,6 +557,159 @@ 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
+{
+ bool hardware_decoding; /** set if D3D11_CREATE_DEVICE_VIDEO_SUPPORT is needed */
+} libvlc_video_surface_device_cfg_t;
+
+typedef struct
+{
+ void *device_context; /** ID3D11DeviceContext* for D3D11, IDirect3DDevice9 * for D3D9 */
+} libvlc_video_surface_device_setup_t;
+
+typedef struct
+{
+ unsigned width; /** rendering video width in pixel */
+ unsigned height; /** rendering video height in pixel */
+} libvlc_video_surface_cfg_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 const libvlc_video_surface_device_cfg_t*
+ * \ref output pointer to a libvlc_video_surface_device_setup_t* to fill
+ *
+ * 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_surface_cfg_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/include/vlc_vout_display.h b/include/vlc_vout_display.h
index 3126138459..33bd344a99 100644
--- a/include/vlc_vout_display.h
+++ b/include/vlc_vout_display.h
@@ -459,22 +459,22 @@ void vout_display_TranslateMouseState(vout_display_t *vd, vlc_mouse_t *video,
typedef struct
{
bool hardware_decoding; /** set if D3D11_CREATE_DEVICE_VIDEO_SUPPORT is needed */
-} vlc_video_surface_device_cfg_t;
+} vlc_video_surface_device_cfg_t; /* must match libvlc_video_surface_device_cfg_t */
typedef struct
{
void *device_context; /** ID3D11DeviceContext* for D3D11, IDirect3DDevice9* for D3D9 */
-} vlc_video_surface_device_setup_t;
+} vlc_video_surface_device_setup_t; /* must match libvlc_video_surface_device_setup_t */
typedef struct
{
unsigned width, height;
-} vlc_video_surface_cfg_t;
+} vlc_video_surface_cfg_t; /* must match libvlc_video_surface_cfg_t */
typedef struct
{
intptr_t surface_format; /* DXGI_FORMAT for D3D11, D3DFORMAT for D3D9 */
-} video_surface_output_cfg_t;
+} video_surface_output_cfg_t; /* must match libvlc_video_surface_cfg_t */
typedef enum
{
@@ -484,7 +484,7 @@ typedef enum
VLC_VIDEO_SURFACE_SWAP,
VLC_VIDEO_SURFACE_START_RENDERING,
VLC_VIDEO_SURFACE_FINISHED_RENDERING,
-} vlc_video_surface_control_t;
+} vlc_video_surface_control_t; /* must match libvlc_video_callback_control_t */
typedef int (*vlc_video_surface_control)(void* opaque,
vlc_video_surface_control_t control,
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..8e63569e4b 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,27 @@ int libvlc_media_player_get_role(libvlc_media_player_t *mp)
free(str);
return ret;
}
+
+#include <vlc_vout_display.h>
+
+/* make sure surface structures from libvlc can be passed as such to vlc */
+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
+ , "video surface callback IDs mismatch");
+
+static_assert( sizeof( vlc_video_surface_device_cfg_t ) == sizeof( libvlc_video_surface_device_cfg_t ) &&
+ offsetof( vlc_video_surface_device_cfg_t, hardware_decoding ) == offsetof( libvlc_video_surface_device_cfg_t, hardware_decoding )
+ , "video surface device configuration mismatch" );
+
+static_assert(sizeof(vlc_video_surface_device_setup_t) == sizeof(libvlc_video_surface_device_setup_t) &&
+ offsetof(vlc_video_surface_device_setup_t, device_context) == offsetof(libvlc_video_surface_device_setup_t, device_context)
+ , "video surface device setup mismatch");
+
+static_assert(sizeof(vlc_video_surface_cfg_t) == sizeof(libvlc_video_surface_cfg_t) &&
+ offsetof(vlc_video_surface_cfg_t, width) == offsetof(libvlc_video_surface_cfg_t, width) &&
+ offsetof(vlc_video_surface_cfg_t, height) == offsetof(libvlc_video_surface_cfg_t, height)
+ , "video surface setup mismatch");
--
2.17.1
More information about the vlc-devel
mailing list