[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