Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

command: add dolby-vision-profile and dolby-vision-level to track-list #14082

Merged
merged 3 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DOCS/interface-changes/dolby-vision-configuration.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add `track-list/N/dolby-vision-profile` and `track-list/N/dolby-vision-level`
6 changes: 6 additions & 0 deletions DOCS/man/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions TOOLS/matroska.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@
),
),
),
'BlockAdditionMapping*, 41e4, sub', (
'BlockAddIDValue, 41f0, uint',
'BlockAddIDName, 41a4, str',
'BlockAddIDType, 41e7, uint',
'BlockAddIDExtraData, 41ed, binary',
),
),
),

Expand Down
3 changes: 3 additions & 0 deletions demux/demux_lavf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
106 changes: 106 additions & 0 deletions demux/demux_mkv.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <assert.h>

#include <libavutil/common.h>
#include <libavutil/dovi_meta.h>
#include <libavutil/lzo.h>
#include <libavutil/intreadwrite.h>
#include <libavutil/avstring.h>
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -746,13 +749,92 @@ 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
*/
static void demux_mkv_free_trackentry(mkv_track_t *track)
{
talloc_free(track->parser_tmp);
av_freep(&track->dovi_config);
talloc_free(track);
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -1599,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);

Expand Down Expand Up @@ -2898,6 +2992,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);
Expand Down
4 changes: 4 additions & 0 deletions demux/stheader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions player/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}
};

Expand Down
Loading