[vlc-commits] libvlc: add a callback to pass frame metadata before rendering

Steve Lhomme git at videolan.org
Mon Feb 10 09:06:50 CET 2020


vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Wed Feb  5 13:37:29 2020 +0100| [965b1d9c1c48f30b71bc8fd35a36f100038528bd] | committer: Steve Lhomme

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.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=965b1d9c1c48f30b71bc8fd35a36f100038528bd
---

 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 6ce84fad99..78f06f22c3 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 ec3dbf806f..99cabe8907 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 7c72c9774b..1c83ccc378 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 cdb6ba0b8c..9fa894ed8e 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 409bd1f70d..4dbbce7a90 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 9c1969ac77..0469bef233 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, 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 */
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 88c49cc385..3f2d04d662 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -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 );
 }
diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index 9e36eb1918..8878054b9c 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,



More information about the vlc-commits mailing list