summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-08 07:42:05 +0200
committerwm4 <wm4@nowhere>2013-09-08 07:43:23 +0200
commit35fd083828a57eb7ae995bd081dad88a8d64f75d (patch)
treeb6f377dceee9ad4f888bb44d0842a00fc4ee3d04
parentba07000b886802909a52810568705897d600263a (diff)
downloadmpv-35fd083828a57eb7ae995bd081dad88a8d64f75d.tar.bz2
mpv-35fd083828a57eb7ae995bd081dad88a8d64f75d.tar.xz
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.
-rw-r--r--DOCS/man/en/input.rst1
-rw-r--r--demux/demux.c19
-rw-r--r--demux/demux.h6
-rw-r--r--demux/demux_lavf.c7
-rw-r--r--demux/demux_mkv.c19
-rw-r--r--mpvcore/command.c17
6 files changed, 59 insertions, 10 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst
index bacb99c14b..c05fb664de 100644
--- a/DOCS/man/en/input.rst
+++ b/DOCS/man/en/input.rst
@@ -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``
diff --git a/demux/demux.c b/demux/demux.c
index 8d84d4450c..c3635b9ab1 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -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);
}
}
diff --git a/demux/demux.h b/demux/demux.h
index 00758ea012..c42c964fa9 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -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);
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 908eb3c111..dbe16a76b9 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -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);
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index a391dde5a6..120bbbb93a 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -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);
diff --git a/mpvcore/command.c b/mpvcore/command.c
index d8642e40fa..d986ae1a64 100644
--- a/mpvcore/command.c
+++ b/mpvcore/command.c
@@ -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"),