[vlc-devel] [PATCH 1/8] libvlc: add rendering callbacks for D3D11 and D3D9
Rémi Denis-Courmont
remi at remlab.net
Thu May 9 16:55:41 CEST 2019
Le torstaina 9. toukokuuta 2019, 17.28.00 EEST Steve Lhomme a écrit :
> ---
> include/vlc/libvlc_media_player.h | 189 ++++++++++++++++++++++++++++++
> lib/libvlc.sym | 1 +
> lib/media_player.c | 61 ++++++++++
> 3 files changed, 251 insertions(+)
>
> diff --git a/include/vlc/libvlc_media_player.h
> b/include/vlc/libvlc_media_player.h index ca72a550d3..cbeb7231a9 100644
> --- a/include/vlc/libvlc_media_player.h
> +++ b/include/vlc/libvlc_media_player.h
> @@ -289,6 +289,42 @@ LIBVLC_API void libvlc_media_player_stop (
> libvlc_media_player_t *p_mi ); LIBVLC_API int
> libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi,
> libvlc_renderer_item_t *p_item );
>
> +/**
> + * Enumeration of the Video color primaries.
> + */
> +typedef enum libvlc_video_color_primaries_t {
> + libvlc_video_primaries_BT601_525 = 1,
> + libvlc_video_primaries_BT601_625 = 2,
> + libvlc_video_primaries_BT709 = 3,
> + libvlc_video_primaries_BT2020 = 4,
> + libvlc_video_primaries_DCI_P3 = 5,
> + libvlc_video_primaries_BT470_M = 6,
> +} libvlc_video_color_primaries_t;
> +
> +/**
> + * Enumeration of the Video color spaces.
> + */
> +typedef enum libvlc_video_color_space_t {
> + libvlc_video_colorspace_BT601 = 1,
> + libvlc_video_colorspace_BT709 = 2,
> + libvlc_video_colorspace_BT2020 = 3,
> +} libvlc_video_color_space_t;
> +
> +/**
> + * Enumeration of the Video transfer functions.
> + */
> +typedef enum libvlc_video_transfer_func_t {
> + libvlc_video_transfer_func_LINEAR = 1,
> + libvlc_video_transfer_func_SRGB = 2,
> + libvlc_video_transfer_func_BT470_BG = 3,
> + libvlc_video_transfer_func_BT470_M = 4,
> + libvlc_video_transfer_func_BT709 = 5,
> + libvlc_video_transfer_func_PQ = 6,
> + libvlc_video_transfer_func_SMPTE_240 = 7,
> + libvlc_video_transfer_func_HLG = 8,
> +} libvlc_video_transfer_func_t;
> +
> +
> /**
> * Callback prototype to allocate and lock a picture buffer.
> *
> @@ -557,6 +593,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_direct3d_set_callbacks
> + */
> +typedef enum libvlc_video_direct3d_engine_t {
> + /** Direct3D11 rendering engine */
> + libvlc_video_direct3d_engine_d3d11,
> + /** Direct3D9 rendering engine */
> + libvlc_video_direct3d_engine_d3d9,
> +} libvlc_video_direct3d_engine_t;
> +
> +typedef struct
> +{
> + bool hardware_decoding; /** set if D3D11_CREATE_DEVICE_VIDEO_SUPPORT is
> needed for D3D11 */ +} libvlc_video_direct3d_device_cfg_t;
> +
> +typedef struct
> +{
> + void *device_context; /** ID3D11DeviceContext* for D3D11,
> IDirect3DDevice9 * for D3D9 */ +} libvlc_video_direct3d_device_setup_t;
> +
> +/** Setup the rendering environment.
> + *
> + * \param opaque private pointer passed to the @a
> libvlc_video_direct3d_set_callbacks() [IN] + * \param cfg requested
> configuration of the video device
> + * \param out libvlc_video_direct3d_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_direct3d_device_setup_cb )( void *opaque, const
> libvlc_video_direct3d_device_cfg_t *cfg,
> libvlc_video_direct3d_device_setup_t *out );
Usually the setup callbacks have a mechanism to set the private data per
instance, namely void **opaque.
> +
> +/** Cleanup the rendering environment initialized during \ref
> libvlc_video_direct3d_device_setup_cb. + *
> + * \param opaque private pointer passed to the @a
> libvlc_video_direct3d_set_callbacks() [IN] + * \version LibVLC 4.0.0 or
> later
> + */
> +typedef void( *libvlc_video_direct3d_device_cleanup_cb )( void *opaque );
> +
> +typedef struct
> +{
> + unsigned width; /** rendering video width in
> pixel */ + unsigned height; /** rendering video
> height in pixel */ + unsigned bitdepth; /** rendering video bit
> depth in bits per channel */ + bool full_range; /** video is
> full range or studio/limited range */ + libvlc_video_color_space_t
> colorspace; /** video color space */ +
> libvlc_video_color_primaries_t primaries; /** video color primaries
> */ + libvlc_video_transfer_func_t transfer; /** video transfer
> function */ +} libvlc_video_direct3d_cfg_t;
> +
> +typedef struct
> +{
> + intptr_t surface_format; /** the rendering DXGI_FORMAT for \ref
> libvlc_video_rendering_direct3d11,
intptr_t seems weird for what seems to be an enumerated type. Specifically, it
seems odd that Win32 and Win64 would have different entropy for this.
> +
> D3DFORMAT for \ref libvlc_video_rendering_direct3d9 */ + bool
> full_range; /** video is full range or studio/limited range */ +
> libvlc_video_color_space_t colorspace; /** video color space
> */ + libvlc_video_color_primaries_t primaries; /** video color
> primaries */ + libvlc_video_transfer_func_t transfer; /** video
> transfer function */ +} libvlc_video_output_cfg_t;
> +
> +/** Update the rendering output setup.
> + *
> + * \param opaque private pointer passed to the @a
> libvlc_video_direct3d_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_direct3d_update_output_cb )( void *opaque,
> const libvlc_video_direct3d_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_direct3d_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_direct3d_start_end_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_direct3d_set_callbacks( libvlc_media_player_t *mp,
> + libvlc_video_direct3d_engine_t
> engine, +
> libvlc_video_direct3d_device_setup_cb setup_cb, +
> libvlc_video_direct3d_device_cleanup_cb cleanup_cb, +
> libvlc_video_direct3d_update_output_cb
> update_output_cb, +
> libvlc_video_swap_cb swap_cb, +
> libvlc_video_direct3d_start_end_rendering_cb makeCurrent_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..51a45688de 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_direct3d_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..1172055a14 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_direct3d_set_callbacks( libvlc_media_player_t *mp,
> + libvlc_video_direct3d_engine_t
> engine, +
> libvlc_video_direct3d_device_setup_cb setup_cb, +
> libvlc_video_direct3d_device_cleanup_cb cleanup_cb, +
> libvlc_video_direct3d_update_output_cb
> update_output_cb, +
> libvlc_video_swap_cb swap_cb, +
> libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb, +
> void* opaque )
> +{
> + var_SetString( mp, "window", "wdummy");
> +
> + if ( engine == libvlc_video_direct3d_engine_d3d11 )
> + {
> + var_SetString ( mp, "vout", "direct3d11" );
> + var_SetString ( mp, "avcodec-hw", "d3d11va");
> + }
> + else if ( engine == libvlc_video_direct3d_engine_d3d9 )
> + {
> + 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 );
> + return 1;
> +}
> +
> /**************************************************************************
> * set_nsobject
>
> **************************************************************************/
> @@ -2049,3 +2082,31 @@ 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
> + otherwise we will need wrappers between what libvlc understands and what
> vlc uses */ +
> +static_assert(libvlc_video_colorspace_BT601 == COLOR_SPACE_BT601 &&
> + libvlc_video_colorspace_BT709 == COLOR_SPACE_BT709 &&
> + libvlc_video_colorspace_BT2020 == COLOR_SPACE_BT2020
> + , "libvlc video colorspace mismatch");
> +
> +static_assert(libvlc_video_transfer_func_LINEAR ==
> TRANSFER_FUNC_LINEAR && + libvlc_video_transfer_func_SRGB
> == TRANSFER_FUNC_SRGB && +
> libvlc_video_transfer_func_BT470_BG == TRANSFER_FUNC_BT470_BG && +
> libvlc_video_transfer_func_BT470_M == TRANSFER_FUNC_BT470_M &&
> + libvlc_video_transfer_func_BT709 ==
> TRANSFER_FUNC_BT709 && + libvlc_video_transfer_func_PQ
> == TRANSFER_FUNC_SMPTE_ST2084 && +
> libvlc_video_transfer_func_SMPTE_240 == TRANSFER_FUNC_SMPTE_240 && +
> libvlc_video_transfer_func_HLG == TRANSFER_FUNC_HLG +
> , "libvlc video transfer function mismatch");
> +
> +static_assert(libvlc_video_primaries_BT601_525 == COLOR_PRIMARIES_BT601_525
> && + libvlc_video_primaries_BT601_625 ==
> COLOR_PRIMARIES_BT601_625 && + libvlc_video_primaries_BT709
> == COLOR_PRIMARIES_BT709 && + libvlc_video_primaries_BT2020
> == COLOR_PRIMARIES_BT2020 && + libvlc_video_primaries_DCI_P3
> == COLOR_PRIMARIES_DCI_P3 && +
> libvlc_video_primaries_BT470_M == COLOR_PRIMARIES_BT470_M +
> , "libvlc video color primaries mismatch");
--
レミ・デニ-クールモン
http://www.remlab.net/
More information about the vlc-devel
mailing list