From 07fbba3935e9d4327d3ae946b747486693d9d0f7 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 6 Oct 2013 20:49:12 -0400 Subject: matroska: store segment/edition uids in a single structure To support edition references in matroska chapters, editions need to be remembered for each chapter and source. To facilitate easier management of these now-paired uids, a single structure is used. --- demux/demux.h | 14 +++++++++++--- demux/demux_mkv.c | 23 +++++++++++++++-------- 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'demux') diff --git a/demux/demux.h b/demux/demux.h index 1e0546a6d0..0c8f9cb3f8 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -128,14 +128,19 @@ typedef struct demux_chapter uint64_t demuxer_id; // for mapping to internal demuxer data structures } demux_chapter_t; +struct matroska_segment_uid { + unsigned char segment[16]; + uint64_t edition; +}; + struct matroska_data { - unsigned char segment_uid[16]; + struct matroska_segment_uid uid; // Ordered chapter information if any struct matroska_chapter { uint64_t start; uint64_t end; bool has_segment_uid; - unsigned char segment_uid[16]; + struct matroska_segment_uid uid; char *name; } *ordered_chapters; int num_ordered_chapters; @@ -151,7 +156,7 @@ typedef struct demux_attachment struct demuxer_params { int matroska_num_wanted_uids; - unsigned char (*matroska_wanted_uids)[16]; + struct matroska_segment_uid *matroska_wanted_uids; int matroska_wanted_segment; bool *matroska_was_valid; struct ass_library *ass_library; @@ -301,4 +306,7 @@ void mp_tags_set_bstr(struct mp_tags *tags, bstr key, bstr value); char *mp_tags_get_str(struct mp_tags *tags, const char *key); char *mp_tags_get_bstr(struct mp_tags *tags, bstr key); +bool demux_matroska_uid_cmp(struct matroska_segment_uid *a, + struct matroska_segment_uid *b); + #endif /* MPLAYER_DEMUXER_H */ diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index bbbe88d903..9ca4e62ecb 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -377,24 +377,24 @@ static int demux_mkv_read_info(demuxer_t *demuxer) } if (info.n_segment_uid) { int len = info.segment_uid.len; - if (len != sizeof(demuxer->matroska_data.segment_uid)) { + if (len != sizeof(demuxer->matroska_data.uid.segment)) { mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] segment uid invalid length %d\n", len); } else { - memcpy(demuxer->matroska_data.segment_uid, info.segment_uid.start, + memcpy(demuxer->matroska_data.uid.segment, info.segment_uid.start, len); mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid"); for (int i = 0; i < len; i++) mp_msg(MSGT_DEMUX, MSGL_V, " %02x", - demuxer->matroska_data.segment_uid[i]); + demuxer->matroska_data.uid.segment[i]); mp_msg(MSGT_DEMUX, MSGL_V, "\n"); } } if (demuxer->params && demuxer->params->matroska_wanted_uids) { - unsigned char (*uids)[16] = demuxer->params->matroska_wanted_uids; if (info.n_segment_uid) { for (int i = 0; i < demuxer->params->matroska_num_wanted_uids; i++) { - if (!memcmp(info.segment_uid.start, uids[i], 16)) + struct matroska_segment_uid *uid = demuxer->params->matroska_wanted_uids + i; + if (!memcmp(info.segment_uid.start, uid->segment, 16)) goto out; } } @@ -847,7 +847,7 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) if (ca->n_chapter_segment_uid) { chapter.has_segment_uid = true; int len = ca->chapter_segment_uid.len; - if (len != sizeof(chapter.segment_uid)) + if (len != sizeof(chapter.uid.segment)) mp_msg(MSGT_DEMUX, warn_level, "[mkv] Chapter segment uid bad length %d\n", len); else if (ca->n_chapter_segment_edition_uid) { @@ -855,12 +855,12 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) "unsupported edition recursion in chapter; " "will skip on playback!\n"); } else { - memcpy(chapter.segment_uid, ca->chapter_segment_uid.start, + memcpy(chapter.uid.segment, ca->chapter_segment_uid.start, len); mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter segment uid "); for (int n = 0; n < len; n++) mp_msg(MSGT_DEMUX, MSGL_V, "%02x ", - chapter.segment_uid[n]); + chapter.uid.segment[n]); mp_msg(MSGT_DEMUX, MSGL_V, "\n"); } } @@ -2737,3 +2737,10 @@ const demuxer_desc_t demuxer_desc_matroska = { .seek = demux_mkv_seek, .control = demux_mkv_control }; + +bool demux_matroska_uid_cmp(struct matroska_segment_uid *a, + struct matroska_segment_uid *b) +{ + return (!memcmp(a->segment, b->segment, 16) && + a->edition == b->edition); +} -- cgit v1.2.3 From 4f287f17929e4448688266105caa2c939720d01f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 26 Sep 2013 02:21:19 -0400 Subject: matroska: parse the requested edition for the segment reference --- demux/demux_mkv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'demux') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 9ca4e62ecb..8b497a1402 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -850,13 +850,13 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) if (len != sizeof(chapter.uid.segment)) mp_msg(MSGT_DEMUX, warn_level, "[mkv] Chapter segment uid bad length %d\n", len); - else if (ca->n_chapter_segment_edition_uid) { - mp_tmsg(MSGT_DEMUX, warn_level, "[mkv] Warning: " - "unsupported edition recursion in chapter; " - "will skip on playback!\n"); - } else { + else { memcpy(chapter.uid.segment, ca->chapter_segment_uid.start, len); + if (ca->n_chapter_segment_edition_uid) + chapter.uid.edition = ca->chapter_segment_edition_uid; + else + chapter.uid.edition = 0; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter segment uid "); for (int n = 0; n < len; n++) mp_msg(MSGT_DEMUX, MSGL_V, "%02x ", -- cgit v1.2.3 From 069a2d047d458d980181de9b5b9654d3dc2c1bdf Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 26 Sep 2013 02:54:25 -0400 Subject: matroska: set the edition uid when reading a chapter reference --- demux/demux_mkv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'demux') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 8b497a1402..8c827f4131 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -394,8 +394,10 @@ static int demux_mkv_read_info(demuxer_t *demuxer) if (info.n_segment_uid) { for (int i = 0; i < demuxer->params->matroska_num_wanted_uids; i++) { struct matroska_segment_uid *uid = demuxer->params->matroska_wanted_uids + i; - if (!memcmp(info.segment_uid.start, uid->segment, 16)) + if (!memcmp(info.segment_uid.start, uid->segment, 16)) { + demuxer->matroska_data.uid.edition = uid->edition; goto out; + } } } mp_tmsg(MSGT_DEMUX, MSGL_INFO, -- cgit v1.2.3 From 2fe2be4df36c17b460bd9588e9276a2e14e4aca9 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 26 Sep 2013 02:53:54 -0400 Subject: matroska: select the edition using the requested edition uid --- demux/demux_mkv.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'demux') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 8c827f4131..88e91a3717 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -785,6 +785,12 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) struct MPOpts *opts = demuxer->opts; stream_t *s = demuxer->stream; int wanted_edition = opts->edition_id; + uint64_t wanted_edition_uid = demuxer->matroska_data.uid.edition; + + /* A specific edition UID was requested; ignore the user option which is + * only applicable to the top-level file. */ + if (wanted_edition_uid) + wanted_edition = -1; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); struct ebml_chapters file_chapters = {}; @@ -793,7 +799,7 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) &ebml_chapters_desc) < 0) return -1; - int selected_edition = 0; + int selected_edition = -1; int num_editions = file_chapters.n_edition_entry; struct ebml_edition_entry *editions = file_chapters.edition_entry; if (wanted_edition >= 0 && wanted_edition < num_editions) { @@ -802,11 +808,24 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) selected_edition); } else for (int i = 0; i < num_editions; i++) - if (editions[i].edition_flag_default) { + if (wanted_edition_uid && + editions[i].edition_uid == wanted_edition_uid) { + selected_edition = i; + break; + } else if (editions[i].edition_flag_default) { selected_edition = i; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Default edition: %d\n", i); break; } + if (selected_edition < 0) { + if (wanted_edition_uid) { + mp_msg(MSGT_DEMUX, MSGL_ERR, + "[mkv] Unable to find expected edition uid: %"PRIu64"\n", + wanted_edition_uid); + return -1; + } else + selected_edition = 0; + } struct matroska_chapter *m_chapters = NULL; if (editions[selected_edition].edition_flag_ordered) { int count = editions[selected_edition].n_chapter_atom; -- cgit v1.2.3