Skip to content

Commit

Permalink
mp_image: add Dolby Vision metadata mapping
Browse files Browse the repository at this point in the history
Remove side-loading metadata in vo_gpu_next.c and remove unneded
side-data duplication.
  • Loading branch information
kasper93 authored and Dudemanguy committed Mar 9, 2024
1 parent 05c8d5a commit d9c1e9b
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 42 deletions.
23 changes: 21 additions & 2 deletions video/filter/vf_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

#include <libavutil/rational.h>
#include <libavutil/buffer.h>
#include <libavutil/frame.h>
#include <libplacebo/utils/libav.h>

#include "common/msg.h"
#include "common/common.h"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
37 changes: 29 additions & 8 deletions video/mp_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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]));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
2 changes: 0 additions & 2 deletions video/mp_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
24 changes: 0 additions & 24 deletions video/out/placebo/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, &params);
}

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
}
3 changes: 0 additions & 3 deletions video/out/placebo/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
3 changes: 0 additions & 3 deletions video/out/vo_gpu_next.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit d9c1e9b

Please sign in to comment.