[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