[vlc-devel] [PATCH 2/8] libvlc: add rendering callbacks for D3D11 and D3D9
Rémi Denis-Courmont
remi at remlab.net
Mon May 6 17:08:09 CEST 2019
Le maanantaina 6. toukokuuta 2019, 17.39.51 EEST Thomas Guillem a écrit :
> On Mon, May 6, 2019, at 15:02, Steve Lhomme wrote:
> > ---
> >
> > include/vlc/libvlc_media_player.h | 144 ++++++++++++++++++++++++++++++
> > include/vlc_vout_display.h | 8 +-
> > lib/libvlc.sym | 1 +
> > lib/media_player.c | 54 +++++++++++
> > 4 files changed, 203 insertions(+), 4 deletions(-)
> >
> > diff --git a/include/vlc/libvlc_media_player.h
> > b/include/vlc/libvlc_media_player.h
> > index ca72a550d3..72b4648019 100644
> > --- a/include/vlc/libvlc_media_player.h
> > +++ b/include/vlc/libvlc_media_player.h
> > @@ -557,6 +557,150 @@ 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_surface_set_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 for D3D11 */
> > +} libvlc_video_surface_device_cfg_t;
> > +
> > +typedef struct
> > +{
> > + void *device_context; /** ID3D11DeviceContext* for D3D11,
> > IDirect3DDevice9 * for D3D9 */
> > +} libvlc_video_surface_device_setup_t;
> > +
> > +/** Setup the rendering environment.
> > + *
> > + * \param opaque private pointer passed to the @a
> > libvlc_video_surface_set_callbacks() [IN]
> > + * \param cfg requested configuration of the video device
> > + * \param out libvlc_video_surface_device_setup_t* to fill
> > + * \return true on success
> > + * \version LibVLC 4.0.0 or later
> > + *
> > + * 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.
> > + */
> > +typedef bool( *libvlc_video_surface_device_setup_cb )( void *opaque,
> > const libvlc_video_surface_device_cfg_t *cfg,
> > libvlc_video_surface_device_setup_t *out );
> > +
> > +/** Cleanup the rendering environment initialized during \ref
> > libvlc_video_surface_device_setup_cb.
> > + *
> > + * \param opaque private pointer passed to the @a
> > libvlc_video_surface_set_callbacks() [IN]
> > + * \version LibVLC 4.0.0 or later
> > + */
> > +typedef void( *libvlc_video_surface_device_cleanup_cb )( void *opaque
> > );
> > +
> > +typedef struct
> > +{
> > + unsigned width; /** rendering video width
> > in pixel */
> > + unsigned height; /** rendering video height
> > in pixel */
> > +} libvlc_video_surface_cfg_t;
> > +
> > +typedef struct
> > +{
> > + intptr_t surface_format; /** the rendering DXGI_FORMAT for \ref
> > libvlc_video_rendering_direct3d11,
> > + D3DFORMAT for \ref
> > libvlc_video_rendering_direct3d9 */
> > +} libvlc_video_output_cfg_t;
> > +
> > +/** Update the rendering output setup.
> > + *
> > + * \param opaque private pointer passed to the @a
> > libvlc_video_surface_set_callbacks() [IN]
> > + * \param cfg configuration of the video that will be rendered
> > + * \param output configuration describing with how the rendering is
> > setup
> > + * \version LibVLC 4.0.0 or later
> > + *
> > + * Tone mapping, range and color conversion will be done depending on
> > the values
> > + * set in the output structure.
> > + */
> > +typedef bool( *libvlc_video_surface_update_output_cb )( void *opaque,
> > const libvlc_video_surface_cfg_t *cfg, libvlc_video_output_cfg_t
> > *output );
> > +
> > +/** Tell the host the rendering is about to start/has finished.
> > + *
> > + * \param opaque private pointer passed to the @a
> > libvlc_video_surface_set_callbacks() [IN]
> > + * \param enter true if the rendering is about to start, false if it's
> > finished
> > + * \return true on success
> > + * \version LibVLC 4.0.0 or later
> > + *
> > + * On Direct3D9 the following may change on the provided
> > IDirect3DDevice9*
> > + * between \ref enter being true and \ref enter being false:
> > + * - 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
> > + *
> > + * On Direct3D11 the following may change on the provided
> > ID3D11DeviceContext*
> > + * between \ref enter being true and \ref enter being false:
> > + * - IASetPrimitiveTopology()
> > + * - IASetInputLayout()
> > + * - IASetVertexBuffers()
> > + * - IASetIndexBuffer()
> > + * - VSSetConstantBuffers()
> > + * - VSSetShader()
> > + * - PSSetSamplers()
> > + * - PSSetConstantBuffers()
> > + * - PSSetShaderResources()
> > + * - PSSetShader()
> > + * - RSSetViewports()
> > + * - DrawIndexed()
> > + */
> > +typedef bool( *libvlc_video_surface_start_rendering_cb )( void
> > *opaque, bool enter );
> > +
> > +
> > +/**
> > + * 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_surface_set_callbacks( libvlc_media_player_t *mp,
> > + libvlc_video_rendering_t
> > engine,
> > +
> > libvlc_video_surface_device_setup_cb setup_cb,
> > +
> > libvlc_video_surface_device_cleanup_cb cleanup_cb,
> > +
> > libvlc_video_surface_update_output_cb update_output_cb,
> > + libvlc_video_swap_cb swap_cb,
> > +
> > libvlc_video_surface_start_rendering_cb makeCurrent_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 7b2c9cf0d3..23657d21f5 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_output_cfg_t
> > */
> >
> > typedef bool( *vlc_video_surface_device_setup_cb )( void *opaque,
> >
> > const vlc_video_surface_device_cfg_t *cfg,
> > vlc_video_surface_device_setup_t *out );
> >
> > typedef void( *vlc_video_surface_device_cleanup_cb )( void *opaque );
> >
> > diff --git a/lib/libvlc.sym b/lib/libvlc.sym
> > index ef132c37e4..2a6bba09c2 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_surface_set_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..e87c43b5ba 100644
> > --- a/lib/media_player.c
> > +++ b/lib/media_player.c
> > @@ -1202,6 +1202,39 @@ int libvlc_video_set_output_callbacks(
> > libvlc_media_player_t *mp,
> >
> > }
> >
> > +int libvlc_video_surface_set_callbacks( libvlc_media_player_t *mp,
> > + libvlc_video_rendering_t
> > engine,
> > +
> > libvlc_video_surface_device_setup_cb setup_cb,
> > +
> > libvlc_video_surface_device_cleanup_cb cleanup_cb,
> > +
> > libvlc_video_surface_update_output_cb update_output_cb,
> > + libvlc_video_swap_cb swap_cb,
> > +
> > libvlc_video_surface_start_rendering_cb makeCurrent_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-setup", setup_cb );
> > + var_SetAddress( mp, "vout-cb-cleanup", cleanup_cb );
> > + 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 );
>
> Are we sure we can do that without doing a transformation from the libvlc
> struct to the vlc one ?
No. We cannot. Having the same representation does not provide aliasing in C.
--
Реми Дёни-Курмон
http://www.remlab.net/
More information about the vlc-devel
mailing list