libvlc: add a callback to pass frame metadata before rendering

Only supported by the Direct3D11 rendering engine.

It replaces the metadata passed to start_end_rendering_cb.
This commit is contained in:
Steve Lhomme 2020-02-05 13:37:29 +01:00
parent 29e1f62d36
commit 965b1d9c1c
8 changed files with 92 additions and 60 deletions

View File

@ -417,7 +417,7 @@ static void Swap_cb( void* opaque )
ctx->swapchain->Present( 0, 0 );
}
static bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 )
static bool StartRendering_cb( void *opaque, bool enter )
{
struct render_context *ctx = static_cast<struct render_context *>( opaque );
if ( enter )
@ -582,7 +582,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
/* Tell VLC to render into our D3D11 environment */
libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d11,
Setup_cb, Cleanup_cb, Resize_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, SelectPlane_cb,
Setup_cb, Cleanup_cb, Resize_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb,
nullptr, SelectPlane_cb,
&Context );
libvlc_media_player_play( p_mp );

View File

@ -256,7 +256,7 @@ static void Swap_cb( void* opaque )
*
* This is called outside of the UI thread (in the VLC rendering thread).
*/
static bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 )
static bool StartRendering_cb( void *opaque, bool enter )
{
struct render_context *ctx = opaque;
if ( enter )
@ -377,7 +377,8 @@ int WINAPI WinMain(HINSTANCE hInstance,
/* Tell VLC to render into our D3D9 environment */
libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d9,
Setup_cb, Cleanup_cb, Resize_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, NULL,
Setup_cb, Cleanup_cb, Resize_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb,
NULL, NULL,
&Context );
libvlc_media_player_play( p_mp );

View File

@ -560,6 +560,33 @@ typedef bool (*libvlc_video_makeCurrent_cb)(void* opaque, bool enter);
*/
typedef void* (*libvlc_video_getProcAddress_cb)(void* opaque, const char* fct_name);
typedef struct
{
/* similar to SMPTE ST 2086 mastering display color volume */
uint16_t RedPrimary[2];
uint16_t GreenPrimary[2];
uint16_t BluePrimary[2];
uint16_t WhitePoint[2];
unsigned int MaxMasteringLuminance;
unsigned int MinMasteringLuminance;
uint16_t MaxContentLightLevel;
uint16_t MaxFrameAverageLightLevel;
} libvlc_video_direct3d_hdr10_metadata_t;
typedef enum libvlc_video_metadata_type_t {
libvlc_video_metadata_frame_hdr10, /**< libvlc_video_direct3d_hdr10_metadata_t */
} libvlc_video_metadata_type_t;
/**
* Callback prototype to receive metadata before rendering.
*
* \param opaque private pointer passed to the @a libvlc_video_set_output_callbacks() [IN]
* \param type type of data passed in metadata [IN]
* \param metadata the type of metadata [IN]
* \version LibVLC 4.0.0 or later
*/
typedef void (*libvlc_video_frameMetadata_cb)(void* opaque, libvlc_video_metadata_type_t type, const void *metadata);
/**
* Enumeration of the Video engine to be used on output.
* can be passed to @a libvlc_video_set_output_callbacks
@ -712,24 +739,10 @@ typedef bool( *libvlc_video_direct3d_update_output_cb )( void *opaque,
const libvlc_video_direct3d_cfg_t *cfg,
libvlc_video_output_cfg_t *output );
typedef struct
{
/* similar to SMPTE ST 2086 mastering display color volume */
uint16_t RedPrimary[2];
uint16_t GreenPrimary[2];
uint16_t BluePrimary[2];
uint16_t WhitePoint[2];
unsigned int MaxMasteringLuminance;
unsigned int MinMasteringLuminance;
uint16_t MaxContentLightLevel;
uint16_t MaxFrameAverageLightLevel;
} libvlc_video_direct3d_hdr10_metadata_t;
/** Tell the host the rendering is about to start/has finished.
*
* \param opaque private pointer set on the opaque parameter of @a libvlc_video_direct3d_device_setup_cb() [IN]
* \param enter true if the rendering is about to start, false if it's finished
* \param hdr10 libvlc_video_direct3d_hdr10_metadata_t* or NULL [IN]
* \return true on success
* \version LibVLC 4.0.0 or later
*
@ -748,7 +761,7 @@ typedef struct
* - RSSetViewports()
* - DrawIndexed()
*/
typedef bool( *libvlc_video_direct3d_start_end_rendering_cb )( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 );
typedef bool( *libvlc_video_direct3d_start_end_rendering_cb )( void *opaque, bool enter );
/** Tell the host the rendering for the given plane is about to start
*
@ -785,6 +798,7 @@ typedef bool( *libvlc_video_direct3d_select_plane_cb )( void *opaque, size_t pla
* rendering format used by the host (cannot be NULL)
* \param swap_cb callback to tell the host it should display the rendered picture (cannot be NULL)
* \param makeCurrent_cb callback to tell the host the rendering is starting/ended (cannot be NULL)
* \param metadata_cb callback to provide frame metadata (D3D11 only)
* \param select_plane_cb callback to select different D3D11 rendering targets
* \param opaque private pointer passed to the \ref cleanup_cb callback
*
@ -801,6 +815,7 @@ bool libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
libvlc_video_direct3d_update_output_cb update_output_cb,
libvlc_video_swap_cb swap_cb,
libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb,
libvlc_video_frameMetadata_cb metadata_cb,
libvlc_video_direct3d_select_plane_cb select_plane_cb,
void* opaque );

View File

@ -601,6 +601,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-metadata", VLC_VAR_ADDRESS );
var_Create( mp, "vout-cb-select-plane", VLC_VAR_ADDRESS );
var_Create (mp, "dec-dev", VLC_VAR_STRING);
@ -1080,6 +1081,7 @@ bool libvlc_video_direct3d_set_callbacks(libvlc_media_player_t *mp,
libvlc_video_direct3d_update_output_cb update_output_cb,
libvlc_video_swap_cb swap_cb,
libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb,
libvlc_video_frameMetadata_cb metadata_cb,
libvlc_video_direct3d_select_plane_cb select_plane_cb,
void *opaque)
{
@ -1105,6 +1107,7 @@ bool libvlc_video_direct3d_set_callbacks(libvlc_media_player_t *mp,
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 );
var_SetAddress( mp, "vout-cb-metadata", metadata_cb );
var_SetAddress( mp, "vout-cb-select-plane", select_plane_cb );
return true;
}

View File

@ -483,7 +483,7 @@ bool LocalSwapchainUpdateOutput( void *opaque, const libvlc_video_direct3d_cfg_t
return true;
}
bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *p_hdr10 )
bool LocalSwapchainStartEndRendering( void *opaque, bool enter )
{
struct d3d11_local_swapchain *display = opaque;
@ -507,29 +507,36 @@ bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const libvlc_vid
}
#endif
if ( display->dxgiswapChain4 && p_hdr10 != NULL )
{
DXGI_HDR_METADATA_HDR10 hdr10 = { 0 };
hdr10.GreenPrimary[0] = p_hdr10->GreenPrimary[0];
hdr10.GreenPrimary[1] = p_hdr10->GreenPrimary[1];
hdr10.BluePrimary[0] = p_hdr10->BluePrimary[0];
hdr10.BluePrimary[1] = p_hdr10->BluePrimary[1];
hdr10.RedPrimary[0] = p_hdr10->RedPrimary[0];
hdr10.RedPrimary[1] = p_hdr10->RedPrimary[1];
hdr10.WhitePoint[0] = p_hdr10->WhitePoint[0];
hdr10.WhitePoint[1] = p_hdr10->WhitePoint[1];
hdr10.MinMasteringLuminance = p_hdr10->MinMasteringLuminance;
hdr10.MaxMasteringLuminance = p_hdr10->MaxMasteringLuminance;
hdr10.MaxContentLightLevel = p_hdr10->MaxContentLightLevel;
hdr10.MaxFrameAverageLightLevel = p_hdr10->MaxFrameAverageLightLevel;
IDXGISwapChain4_SetHDRMetaData( display->dxgiswapChain4, DXGI_HDR_METADATA_TYPE_HDR10, sizeof( hdr10 ), &hdr10 );
}
D3D11_ClearRenderTargets( display->d3d_dev, display->pixelFormat, display->swapchainTargetView );
}
return true;
}
void LocalSwapchainSetMetadata( void *opaque, libvlc_video_metadata_type_t type, const void *metadata )
{
struct d3d11_local_swapchain *display = opaque;
assert(type == libvlc_video_metadata_frame_hdr10);
if (type == libvlc_video_metadata_frame_hdr10 && metadata && display->dxgiswapChain4)
{
const libvlc_video_direct3d_hdr10_metadata_t *p_hdr10 = metadata;
DXGI_HDR_METADATA_HDR10 hdr10 = { 0 };
hdr10.GreenPrimary[0] = p_hdr10->GreenPrimary[0];
hdr10.GreenPrimary[1] = p_hdr10->GreenPrimary[1];
hdr10.BluePrimary[0] = p_hdr10->BluePrimary[0];
hdr10.BluePrimary[1] = p_hdr10->BluePrimary[1];
hdr10.RedPrimary[0] = p_hdr10->RedPrimary[0];
hdr10.RedPrimary[1] = p_hdr10->RedPrimary[1];
hdr10.WhitePoint[0] = p_hdr10->WhitePoint[0];
hdr10.WhitePoint[1] = p_hdr10->WhitePoint[1];
hdr10.MinMasteringLuminance = p_hdr10->MinMasteringLuminance;
hdr10.MaxMasteringLuminance = p_hdr10->MaxMasteringLuminance;
hdr10.MaxContentLightLevel = p_hdr10->MaxContentLightLevel;
hdr10.MaxFrameAverageLightLevel = p_hdr10->MaxFrameAverageLightLevel;
IDXGISwapChain4_SetHDRMetaData( display->dxgiswapChain4, DXGI_HDR_METADATA_TYPE_HDR10, sizeof( hdr10 ), &hdr10 );
}
}
bool LocalSwapchainSelectPlane( void *opaque, size_t plane )
{
struct d3d11_local_swapchain *display = opaque;

View File

@ -33,7 +33,8 @@ void *CreateLocalSwapchainHandle(vlc_object_t *, HWND, d3d11_device_t *d3d_dev);
void LocalSwapchainCleanupDevice( void *opaque );
void LocalSwapchainSwap( void *opaque );
bool LocalSwapchainUpdateOutput( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out );
bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *p_hdr10 );
bool LocalSwapchainStartEndRendering( void *opaque, bool enter );
void LocalSwapchainSetMetadata( void *opaque, libvlc_video_metadata_type_t, const void * );
bool LocalSwapchainSelectPlane( void *opaque, size_t plane );
#endif /* VLC_D3D11_SWAPCHAIN_H */

View File

@ -123,6 +123,7 @@ struct vout_display_sys_t
libvlc_video_direct3d_update_output_cb updateOutputCb;
libvlc_video_swap_cb swapCb;
libvlc_video_direct3d_start_end_rendering_cb startEndRenderingCb;
libvlc_video_frameMetadata_cb sendMetadataCb;
libvlc_video_direct3d_select_plane_cb selectPlaneCb;
};
@ -316,6 +317,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
sys->updateOutputCb = var_InheritAddress( vd, "vout-cb-update-output" );
sys->swapCb = var_InheritAddress( vd, "vout-cb-swap" );
sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" );
sys->sendMetadataCb = var_InheritAddress( vd, "vout-cb-metadata" );
sys->selectPlaneCb = var_InheritAddress( vd, "vout-cb-select-plane" );
d3d11_decoder_device_t *dev_sys = GetD3D11OpaqueContext(context);
@ -349,6 +351,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
sys->updateOutputCb = LocalSwapchainUpdateOutput;
sys->swapCb = LocalSwapchainSwap;
sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
sys->sendMetadataCb = LocalSwapchainSetMetadata;
sys->selectPlaneCb = LocalSwapchainSelectPlane;
}
@ -687,29 +690,30 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
VLC_UNUSED(date);
d3d11_device_lock( sys->d3d_dev );
libvlc_video_direct3d_hdr10_metadata_t hdr10;
if (picture->format.mastering.max_luminance)
if ( sys->startEndRenderingCb( sys->outside_opaque, true ))
{
hdr10.GreenPrimary[0] = picture->format.mastering.primaries[0];
hdr10.GreenPrimary[1] = picture->format.mastering.primaries[1];
hdr10.BluePrimary[0] = picture->format.mastering.primaries[2];
hdr10.BluePrimary[1] = picture->format.mastering.primaries[3];
hdr10.RedPrimary[0] = picture->format.mastering.primaries[4];
hdr10.RedPrimary[1] = picture->format.mastering.primaries[5];
hdr10.WhitePoint[0] = picture->format.mastering.white_point[0];
hdr10.WhitePoint[1] = picture->format.mastering.white_point[1];
hdr10.MinMasteringLuminance = picture->format.mastering.min_luminance;
hdr10.MaxMasteringLuminance = picture->format.mastering.max_luminance;
hdr10.MaxContentLightLevel = picture->format.lighting.MaxCLL;
hdr10.MaxFrameAverageLightLevel = picture->format.lighting.MaxFALL;
}
if ( sys->sendMetadataCb && picture->format.mastering.max_luminance )
{
libvlc_video_direct3d_hdr10_metadata_t hdr10;
hdr10.GreenPrimary[0] = picture->format.mastering.primaries[0];
hdr10.GreenPrimary[1] = picture->format.mastering.primaries[1];
hdr10.BluePrimary[0] = picture->format.mastering.primaries[2];
hdr10.BluePrimary[1] = picture->format.mastering.primaries[3];
hdr10.RedPrimary[0] = picture->format.mastering.primaries[4];
hdr10.RedPrimary[1] = picture->format.mastering.primaries[5];
hdr10.WhitePoint[0] = picture->format.mastering.white_point[0];
hdr10.WhitePoint[1] = picture->format.mastering.white_point[1];
hdr10.MinMasteringLuminance = picture->format.mastering.min_luminance;
hdr10.MaxMasteringLuminance = picture->format.mastering.max_luminance;
hdr10.MaxContentLightLevel = picture->format.lighting.MaxCLL;
hdr10.MaxFrameAverageLightLevel = picture->format.lighting.MaxFALL;
sys->sendMetadataCb( sys->outside_opaque, libvlc_video_metadata_frame_hdr10, &hdr10 );
}
if ( sys->startEndRenderingCb( sys->outside_opaque, true,
picture->format.mastering.max_luminance ? &hdr10 : NULL))
{
PreparePicture(vd, picture, subpicture);
sys->startEndRenderingCb( sys->outside_opaque, false, NULL );
sys->startEndRenderingCb( sys->outside_opaque, false );
}
d3d11_device_unlock( sys->d3d_dev );
}

View File

@ -1087,7 +1087,7 @@ static void Direct3D9RenderScene(vout_display_t *vd,
IDirect3DDevice9 *d3ddev = sys->d3d9_device->d3ddev.dev;
HRESULT hr;
if (sys->startEndRenderingCb && !sys->startEndRenderingCb( sys->outside_opaque, true, NULL ))
if (sys->startEndRenderingCb && !sys->startEndRenderingCb( sys->outside_opaque, true ))
return;
if (sys->clear_scene) {
@ -1125,7 +1125,7 @@ static void Direct3D9RenderScene(vout_display_t *vd,
msg_Dbg(vd, "Failed EndScene: 0x%lX", hr);
if (sys->startEndRenderingCb)
sys->startEndRenderingCb( sys->outside_opaque, false, NULL );
sys->startEndRenderingCb( sys->outside_opaque, false );
}
static void Prepare(vout_display_t *vd, picture_t *picture,