From d9c1e9bc5c8ca5e4a75b197789b77890375cb8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 11 Feb 2024 00:52:49 +0100 Subject: mp_image: add Dolby Vision metadata mapping Remove side-loading metadata in vo_gpu_next.c and remove unneded side-data duplication. --- video/filter/vf_format.c | 23 +++++++++++++++++++++-- video/mp_image.c | 37 +++++++++++++++++++++++++++++-------- video/mp_image.h | 2 -- video/out/placebo/utils.c | 24 ------------------------ video/out/placebo/utils.h | 3 --- video/out/vo_gpu_next.c | 3 --- 6 files changed, 50 insertions(+), 42 deletions(-) diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index 2063045864..4a2916864c 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -23,6 +23,8 @@ #include #include +#include +#include #include "common/msg.h" #include "common/common.h" @@ -109,6 +111,16 @@ static void set_params(struct vf_format_opts *p, struct mp_image_params *out, mp_image_params_set_dsize(out, dsize.num, dsize.den); } +static inline void *get_side_data(const struct mp_image *mpi, + enum AVFrameSideDataType type) +{ + for (int i = 0; i < mpi->num_ff_side_data; i++) { + if (mpi->ff_side_data[i].type == type) + return (void *)mpi->ff_side_data[i].buf->data; + } + return NULL; +} + static void vf_format_process(struct mp_filter *f) { struct priv *priv = f->priv; @@ -155,8 +167,15 @@ static void vf_format_process(struct mp_filter *f) } if (!priv->opts->dovi) { - av_buffer_unref(&img->dovi); - av_buffer_unref(&img->dovi_buf); + if (img->params.repr.sys == PL_COLOR_SYSTEM_DOLBYVISION) + img->params.repr.sys = PL_COLOR_SYSTEM_BT_2020_NC; + // Map again to strip any DV metadata set to common fields. + img->params.color.hdr = (struct pl_hdr_metadata){0}; + pl_map_hdr_metadata(&img->params.color.hdr, &(struct pl_av_hdr_metadata) { + .mdm = get_side_data(img, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA), + .clm = get_side_data(img, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL), + .dhp = get_side_data(img, AV_FRAME_DATA_DYNAMIC_HDR_PLUS), + }); } if (!priv->opts->film_grain) diff --git a/video/mp_image.c b/video/mp_image.c index 23b1ab8af0..a8c0262aa7 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -209,7 +209,6 @@ static void mp_image_destructor(void *ptr) av_buffer_unref(&mpi->a53_cc); av_buffer_unref(&mpi->dovi); av_buffer_unref(&mpi->film_grain); - av_buffer_unref(&mpi->dovi_buf); for (int n = 0; n < mpi->num_ff_side_data; n++) av_buffer_unref(&mpi->ff_side_data[n].buf); talloc_free(mpi->ff_side_data); @@ -344,7 +343,6 @@ struct mp_image *mp_image_new_ref(struct mp_image *img) ref_buffer(&new->a53_cc); ref_buffer(&new->dovi); ref_buffer(&new->film_grain); - ref_buffer(&new->dovi_buf); new->ff_side_data = talloc_memdup(NULL, new->ff_side_data, new->num_ff_side_data * sizeof(new->ff_side_data[0])); @@ -382,7 +380,6 @@ struct mp_image *mp_image_new_dummy_ref(struct mp_image *img) new->a53_cc = NULL; new->dovi = NULL; new->film_grain = NULL; - new->dovi_buf = NULL; new->num_ff_side_data = 0; new->ff_side_data = NULL; return new; @@ -542,7 +539,6 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) } assign_bufref(&dst->icc_profile, src->icc_profile); assign_bufref(&dst->dovi, src->dovi); - assign_bufref(&dst->dovi_buf, src->dovi_buf); assign_bufref(&dst->film_grain, src->film_grain); assign_bufref(&dst->a53_cc, src->a53_cc); @@ -1093,14 +1089,38 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) if (sd) dst->a53_cc = sd->buf; + AVBufferRef *dovi = NULL; #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 16, 100) sd = av_frame_get_side_data(src, AV_FRAME_DATA_DOVI_METADATA); - if (sd) - dst->dovi = sd->buf; + if (sd) { +#ifdef PL_HAVE_LAV_DOLBY_VISION + const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->buf->data; + const AVDOVIRpuDataHeader *header = av_dovi_get_header(metadata); + if (header->disable_residual_flag) { + dst->dovi = dovi = av_buffer_alloc(sizeof(struct pl_dovi_metadata)); + MP_HANDLE_OOM(dovi); +#if PL_API_VER >= 343 + pl_map_avdovi_metadata(&dst->params.color, &dst->params.repr, + (void *)dst->dovi->data, metadata); +#else + struct pl_frame frame; + frame.repr = dst->params.repr; + frame.color = dst->params.color; + pl_frame_map_avdovi_metadata(&frame, (void *)dst->dovi->data, metadata); + dst->params.repr = frame.repr; + dst->params.color = frame.color; +#endif + } +#endif + } sd = av_frame_get_side_data(src, AV_FRAME_DATA_DOVI_RPU_BUFFER); - if (sd) - dst->dovi_buf = sd->buf; + if (sd) { +#ifdef PL_HAVE_LIBDOVI + pl_hdr_metadata_from_dovi_rpu(&dst->params.color.hdr, sd->buf->data, + sd->buf->size); +#endif + } #endif sd = av_frame_get_side_data(src, AV_FRAME_DATA_FILM_GRAIN_PARAMS); @@ -1125,6 +1145,7 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src) // Allocated, but non-refcounted data. talloc_free(dst->ff_side_data); + av_buffer_unref(&dovi); return res; } diff --git a/video/mp_image.h b/video/mp_image.h index 3a6130a24d..af0d9fd58d 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -116,8 +116,6 @@ typedef struct mp_image { struct AVBufferRef *dovi; // Film grain data, if any struct AVBufferRef *film_grain; - // Dolby Vision RPU buffer, if any - struct AVBufferRef *dovi_buf; // Other side data we don't care about. struct mp_ff_side_data *ff_side_data; int num_ff_side_data; diff --git a/video/out/placebo/utils.c b/video/out/placebo/utils.c index e01c371039..86b0bfd38d 100644 --- a/video/out/placebo/utils.c +++ b/video/out/placebo/utils.c @@ -71,27 +71,3 @@ void mppl_log_set_probing(pl_log log, bool probing) params.log_cb = probing ? log_cb_probing : log_cb; pl_log_update(log, ¶ms); } - -void mp_map_dovi_metadata_to_pl(struct mp_image *mpi, - struct pl_frame *frame) -{ -#ifdef PL_HAVE_LAV_DOLBY_VISION - if (mpi->dovi) { - const AVDOVIMetadata *metadata = (AVDOVIMetadata *) mpi->dovi->data; - const AVDOVIRpuDataHeader *header = av_dovi_get_header(metadata); - - if (header->disable_residual_flag) { - // Only automatically map DoVi RPUs that don't require an EL - struct pl_dovi_metadata *dovi = talloc_ptrtype(mpi, dovi); - pl_frame_map_avdovi_metadata(frame, dovi, metadata); - } - } - -#if defined(PL_HAVE_LIBDOVI) - if (mpi->dovi_buf) - pl_hdr_metadata_from_dovi_rpu(&frame->color.hdr, mpi->dovi_buf->data, - mpi->dovi_buf->size); -#endif - -#endif // PL_HAVE_LAV_DOLBY_VISION -} diff --git a/video/out/placebo/utils.h b/video/out/placebo/utils.h index d2fa619b4a..3f61d8b504 100644 --- a/video/out/placebo/utils.h +++ b/video/out/placebo/utils.h @@ -26,6 +26,3 @@ static inline struct pl_rect2d mp_rect2d_to_pl(struct mp_rect rc) .y1 = rc.y1, }; } - -void mp_map_dovi_metadata_to_pl(struct mp_image *mpi, - struct pl_frame *frame); diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 0139cfd3e1..84facb9e44 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -705,9 +705,6 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src // Update chroma location, must be done after initializing planes pl_frame_set_chroma_location(frame, par->chroma_location); - // Set the frame DOVI metadata - mp_map_dovi_metadata_to_pl(mpi, frame); - if (mpi->film_grain) pl_film_grain_from_av(&frame->film_grain, (AVFilmGrainParams *) mpi->film_grain->data); -- cgit v1.2.3