1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-16 12:17:12 +00:00

demux: retrieve per-chapter metadata

Retrieve per-chapter metadata, but don't do much with it. We just make
the metadata of the _current_ chapter available as chapter-metadata
property. Returning the full chapter list with metadata would be no
problem, except that the property interface isn't really good with
structured data, so it's not available for now.

Not sure if it's worth it, but it was requested via github issue #201.
This commit is contained in:
wm4 2013-09-08 07:42:05 +02:00
parent ba07000b88
commit 35fd083828
6 changed files with 59 additions and 10 deletions

View File

@ -412,6 +412,7 @@ Name W Comment
``angle`` x current DVD angle
``metadata`` metadata key/value pairs
``metadata/<key>`` value of metadata entry ``<key>``
``chapter-metadata`` metadata of current chapter (works similar)
``pause`` x pause status (bool)
``cache`` network cache fill state (0-100)
``pts-association-mode`` x see ``--pts-association-mode``

View File

@ -870,18 +870,33 @@ void demuxer_sort_chapters(demuxer_t *demuxer)
}
int demuxer_add_chapter(demuxer_t *demuxer, struct bstr name,
uint64_t start, uint64_t end)
uint64_t start, uint64_t end, uint64_t demuxer_id)
{
struct demux_chapter new = {
.original_index = demuxer->num_chapters,
.start = start,
.end = end,
.name = name.len ? bstrdup0(demuxer, name) : NULL,
.metadata = talloc_zero(demuxer, struct mp_tags),
.demuxer_id = demuxer_id,
};
mp_tags_set_bstr(new.metadata, bstr0("title"), name);
MP_TARRAY_APPEND(demuxer, demuxer->chapters, demuxer->num_chapters, new);
return 0;
}
void demuxer_add_chapter_info(struct demuxer *demuxer, uint64_t demuxer_id,
bstr key, bstr value)
{
for (int n = 0; n < demuxer->num_chapters; n++) {
struct demux_chapter *ch = &demuxer->chapters[n];
if (ch->demuxer_id == demuxer_id) {
mp_tags_set_bstr(ch->metadata, key, value);
return;
}
}
}
static void add_stream_chapters(struct demuxer *demuxer)
{
if (demuxer->num_chapters)
@ -892,7 +907,7 @@ static void add_stream_chapters(struct demuxer *demuxer)
if (stream_control(demuxer->stream, STREAM_CTRL_GET_CHAPTER_TIME, &p)
!= STREAM_OK)
return;
demuxer_add_chapter(demuxer, bstr0(""), p * 1e9, 0);
demuxer_add_chapter(demuxer, bstr0(""), p * 1e9, 0, 0);
}
}

View File

@ -122,6 +122,8 @@ typedef struct demux_chapter
int original_index;
uint64_t start, end;
char *name;
struct mp_tags *metadata;
uint64_t demuxer_id; // for mapping to internal demuxer data structures
} demux_chapter_t;
struct matroska_data {
@ -253,7 +255,9 @@ void demuxer_help(void);
int demuxer_add_attachment(struct demuxer *demuxer, struct bstr name,
struct bstr type, struct bstr data);
int demuxer_add_chapter(struct demuxer *demuxer, struct bstr name,
uint64_t start, uint64_t end);
uint64_t start, uint64_t end, uint64_t demuxer_id);
void demuxer_add_chapter_info(struct demuxer *demuxer, uint64_t demuxer_id,
bstr key, bstr value);
int demuxer_seek_chapter(struct demuxer *demuxer, int chapter,
double *seek_pts);
void demuxer_sort_chapters(demuxer_t *demuxer);

View File

@ -627,7 +627,12 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
(AVRational){1, 1000000000});
t = av_dict_get(c->metadata, "title", NULL, 0);
demuxer_add_chapter(demuxer, t ? bstr0(t->value) : bstr0(NULL),
start, end);
start, end, i);
AVDictionaryEntry *t = NULL;
while ((t = av_dict_get(c->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
demuxer_add_chapter_info(demuxer, i, bstr0(t->key),
bstr0(t->value));
}
}
add_new_streams(demuxer);

View File

@ -878,7 +878,8 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer)
BSTR_P(name));
if (idx == selected_edition){
demuxer_add_chapter(demuxer, name, chapter.start, chapter.end);
demuxer_add_chapter(demuxer, name, chapter.start, chapter.end,
ca->chapter_uid);
if (editions[idx].edition_flag_ordered) {
chapter.name = talloc_strndup(m_chapters, name.start,
name.len);
@ -913,11 +914,21 @@ static int demux_mkv_read_tags(demuxer_t *demuxer)
for (int i = 0; i < tags.n_tag; i++) {
struct ebml_tag tag = tags.tag[i];
if (tag.targets.target_track_uid || tag.targets.target_edition_uid ||
tag.targets.target_chapter_uid || tag.targets.target_attachment_uid)
tag.targets.target_attachment_uid)
continue;
for (int j = 0; j < tag.n_simple_tag; j++)
demux_info_add_bstr(demuxer, tag.simple_tag[j].tag_name, tag.simple_tag[j].tag_string);
if (tag.targets.target_chapter_uid) {
for (int j = 0; j < tag.n_simple_tag; j++) {
demuxer_add_chapter_info(demuxer, tag.targets.target_chapter_uid,
tag.simple_tag[j].tag_name,
tag.simple_tag[j].tag_string);
}
} else {
for (int j = 0; j < tag.n_simple_tag; j++) {
demux_info_add_bstr(demuxer, tag.simple_tag[j].tag_name,
tag.simple_tag[j].tag_string);
}
}
}
talloc_free(parse_ctx.talloc_ctx);

View File

@ -694,6 +694,19 @@ static int mp_property_metadata(m_option_t *prop, int action, void *arg,
return tag_property(prop, action, arg, demuxer->metadata);
}
static int mp_property_chapter_metadata(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
struct demuxer *demuxer = mpctx->master_demuxer;
int chapter = get_current_chapter(mpctx);
if (!demuxer || chapter < 0)
return M_PROPERTY_UNAVAILABLE;
assert(chapter < demuxer->num_chapters);
return tag_property(prop, action, arg, demuxer->chapters[chapter].metadata);
}
static int mp_property_pause(m_option_t *prop, int action, void *arg,
void *ctx)
{
@ -1741,8 +1754,8 @@ static const m_option_t mp_properties[] = {
0, 0, 0, NULL },
{ "editions", mp_property_editions, CONF_TYPE_INT },
{ "angle", mp_property_angle, &m_option_type_dummy },
{ "metadata", mp_property_metadata, CONF_TYPE_STRING_LIST,
0, 0, 0, NULL },
{ "metadata", mp_property_metadata, CONF_TYPE_STRING_LIST },
{ "chapter-metadata", mp_property_chapter_metadata, CONF_TYPE_STRING_LIST },
M_OPTION_PROPERTY_CUSTOM("pause", mp_property_pause),
{ "cache", mp_property_cache, CONF_TYPE_INT },
M_OPTION_PROPERTY("pts-association-mode"),