From a094971ce86ef653ca8b2733f7f105c5291e6eb5 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] 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 61a33ffb84..6abece6e95 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -165,6 +165,12 @@ elements_matroska = ( ), ), ), + '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 2d13eb6a4b..0db7cb1ca2 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; }