From e94288183fc8d217ee792280bb4d6cb8c16be9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 8 May 2024 03:19:05 +0200 Subject: [PATCH 1/3] demux_mkv: demux Block Additional Mappings Parse Dolby Vision configuration. --- TOOLS/matroska.py | 6 ++++ demux/demux_mkv.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 61a33ffb842e8..6abece6e95886 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -165,6 +165,12 @@ ), ), ), + 'BlockAdditionMapping*, 41e4, sub', ( + 'BlockAddIDValue, 41f0, uint', + 'BlockAddIDName, 41a4, str', + 'BlockAddIDType, 41e7, uint', + 'BlockAddIDExtraData, 41ed, binary', + ), ), ), diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 2d13eb6a4b6d7..0db7cb1ca2652 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -154,6 +155,8 @@ typedef struct mkv_track { /* latest added index entry for this track */ size_t last_index_entry; + + AVDOVIDecoderConfigurationRecord *dovi_config; } mkv_track_t; typedef struct mkv_index { @@ -746,6 +749,84 @@ static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track, parse_trackprojection(demuxer, track, &video->projection); } +static void parse_dovi_config(struct demuxer *demuxer, struct mkv_track *track, + const uint8_t *buf_ptr, size_t size) +{ + if (size < 4) + return; + + av_free(track->dovi_config); + + size_t dovi_size; + track->dovi_config = av_dovi_alloc(&dovi_size); + MP_HANDLE_OOM(track->dovi_config); + + track->dovi_config->dv_version_major = *buf_ptr++; // 8 bits + track->dovi_config->dv_version_minor = *buf_ptr++; // 8 bits + + uint32_t buf; + buf = *buf_ptr++ << 8; + buf |= *buf_ptr++; + + track->dovi_config->dv_profile = (buf >> 9) & 0x7f; // 7 bits + track->dovi_config->dv_level = (buf >> 3) & 0x3f; // 6 bits + track->dovi_config->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit + track->dovi_config->el_present_flag = (buf >> 1) & 0x01; // 1 bit + track->dovi_config->bl_present_flag = buf & 0x01; // 1 bit + + if (size >= 5) { + track->dovi_config->dv_bl_signal_compatibility_id = ((*buf_ptr++) >> 4) & 0x0f; // 4 bits + } else { + // 0 stands for None + // Dolby Vision V1.2.93 profiles and levels + track->dovi_config->dv_bl_signal_compatibility_id = 0; + } + + MP_DBG(demuxer, "| + Dolby Vision - version: %d.%d, profile: %d, level: %d, " + "RPU: %d, EL: %d, BL: %d, ID: %d\n", + track->dovi_config->dv_version_major, + track->dovi_config->dv_version_minor, + track->dovi_config->dv_profile, + track->dovi_config->dv_level, + track->dovi_config->rpu_present_flag, + track->dovi_config->el_present_flag, + track->dovi_config->bl_present_flag, + track->dovi_config->dv_bl_signal_compatibility_id); +} + +static void parse_block_addition_mapping(struct demuxer *demuxer, + struct mkv_track *track, + struct ebml_block_addition_mapping *block_addition_mapping, + int count) +{ + for (int i = 0; i < count; ++i) { + if (!block_addition_mapping->n_block_add_id_type) + continue; + switch (block_addition_mapping->block_add_id_type) { + case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: + break; + case MKBETAG('a','v','c','E'): + case MKBETAG('h','v','c','E'): + MP_WARN(demuxer, "Dolby Vision enhancement-layer playback is not supported.\n"); + break; + case MKBETAG('d','v','c','C'): + case MKBETAG('d','v','v','C'): + if (block_addition_mapping->n_block_add_id_extra_data) { + bstr data = block_addition_mapping->block_add_id_extra_data; + parse_dovi_config(demuxer, track, data.start, data.len); + } + break; + case MKBETAG('m','v','c','C'): + MP_WARN(demuxer, "MVC configuration is not supported.\n"); + break; + default: + MP_WARN(demuxer, "Unsupported block addition type: %" PRIx64 "\n", + block_addition_mapping->block_add_id_type); + } + block_addition_mapping++; + } +} + /** * \brief free any data associated with given track * \param track track of which to free data @@ -753,6 +834,7 @@ static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track, static void demux_mkv_free_trackentry(mkv_track_t *track) { talloc_free(track->parser_tmp); + av_freep(&track->dovi_config); talloc_free(track); } @@ -859,6 +941,12 @@ static void parse_trackentry(struct demuxer *demuxer, if (entry->n_codec_delay) track->codec_delay = entry->codec_delay / 1e9; + if (entry->n_block_addition_mapping) { + parse_block_addition_mapping(demuxer, track, + entry->block_addition_mapping, + entry->n_block_addition_mapping); + } + mkv_d->tracks[mkv_d->num_tracks++] = track; } From 621482b423a94010471984a5b5917891b0c159b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 8 May 2024 03:20:45 +0200 Subject: [PATCH 2/3] demux_mkv: inject AV_PKT_DATA_DOVI_CONF to demuxed packets --- demux/demux_mkv.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 0db7cb1ca2652..8d8a5d66de8b1 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -2986,6 +2986,18 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) add->block_additional.start, add->block_additional.len); } } + if (track->dovi_config) { + size_t dovi_size; + AVDOVIDecoderConfigurationRecord *dovi = av_dovi_alloc(&dovi_size); + MP_HANDLE_OOM(dovi); + memcpy(dovi, track->dovi_config, dovi_size); + if (av_packet_add_side_data(dp->avpacket, + AV_PKT_DATA_DOVI_CONF, + (uint8_t *)dovi, dovi_size) < 0) + { + av_free(dovi); + } + } mkv_parse_and_add_packet(demuxer, track, dp); talloc_free_children(track->parser_tmp); From 339d4f8eca6bd1403bdeec57a6db51d256f7ef4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 8 May 2024 03:21:42 +0200 Subject: [PATCH 3/3] command: add dolby-vision-profile and dolby-vision-level to track-list --- DOCS/interface-changes/dolby-vision-configuration.txt | 1 + DOCS/man/input.rst | 6 ++++++ demux/demux_lavf.c | 3 +++ demux/demux_mkv.c | 6 ++++++ demux/stheader.h | 4 ++++ player/command.c | 4 ++++ 6 files changed, 24 insertions(+) create mode 100644 DOCS/interface-changes/dolby-vision-configuration.txt diff --git a/DOCS/interface-changes/dolby-vision-configuration.txt b/DOCS/interface-changes/dolby-vision-configuration.txt new file mode 100644 index 0000000000000..9383310fb9d41 --- /dev/null +++ b/DOCS/interface-changes/dolby-vision-configuration.txt @@ -0,0 +1 @@ +add `track-list/N/dolby-vision-profile` and `track-list/N/dolby-vision-level` diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index df4766b5be415..e0bfadf98f457 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -3185,6 +3185,10 @@ Property list values currently. It's possible that future mpv versions will make these properties unavailable instead in this case. + ``track-list/N/dolby-vision-profile``, ``track-list/N/dolby-vision-level`` + Dolby Vision profile and level. May not be available if the container + does not provide this information. + When querying the property with the client API using ``MPV_FORMAT_NODE``, or with Lua ``mp.get_property_native``, this will return a mpv_node with the following contents: @@ -3229,6 +3233,8 @@ Property list "replaygain-track-gain" MPV_FORMAT_DOUBLE "replaygain-album-peak" MPV_FORMAT_DOUBLE "replaygain-album-gain" MPV_FORMAT_DOUBLE + "dolby-vision-profile" MPV_FORMAT_INT64 + "dolby-vision-level" MPV_FORMAT_INT64 ``current-tracks/...`` This gives access to currently selected tracks. It redirects to the correct diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 94b1c893c521a..c1dbe6a8a87e8 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -796,6 +796,9 @@ static void handle_new_stream(demuxer_t *demuxer, int i) MP_VERBOSE(demuxer, "Found Dolby Vision config record: profile " "%d level %d\n", cfg->dv_profile, cfg->dv_level); av_format_inject_global_side_data(avfc); + sh->codec->dovi = true; + sh->codec->dv_profile = cfg->dv_profile; + sh->codec->dv_level = cfg->dv_level; } // This also applies to vfw-muxed mkv, but we can't detect these easily. diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 8d8a5d66de8b1..4a9bfb2faf9ed 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1687,6 +1687,12 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track) sh_v->rotate = rotate; } + if (track->dovi_config) { + sh_v->dovi = true; + sh_v->dv_level = track->dovi_config->dv_level; + sh_v->dv_profile = track->dovi_config->dv_profile; + } + done: demux_add_sh_stream(demuxer, sh); diff --git a/demux/stheader.h b/demux/stheader.h index 036c8f54e7f65..6025aa5a0c914 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -121,6 +121,10 @@ struct mp_codec_params { struct pl_color_repr repr; // color representaion info where available struct mp_rect crop; // crop to be applied + bool dovi; + uint8_t dv_profile; + uint8_t dv_level; + // STREAM_VIDEO + STREAM_AUDIO int bits_per_coded_sample; char *format_name; // pixel format (video) or sample format (audio) diff --git a/player/command.c b/player/command.c index 4c7ca24db9a3e..e7561a872958d 100644 --- a/player/command.c +++ b/player/command.c @@ -2078,6 +2078,10 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) .unavailable = !has_rg}, {"replaygain-album-gain", SUB_PROP_FLOAT(rg.album_gain), .unavailable = !has_rg}, + {"dolby-vision-profile", SUB_PROP_INT(p.dv_profile), + .unavailable = !p.dovi}, + {"dolby-vision-level", SUB_PROP_INT(p.dv_level), + .unavailable = !p.dovi}, {0} };