[vlc-devel] [PATCH 01/21] libvlc: add a callback to pass frame metadata before rendering

Steve Lhomme robux4 at ycbcr.xyz
Wed Feb 5 16:13:09 CET 2020


Only supported by the Direct3D11 rendering engine.

It replaces the metadata passed to start_end_rendering_cb.
---
 doc/libvlc/d3d11_player.cpp                  |  5 ++-
 doc/libvlc/d3d9_player.c                     |  5 ++-
 include/vlc/libvlc_media_player.h            | 45 +++++++++++++-------
 lib/media_player.c                           |  3 ++
 modules/video_output/win32/d3d11_swapchain.c | 45 +++++++++++---------
 modules/video_output/win32/d3d11_swapchain.h |  3 +-
 modules/video_output/win32/direct3d11.c      | 42 +++++++++---------
 modules/video_output/win32/direct3d9.c       |  4 +-
 8 files changed, 92 insertions(+), 60 deletions(-)

diff --git a/doc/libvlc/d3d11_player.cpp b/doc/libvlc/d3d11_player.cpp
index 6ce84fad993..78f06f22c33 100644
--- a/doc/libvlc/d3d11_player.cpp
+++ b/doc/libvlc/d3d11_player.cpp
@@ -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 );
diff --git a/doc/libvlc/d3d9_player.c b/doc/libvlc/d3d9_player.c
index ec3dbf806fb..99cabe8907a 100644
--- a/doc/libvlc/d3d9_player.c
+++ b/doc/libvlc/d3d9_player.c
@@ -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 );
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 7c72c9774b2..1c83ccc378d 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -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 );
 
diff --git a/lib/media_player.c b/lib/media_player.c
index cdb6ba0b8c5..9fa894ed8eb 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -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;
 }
diff --git a/modules/video_output/win32/d3d11_swapchain.c b/modules/video_output/win32/d3d11_swapchain.c
index 71112e876b9..7c2f435ab4c 100644
--- a/modules/video_output/win32/d3d11_swapchain.c
+++ b/modules/video_output/win32/d3d11_swapchain.c
@@ -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;
diff --git a/modules/video_output/win32/d3d11_swapchain.h b/modules/video_output/win32/d3d11_swapchain.h
index 6a4bbae5ea7..92608ac879a 100644
--- a/modules/video_output/win32/d3d11_swapchain.h
+++ b/modules/video_output/win32/d3d11_swapchain.h
@@ -33,7 +33,8 @@ void *CreateLocalSwapchainHandle(vlc_object_t *, HWND, ID3D11DeviceContext *);
 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 */
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index c5f6a63fcde..16a471830b2 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -122,6 +122,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;
 };
 
@@ -315,6 +316,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" );
 
     HRESULT hr;
@@ -350,6 +352,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;
     }
 
@@ -688,29 +691,30 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
 
     VLC_UNUSED(date);
 
-    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 );
     }
 }
 
diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index 9e36eb19184..8878054b9c1 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -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,
-- 
2.17.1



More information about the vlc-devel mailing list