[vlc-commits] [Git][videolan/vlc][master] 8 commits: vlc_es: add DoVi config record to video_format_t

Steve Lhomme (@robUx4) gitlab at videolan.org
Sun Oct 23 11:33:46 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
7aed2376 by Niklas Haas at 2022-10-23T11:18:31+00:00
vlc_es: add DoVi config record to video_format_t

This was missing from the current implementation of DoVi, which only
forwarded the per-frame RPUs. This is, however, insufficient for all
consumers of this metadata - some will need to decide whether DoVi
reshaping is required or not up-front, at init time. To do this cleanly
we need access to the stream-wide DoVi configuration record.

- - - - -
7370d867 by Niklas Haas at 2022-10-23T11:18:31+00:00
avformat: demux: forward parsed dovi config record

- - - - -
f157e030 by Niklas Haas at 2022-10-23T11:18:31+00:00
avcodec: forward demuxer dovi metadata

- - - - -
0f95f656 by Niklas Haas at 2022-10-23T11:18:31+00:00
demux: mp4: implement dvcC box

Only parse the basic/easy fields for now, since these are the only ones
we care about for the time being.

- - - - -
d0c345b6 by Niklas Haas at 2022-10-23T11:18:31+00:00
libplacebo: fix #if version guard for dovi

This was accidentally 187, when it should have been 185.

- - - - -
7e5d6af7 by Niklas Haas at 2022-10-23T11:18:31+00:00
libplacebo: expose raw dovi metadata mapping util

Expose the raw metadata mapping primitive to be re-used in pl_scale.

- - - - -
f32ef7bd by Niklas Haas at 2022-10-23T11:18:31+00:00
opengl: expose dovi metadata ancillary to gl filters

Memcpy the ancillary struct to avoid depending on `picture`'s lifetime

- - - - -
b1dcc6ae by Niklas Haas at 2022-10-23T11:18:31+00:00
pl_scale: support dolby vision

And auto-enable pl_scale when DoVi input processing is required.

- - - - -


13 changed files:

- include/vlc_es.h
- modules/codec/avcodec/video.c
- modules/demux/avformat/demux.c
- modules/demux/mp4/essetup.c
- modules/demux/mp4/libmp4.c
- modules/demux/mp4/libmp4.h
- modules/video_output/libplacebo/display.c
- modules/video_output/libplacebo/utils.c
- modules/video_output/libplacebo/utils.h
- modules/video_output/opengl/filter.h
- modules/video_output/opengl/filters.c
- modules/video_output/opengl/pl_scale.c
- modules/video_output/opengl/vout_helper.c


Changes:

=====================================
include/vlc_es.h
=====================================
@@ -392,6 +392,15 @@ struct video_format_t
         uint16_t MaxCLL;  /* max content light level */
         uint16_t MaxFALL; /* max frame average light level */
     } lighting;
+    struct {
+        uint8_t version_major;
+        uint8_t version_minor;
+        unsigned profile : 7;
+        unsigned level : 6;
+        unsigned rpu_present : 1;
+        unsigned el_present : 1;
+        unsigned bl_present : 1;
+    } dovi;
     uint32_t i_cubemap_padding; /**< padding in pixels of the cube map faces */
 };
 


=====================================
modules/codec/avcodec/video.c
=====================================
@@ -275,6 +275,8 @@ static int lavc_UpdateVideoFormat(decoder_t *dec, AVCodecContext *ctx,
     dec->fmt_out.video.pose = dec->fmt_in.video.pose;
     if ( dec->fmt_in.video.mastering.max_luminance )
         dec->fmt_out.video.mastering = dec->fmt_in.video.mastering;
+    if ( dec->fmt_in.video.dovi.version_major )
+        dec->fmt_out.video.dovi = dec->fmt_in.video.dovi;
     dec->fmt_out.video.lighting = dec->fmt_in.video.lighting;
     p_sys->decoder_width  = dec->fmt_out.video.i_width;
     p_sys->decoder_height = dec->fmt_out.video.i_height;


=====================================
modules/demux/avformat/demux.c
=====================================
@@ -47,6 +47,10 @@
 #include <libavformat/avformat.h>
 #include <libavutil/display.h>
 
+#if LIBAVUTIL_VERSION_CHECK( 57, 16, 100 )
+# include <libavutil/dovi_meta.h>
+#endif
+
 //#define AVFORMAT_DEBUG 1
 
 # define HAVE_AVUTIL_CODEC_ATTACHMENT 1
@@ -181,6 +185,24 @@ static void get_rotation(es_format_t *fmt, AVStream *s)
     }
 }
 
+static void get_dovi_config(es_format_t *fmt, AVStream *s)
+{
+#if LIBAVUTIL_VERSION_CHECK( 57, 16, 100 )
+    AVDOVIDecoderConfigurationRecord *cfg;
+    cfg = av_stream_get_side_data(s, AV_PKT_DATA_DOVI_CONF, NULL);
+    if (!cfg)
+        return;
+
+    fmt->video.dovi.version_major = cfg->dv_version_major;
+    fmt->video.dovi.version_minor = cfg->dv_version_minor;
+    fmt->video.dovi.profile = cfg->dv_profile;
+    fmt->video.dovi.level = cfg->dv_level;
+    fmt->video.dovi.rpu_present = cfg->rpu_present_flag;
+    fmt->video.dovi.el_present = cfg->el_present_flag;
+    fmt->video.dovi.bl_present = cfg->bl_present_flag;
+#endif
+}
+
 static AVDictionary * BuildAVOptions( demux_t *p_demux )
 {
     char *psz_opts = var_InheritString( p_demux, "avformat-options" );
@@ -494,6 +516,7 @@ int avformat_OpenDemux( vlc_object_t *p_this )
             es_fmt.video.i_visible_height = es_fmt.video.i_height;
 
             get_rotation(&es_fmt, s);
+            get_dovi_config(&es_fmt, s);
 
 # warning FIXME: implement palette transmission
             psz_type = "video";


=====================================
modules/demux/mp4/essetup.c
=====================================
@@ -507,6 +507,23 @@ int SetupVideoES( demux_t *p_demux, const mp4_track_t *p_track, const MP4_Box_t
         }
     }
 
+    const MP4_Box_t *p_dvcC = MP4_BoxGet( p_sample, "dvcC" );
+    if( !p_dvcC )
+        p_dvcC = MP4_BoxGet( p_sample, "dvvC" );
+    if( !p_dvcC )
+        p_dvcC = MP4_BoxGet( p_sample, "dvwC" );
+    if( p_dvcC && BOXDATA(p_dvcC) )
+    {
+        const MP4_Box_data_dvcC_t *p_data = BOXDATA( p_dvcC );
+        p_fmt->video.dovi.version_major = p_data->i_version_major;
+        p_fmt->video.dovi.version_minor = p_data->i_version_minor;
+        p_fmt->video.dovi.profile = p_data->i_profile;
+        p_fmt->video.dovi.level = p_data->i_level;
+        p_fmt->video.dovi.rpu_present = p_data->i_rpu_present;
+        p_fmt->video.dovi.bl_present = p_data->i_bl_present;
+        p_fmt->video.dovi.el_present = p_data->i_el_present;
+    }
+
     SetupGlobalExtensions( p_sample, p_fmt );
 
     /* now see if esds is present and if so create a data packet


=====================================
modules/demux/mp4/libmp4.c
=====================================
@@ -4037,6 +4037,24 @@ static int MP4_ReadBox_irot( stream_t *p_stream, MP4_Box_t *p_box )
     MP4_READBOX_EXIT( 1 );
 }
 
+static int MP4_ReadBox_dvcC( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_Box_data_dvcC_t *p_dvcC;
+    uint16_t flags;
+    MP4_READBOX_ENTER( MP4_Box_data_dvcC_t, NULL );
+    p_dvcC = p_box->data.p_dvcC;
+    MP4_GET1BYTE( p_dvcC->i_version_major );
+    MP4_GET1BYTE( p_dvcC->i_version_minor );
+    MP4_GET2BYTES( flags );
+    p_dvcC->i_profile       = (flags >> 9) & 0x7f;  // 7 bits
+    p_dvcC->i_level         = (flags >> 3) & 0x3f;  // 6 bits
+    p_dvcC->i_rpu_present   = (flags >> 2) & 0x01;  // 1 bit
+    p_dvcC->i_el_present    = (flags >> 1) & 0x01;  // 1 bit
+    p_dvcC->i_bl_present    =  flags       & 0x01;  // 1 bit
+    /* TODO: remainder of box, if needed */
+    MP4_READBOX_EXIT( 1 );
+}
+
 static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
 {
     const uint8_t *p_peek;
@@ -4994,6 +5012,9 @@ static const struct
     { ATOM_keys,    MP4_ReadBox_keys,         ATOM_meta },
     { ATOM_colr,    MP4_ReadBox_colr,         0 },
     { ATOM_irot,    MP4_ReadBox_irot,         0 }, /* heif */
+    { ATOM_dvcC,    MP4_ReadBox_dvcC,         0 }, /* dolby vision config record */
+    { ATOM_dvvC,    MP4_ReadBox_dvcC,         0 },
+    { ATOM_dvwC,    MP4_ReadBox_dvcC,         0 },
 
     /* XiphQT */
     { ATOM_vCtH,    MP4_ReadBox_Binary,       ATOM_wave },


=====================================
modules/demux/mp4/libmp4.h
=====================================
@@ -416,6 +416,9 @@ typedef int64_t stime_t;
 #define ATOM_mdcv VLC_FOURCC( 'm', 'd', 'c', 'v' )
 #define ATOM_clli VLC_FOURCC( 'c', 'l', 'l', 'i' )
 #define ATOM_purl VLC_FOURCC( 'p', 'u', 'r', 'l' )
+#define ATOM_dvcC VLC_FOURCC( 'd', 'v', 'c', 'C' )
+#define ATOM_dvvC VLC_FOURCC( 'd', 'v', 'v', 'C' )
+#define ATOM_dvwC VLC_FOURCC( 'd', 'v', 'w', 'C' )
 
 #define ATOM_0x40PRM VLC_FOURCC( '@', 'P', 'R', 'M' )
 #define ATOM_0x40PRQ VLC_FOURCC( '@', 'P', 'R', 'Q' )
@@ -717,6 +720,17 @@ typedef struct
     uint16_t i_ccw_degrees;
 } MP4_Box_data_irot_t;
 
+typedef struct
+{
+    uint8_t i_version_major;
+    uint8_t i_version_minor;
+    uint8_t i_profile;
+    uint8_t i_level;
+    uint8_t i_rpu_present;
+    uint8_t i_el_present;
+    uint8_t i_bl_present;
+} MP4_Box_data_dvcC_t;
+
 #define SAMPLE_DESC_COMMON_HEADER \
     uint8_t  i_reserved1[6];\
     uint16_t i_data_reference_index
@@ -1760,6 +1774,7 @@ typedef union MP4_Box_data_s
     MP4_Box_data_vpcC_t *p_vpcC;
     MP4_Box_data_SmDm_t *p_SmDm;
     MP4_Box_data_CoLL_t *p_CoLL;
+    MP4_Box_data_dvcC_t *p_dvcC;
 
     MP4_Box_data_tfra_t *p_tfra;
     MP4_Box_data_mfro_t *p_mfro;


=====================================
modules/video_output/libplacebo/display.c
=====================================
@@ -248,7 +248,7 @@ static void PictureRender(vout_display_t *vd, picture_t *pic,
     };
 
 #if PL_API_VER >= 185
-    vlc_placebo_DoviMetadata(&img, pic, &sys->dovi_metadata);
+    vlc_placebo_frame_DoviMetadata(&img, pic, &sys->dovi_metadata);
 #endif
 
     struct vlc_ancillary *iccp = picture_GetAncillary(pic, VLC_ANCILLARY_ID_ICC);


=====================================
modules/video_output/libplacebo/utils.c
=====================================
@@ -452,15 +452,10 @@ struct pl_color_repr vlc_placebo_ColorRepr(const video_format_t *fmt)
     };
 }
 
-#if PL_API_VER >= 187
-void vlc_placebo_DoviMetadata(struct pl_frame *frame, const picture_t *pic,
+#if PL_API_VER >= 185
+void vlc_placebo_DoviMetadata(const vlc_video_dovi_metadata_t *src,
                               struct pl_dovi_metadata *dst)
 {
-    struct vlc_ancillary *ancillary = picture_GetAncillary(pic, VLC_ANCILLARY_ID_DOVI);
-    if (!ancillary)
-        return;
-
-    const vlc_video_dovi_metadata_t *src = vlc_ancillary_GetData(ancillary);
     static_assert(sizeof(dst->nonlinear_offset) == sizeof(src->nonlinear_offset), "array mismatch");
     static_assert(sizeof(dst->nonlinear) == sizeof(src->nonlinear_matrix), "matrix mismatch");
     static_assert(sizeof(dst->linear) == sizeof(src->linear_matrix), "matrix mismatch");
@@ -500,6 +495,17 @@ void vlc_placebo_DoviMetadata(struct pl_frame *frame, const picture_t *pic,
             }
         }
     }
+}
+
+void vlc_placebo_frame_DoviMetadata(struct pl_frame *frame, const picture_t *pic,
+                                    struct pl_dovi_metadata *dst)
+{
+    struct vlc_ancillary *ancillary = picture_GetAncillary(pic, VLC_ANCILLARY_ID_DOVI);
+    if (!ancillary)
+        return;
+
+    const vlc_video_dovi_metadata_t *src = vlc_ancillary_GetData(ancillary);
+    vlc_placebo_DoviMetadata(src, dst);
 
     // The output of the Dolby Vision reshaping process is always BT.2020/PQ,
     // no matter the color space of the base layer, so override these fields


=====================================
modules/video_output/libplacebo/utils.h
=====================================
@@ -39,9 +39,13 @@ struct pl_color_repr vlc_placebo_ColorRepr(const video_format_t *);
 enum pl_chroma_location vlc_placebo_ChromaLoc(const video_format_t *);
 
 #if PL_API_VER >= 185
-// Map dolby vision metadata, using `data` as storage.
-void vlc_placebo_DoviMetadata(struct pl_frame *out, const picture_t *pic,
-                              struct pl_dovi_metadata *data);
+// Map raw dolby vision metadata struct
+void vlc_placebo_DoviMetadata(const vlc_video_dovi_metadata_t *src,
+                              struct pl_dovi_metadata *dst);
+
+// Map metadata from frame if present, using `data` as storage
+void vlc_placebo_frame_DoviMetadata(struct pl_frame *frame, const picture_t *pic,
+                                    struct pl_dovi_metadata *data);
 #endif
 
 int vlc_placebo_PlaneComponents(const video_format_t *, struct pl_plane[4]);


=====================================
modules/video_output/opengl/filter.h
=====================================
@@ -41,6 +41,7 @@ struct vlc_gl_tex_size {
 struct vlc_gl_input_meta {
     vlc_tick_t pts;
     unsigned plane;
+    const vlc_video_dovi_metadata_t *dovi_rpu;
 };
 
 typedef int


=====================================
modules/video_output/opengl/filters.c
=====================================
@@ -26,6 +26,7 @@
 #include "filters.h"
 
 #include <vlc_common.h>
+#include <vlc_ancillary.h>
 #include <vlc_list.h>
 
 #include "filter_priv.h"
@@ -133,6 +134,10 @@ struct vlc_gl_filters {
     struct {
         /** Last updated picture PTS */
         vlc_tick_t pts;
+
+        /** Dolby Vision RPU metadata for the last picture, if any */
+        vlc_video_dovi_metadata_t dovi_rpu;
+        int has_dovi;
     } pic;
 };
 
@@ -158,6 +163,7 @@ vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
 
     memset(&filters->viewport, 0, sizeof(filters->viewport));
     filters->pic.pts = VLC_TICK_INVALID;
+    filters->pic.has_dovi = 0;
 
     return filters;
 }
@@ -370,6 +376,13 @@ vlc_gl_filters_UpdatePicture(struct vlc_gl_filters *filters,
 
     filters->pic.pts = picture->date;
 
+    struct vlc_ancillary *dovi = picture_GetAncillary(picture, VLC_ANCILLARY_ID_DOVI);
+    filters->pic.has_dovi = !!dovi;
+    if (dovi) {
+        memcpy(&filters->pic.dovi_rpu, vlc_ancillary_GetData(dovi),
+               sizeof(filters->pic.dovi_rpu));
+    }
+
     struct vlc_gl_filter_priv *first_filter =
         vlc_list_first_entry_or_null(&filters->list, struct vlc_gl_filter_priv,
                                      node);
@@ -393,6 +406,7 @@ vlc_gl_filters_Draw(struct vlc_gl_filters *filters)
     struct vlc_gl_input_meta meta = {
         .pts = filters->pic.pts,
         .plane = 0,
+        .dovi_rpu = filters->pic.has_dovi ? &filters->pic.dovi_rpu : NULL,
     };
 
     struct vlc_gl_picture direct_pic;


=====================================
modules/video_output/opengl/pl_scale.c
=====================================
@@ -69,6 +69,10 @@ struct sys
     struct pl_frame frame_out;
     struct pl_render_params render_params;
 
+#if PL_API_VER >= 185
+    struct pl_dovi_metadata dovi_metadata;
+#endif
+
     unsigned out_width;
     unsigned out_height;
 };
@@ -173,6 +177,18 @@ Draw(struct vlc_gl_filter *filter, const struct vlc_gl_picture *pic,
         r->y1 = coords[3] * h;
     }
 
+#if PL_API_VER >= 185
+    if (frame_in->repr.dovi && meta->dovi_rpu) {
+        vlc_placebo_DoviMetadata(meta->dovi_rpu, &sys->dovi_metadata);
+        struct pl_hdr_metadata *hdr = &frame_in->color.hdr;
+        const float scale = 1.0f / ((1 << 12) - 1);
+        hdr->min_luma = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS,
+                                       scale * meta->dovi_rpu->source_min_pq);
+        hdr->max_luma = pl_hdr_rescale(PL_HDR_PQ, PL_HDR_NITS,
+                                       scale * meta->dovi_rpu->source_max_pq);
+    }
+#endif
+
     GLint value;
     vt->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &value);
     GLuint final_draw_framebuffer = value; /* as GLuint */
@@ -293,6 +309,15 @@ Open(struct vlc_gl_filter *filter, const config_chain_t *config,
         .color = vlc_placebo_ColorSpace(&glfmt->fmt),
     };
 
+#if PL_API_VER >= 185
+    if (glfmt->fmt.dovi.rpu_present && !glfmt->fmt.dovi.el_present) {
+        sys->frame_in.color.primaries = PL_COLOR_PRIM_BT_2020;
+        sys->frame_in.color.transfer = PL_COLOR_TRC_PQ;
+        sys->frame_in.repr.sys = PL_COLOR_SYSTEM_DOLBYVISION;
+        sys->frame_in.repr.dovi = &sys->dovi_metadata; /* to be filled later */
+    }
+#endif
+
     /* Initialize frame_in.planes */
     int plane_count =
         vlc_placebo_PlaneComponents(&glfmt->fmt, sys->frame_in.planes);


=====================================
modules/video_output/opengl/vout_helper.c
=====================================
@@ -151,8 +151,9 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
 
     int upscaler = var_InheritInteger(gl, "gl-upscaler");
     int downscaler = var_InheritInteger(gl, "gl-downscaler");
+    int has_dovi = fmt->dovi.rpu_present && !fmt->dovi.el_present; /* can't handle EL yet */
 
-    if (upscaler || downscaler)
+    if (upscaler || downscaler || has_dovi)
     {
         char upscaler_value[12];
         char downscaler_value[12];



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b4d374071298e944d31ddaba51d317c72b006204...b1dcc6ae54344676915ad4a05a5aa3c0fc412097

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b4d374071298e944d31ddaba51d317c72b006204...b1dcc6ae54344676915ad4a05a5aa3c0fc412097
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