From e83d6ca87c7da2d6a9ff09dcec339cadc054610f Mon Sep 17 00:00:00 2001
From: Neil Birkbeck <neil.birkbeck@gmail.com>
Date: Thu, 3 Nov 2016 17:13:03 -0700
Subject: [PATCH] lavf/matroskaenc.c: use metadata key/value to set mastering
metadata
Add key/value metadata interface to allow command line setting of AVMasteringDisplayMetadata. The formatting is the same as the option in libx265.
Signed-off-by: Neil Birkbeck <neil.birkbeck@gmail.com>
---
libavformat/matroskaenc.c | 49 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 3 deletions(-)
@@ -804,17 +804,61 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
}
static int mkv_write_video_color(AVIOContext *pb, AVCodecParameters *par, AVStream *st) {
+ AVDictionaryEntry *tag;
AVIOContext *dyn_cp;
uint8_t *colorinfo_ptr;
int side_data_size = 0;
int ret, colorinfo_size;
const uint8_t *side_data = av_stream_get_side_data(
st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, &side_data_size);
+ AVMasteringDisplayMetadata *metadata =
+ (side_data_size == sizeof(AVMasteringDisplayMetadata)) ?
+ (AVMasteringDisplayMetadata*)side_data : NULL;
ret = avio_open_dyn_buf(&dyn_cp);
if (ret < 0)
return ret;
+ // If key-value pair metadata is specified, override the packet side data
+ // Accept a format similar to the command line argument in x265:
+ // G(x,y)B(x,y)R(x,y)WP(x,y),L(max,min)
+ if (tag = av_dict_get(st->metadata, "master_display", NULL, 0)) {
+ int primaries[4][2];
+ int luma[2];
+ int num_read = sscanf(tag->value,
+ "G(%d,%d)B(%d,%d)R(%d,%d)WP(%d,%d)L(%d,%d)",
+ primaries[1], primaries[1] + 1,
+ primaries[2], primaries[2] + 1,
+ primaries[0], primaries[0] + 1,
+ primaries[3], primaries[3] + 1,
+ luma + 1, luma + 0);
+ if (num_read >= 8) {
+ const float chroma_denom = 50000.f;
+ const float luma_denom = 10000.f;
+ int i, j;
+ if (!metadata) {
+ metadata = (AVMasteringDisplayMetadata*) av_stream_new_side_data(
+ st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
+ sizeof(AVMasteringDisplayMetadata));
+ memset(metadata, 0, sizeof(AVMasteringDisplayMetadata));
+ }
+ for (i = 0; i < 3; ++i) {
+ for (j = 0; j < 2; ++j) {
+ metadata->display_primaries[i][j] =
+ av_make_q(primaries[i][j], chroma_denom);
+ }
+ }
+ metadata->white_point[0] = av_make_q(primaries[3][0], chroma_denom);
+ metadata->white_point[1] = av_make_q(primaries[3][1], chroma_denom);
+ metadata->has_primaries = 1;
+ if (num_read == 10) {
+ metadata->min_luminance = av_make_q(luma[0], luma_denom);
+ metadata->max_luminance = av_make_q(luma[1], luma_denom);
+ metadata->has_luminance = 1;
+ }
+ }
+ }
+
if (par->color_trc != AVCOL_TRC_UNSPECIFIED &&
par->color_trc < AVCOL_TRC_NB) {
put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS,
@@ -840,11 +884,9 @@ static int mkv_write_video_color(AVIOContext *pb, AVCodecParameters *par, AVStre
put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, (xpos >> 7) + 1);
put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, (ypos >> 7) + 1);
}
- if (side_data_size == sizeof(AVMasteringDisplayMetadata)) {
+ if (metadata) {
ebml_master meta_element = start_ebml_master(
dyn_cp, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 0);
- const AVMasteringDisplayMetadata *metadata =
- (const AVMasteringDisplayMetadata*)side_data;
if (metadata->has_primaries) {
put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RX,
av_q2d(metadata->display_primaries[0][0]));
@@ -1425,6 +1467,7 @@ static int mkv_check_tag_name(const char *name, unsigned int elementid)
{
return av_strcasecmp(name, "title") &&
av_strcasecmp(name, "stereo_mode") &&
+ av_strcasecmp(name, "master_display") &&
av_strcasecmp(name, "creation_time") &&
av_strcasecmp(name, "encoding_tool") &&
av_strcasecmp(name, "duration") &&
--
2.8.0.rc3.226.g39d4020