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

Steve Lhomme robux4 at ycbcr.xyz
Fri May 10 08:51:46 CEST 2019


On 2019-05-09 16:55, Rémi Denis-Courmont wrote:
> 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.

I found libvlc_video_format_cb and libvlc_audio_setup_cb use that. But 
the documentation is not clear on what is done with the returned value:

  * \param opaque pointer to the data pointer passed to
  *               libvlc_audio_set_callbacks() [IN/OUT]

  * \param opaque pointer to the private pointer passed to
  *               libvlc_video_set_callbacks() [IN/OUT]

And I don't know what I would do with that either. All other API calls 
mention that the opaque (called data) is the one passed to 
libvlc_audio_set_callbacks() / libvlc_video_set_callbacks().

In my case, for a per-instance value the host can already use a 
different opaque on each libvlc_video_direct3d_set_callbacks() call.

>> +
>> +/** 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.

That's a leftover from what I was using more void pointers. I'll switch 
to an int. In both cases it's an enum.

>> +
>> 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/
> 
> 
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
> 


More information about the vlc-devel mailing list