[vlc-commits] [Git][videolan/vlc][master] 3 commits: vlc_es: add HDR10+ dynamic metadata

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Thu Feb 16 18:03:11 UTC 2023



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
4412b49e by Niklas Haas at 2023-02-16T17:47:05+00:00
vlc_es: add HDR10+ dynamic metadata

Following the precedent set by the DoVi metadata, we encode this as an
ancillary attached directly to the frame, since it contains
frame-dynamic data.

We make the decision to follow ATSC A/341 Amendment 2094-40 instead of
the original SMPTE ST2094-40:2016 specification, because the latter
includes a lot of extra metadata fields which the former intentionally
leaves unused, and which are also unused in practice (both in
implementation and in files). We can easily add them later should a need
arise.

Also, again following the precedent set by `vlc_video_dovi_metadata_t`,
we encode AVRationals directly as `float`. This saves us from having to
do another unnecessary conversion step in the actual usage site (e.g.
the libplacebo vout) by allowing the use of `av_q2d` directly.

- - - - -
5f7a8c04 by Niklas Haas at 2023-02-16T17:47:05+00:00
avcodec: expose HDR10+ metadata

The assert() calls are based on hard-coded guarantees in libavcodec.

- - - - -
ab9b509d by Niklas Haas at 2023-02-16T17:47:05+00:00
libplacebo: forward HDR10+ metadata to libplacebo

Fairly straightforward as libplacebo currently ignores most metadata
fields and only cares about the OOTF (bezier anchors) and global scene
brightness/average measurements.

- - - - -


5 changed files:

- include/vlc_es.h
- modules/codec/avcodec/video.c
- modules/video_output/libplacebo/display.c
- modules/video_output/libplacebo/utils.c
- modules/video_output/libplacebo/utils.h


Changes:

=====================================
include/vlc_es.h
=====================================
@@ -610,6 +610,39 @@ typedef struct vlc_video_dovi_metadata_t
     } nlq[3];
 } vlc_video_dovi_metadata_t;
 
+/**
+ * HDR10+ Dynamic metadata (based on ATSC A/341 Amendment 2094-40)
+ *
+ * This is similar to SMPTE ST2094-40:2016, but omits the mastering display and
+ * target display actual peak luminance LUTs, the rectangular boundaries and
+ * ellipse coefficients, and support for multiple processing windows, as these
+ * are intentionally left unused in this version of the specification.
+ */
+
+#define VLC_ANCILLARY_ID_HDR10PLUS VLC_FOURCC('H','D','R','+')
+
+typedef struct vlc_video_hdr_dynamic_metadata_t
+{
+    uint8_t country_code;           /* ITU-T T.35 Annex A */
+    uint8_t application_version;
+    float targeted_luminance;       /* in cd/m² */
+
+    /* parameters for the first processing window (encompassing the frame) */
+    float maxscl[3];                /* in linearized range [0,1] */
+    float average_maxrgb;           /* in linearized range [0,1] */
+    uint8_t num_histogram;          /* in range [0,15] */
+    struct {
+        uint8_t percentage;         /* in range [1,100] */
+        float percentile;           /* in linearized range [0,1] */
+    } histogram[15];
+    float fraction_bright_pixels;/* in range [0,1] */
+    uint8_t tone_mapping_flag;
+    float knee_point_x;             /* in ootf range [0,1] */
+    float knee_point_y;             /* in ootf range [0,1] */
+    uint8_t num_bezier_anchors;     /* in range [1,15] */
+    float bezier_curve_anchors[15]; /* in range [0,1] */
+} vlc_video_hdr_dynamic_metadata_t;
+
 /**
  * Embedded ICC profiles
  */


=====================================
modules/codec/avcodec/video.c
=====================================
@@ -50,6 +50,10 @@
 # include <libavutil/dovi_meta.h>
 #endif
 
+#if LIBAVUTIL_VERSION_CHECK( 56, 25, 100 )
+# include <libavutil/hdr_dynamic_metadata.h>
+#endif
+
 #include "../cc.h"
 #define FRAME_INFO_DEPTH 64
 
@@ -755,6 +759,39 @@ static void map_dovi_metadata( vlc_video_dovi_metadata_t *out,
 }
 #endif
 
+#if LIBAVUTIL_VERSION_CHECK( 56, 25, 100 )
+static void map_hdrplus_metadata( vlc_video_hdr_dynamic_metadata_t *out,
+                                  const AVDynamicHDRPlus *data )
+{
+    out->country_code = data->itu_t_t35_country_code;
+    out->application_version = data->application_version;
+    out->targeted_luminance = av_q2d( data->targeted_system_display_maximum_luminance );
+
+    assert( data->num_windows > 0 );
+    const AVHDRPlusColorTransformParams *pars = &data->params[0];
+    for ( size_t i = 0; i < ARRAY_SIZE( out->maxscl ); i++ )
+        out->maxscl[i] = av_q2d( pars->maxscl[i] );
+    out->average_maxrgb = av_q2d( pars->average_maxrgb );
+    out->num_histogram = pars->num_distribution_maxrgb_percentiles;
+    assert( out->num_histogram < ARRAY_SIZE( out->histogram ));
+    for ( size_t i = 0; i < out->num_histogram; i++ ) {
+        const AVHDRPlusPercentile pct = pars->distribution_maxrgb[i];
+        out->histogram[i].percentage = pct.percentage;
+        out->histogram[i].percentile = av_q2d( pct.percentile );
+    }
+    out->fraction_bright_pixels = av_q2d( pars->fraction_bright_pixels );
+    out->tone_mapping_flag = pars->tone_mapping_flag;
+    if ( out->tone_mapping_flag ) {
+        out->knee_point_x = av_q2d( pars->knee_point_x );
+        out->knee_point_y = av_q2d( pars->knee_point_y );
+        out->num_bezier_anchors = pars->num_bezier_curve_anchors;
+        assert( out->num_bezier_anchors < ARRAY_SIZE( out->bezier_curve_anchors ));
+        for ( size_t i = 0; i < out->num_bezier_anchors; i++ )
+            out->bezier_curve_anchors[i] = av_q2d( pars->bezier_curve_anchors[i] );
+    }
+}
+#endif
+
 static int DecodeSidedata( decoder_t *p_dec, const AVFrame *frame, picture_t *p_pic )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
@@ -920,6 +957,18 @@ static int DecodeSidedata( decoder_t *p_dec, const AVFrame *frame, picture_t *p_
     }
 #endif
 
+#if LIBAVUTIL_VERSION_CHECK( 56, 25, 100 )
+    const AVFrameSideData *p_hdrplus = av_frame_get_side_data( frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS );
+    if( p_hdrplus )
+    {
+        vlc_video_hdr_dynamic_metadata_t *dst;
+        dst = picture_AttachNewAncillary( p_pic, VLC_ANCILLARY_ID_HDR10PLUS, sizeof(*dst) );
+        if( !dst )
+            return VLC_ENOMEM;
+        map_hdrplus_metadata( dst, (AVDynamicHDRPlus *) p_hdrplus->data );
+    }
+#endif
+
     const AVFrameSideData *p_icc = av_frame_get_side_data( frame, AV_FRAME_DATA_ICC_PROFILE );
     if( p_icc )
     {


=====================================
modules/video_output/libplacebo/display.c
=====================================
@@ -259,6 +259,12 @@ static void PictureRender(vout_display_t *vd, picture_t *pic,
         pl_icc_profile_compute_signature(&img.profile);
     }
 
+    struct vlc_ancillary *hdrplus = picture_GetAncillary(pic, VLC_ANCILLARY_ID_HDR10PLUS);
+    if (hdrplus) {
+        vlc_video_hdr_dynamic_metadata_t *hdm = vlc_ancillary_GetData(hdrplus);
+        vlc_placebo_HdrMetadata(hdm, &img.color.hdr);
+    }
+
     // Upload the image data for each plane
     struct pl_plane_data data[4];
     if (!vlc_placebo_PlaneData(pic, data, NULL)) {


=====================================
modules/video_output/libplacebo/utils.c
=====================================
@@ -452,6 +452,28 @@ struct pl_color_repr vlc_placebo_ColorRepr(const video_format_t *fmt)
     };
 }
 
+void vlc_placebo_HdrMetadata(const vlc_video_hdr_dynamic_metadata_t *src,
+                             struct pl_hdr_metadata *dst)
+{
+#if PL_API_VER >= 242
+    for (size_t i = 0; i < ARRAY_SIZE(dst->scene_max); i++)
+        dst->scene_max[i] = src->maxscl[i];
+    dst->scene_avg = src->average_maxrgb;
+
+    if (src->tone_mapping_flag) {
+        static_assert(sizeof(dst->ootf.anchors) == sizeof(src->bezier_curve_anchors), "array mismatch");
+        memcpy(dst->ootf.anchors, src->bezier_curve_anchors, sizeof(dst->ootf.anchors));
+        dst->ootf.num_anchors = src->num_bezier_anchors;
+        dst->ootf.target_luma = src->targeted_luminance;
+        dst->ootf.knee_x = src->knee_point_x;
+        dst->ootf.knee_y = src->knee_point_y;
+    }
+#else
+    (void) src;
+    (void) dst;
+#endif
+}
+
 #if PL_API_VER >= 185
 void vlc_placebo_DoviMetadata(const vlc_video_dovi_metadata_t *src,
                               struct pl_dovi_metadata *dst)


=====================================
modules/video_output/libplacebo/utils.h
=====================================
@@ -38,6 +38,10 @@ struct pl_color_space vlc_placebo_ColorSpace(const video_format_t *);
 struct pl_color_repr vlc_placebo_ColorRepr(const video_format_t *);
 enum pl_chroma_location vlc_placebo_ChromaLoc(const video_format_t *);
 
+// Map HDR10+ metadata struct (on supported version of libplacebo)
+void vlc_placebo_HdrMetadata(const vlc_video_hdr_dynamic_metadata_t *src,
+                             struct pl_hdr_metadata *dst);
+
 #if PL_API_VER >= 185
 // Map raw dolby vision metadata struct
 void vlc_placebo_DoviMetadata(const vlc_video_dovi_metadata_t *src,



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a7c43747d2320fd8c6d1fef806e00a86af2c5813...ab9b509df6655da6b5980349808f472a2ce26268

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a7c43747d2320fd8c6d1fef806e00a86af2c5813...ab9b509df6655da6b5980349808f472a2ce26268
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list