From 327940361170a4d830bc7c120503cdd0396a125a Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 16 Mar 2009 23:30:48 +0200 Subject: [PATCH] demux_mkv: Parse ordered chapter information Parse the ordered chapter structure if present and place the information in the public demuxer structure. Nothing uses the information yet. --- libmpdemux/demux_mkv.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++-- libmpdemux/demuxer.h | 17 +++++++++++- libmpdemux/ebml.h | 3 ++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index 9c17751e2e..8f8a53e6da 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -12,7 +12,9 @@ #include #include #include +#include +#include "talloc.h" #include "options.h" #include "stream/stream.h" #include "demuxer.h" @@ -405,6 +407,24 @@ static int demux_mkv_read_info(demuxer_t *demuxer) return 1; break; + case MATROSKA_ID_SEGMENTUID:; + l = ebml_read_length(s, &i); + length -= i; + if (l != sizeof(demuxer->matroska_data.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] segment uid invalid length %"PRIu64"\n", l); + stream_skip(s, l); + } else { + stream_read(s, demuxer->matroska_data.segment_uid, l); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid"); + for (int i = 0; i < l; i++) + mp_msg(MSGT_DEMUX, MSGL_V, " %02x", + demuxer->matroska_data.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + length -= l; + break; + default: ebml_read_skip(s, &l); length -= l; @@ -1074,10 +1094,11 @@ demux_mkv_read_cues (demuxer_t *demuxer) return 0; } -static uint64_t read_one_chapter(demuxer_t *demuxer, stream_t *s) +static uint64_t read_one_chapter(struct demuxer *demuxer, stream_t *s) { uint64_t len, l; uint64_t start = 0, end = 0; + struct matroska_chapter chapter = {}; char *name = 0; int i; uint32_t id; @@ -1117,6 +1138,24 @@ static uint64_t read_one_chapter(demuxer_t *demuxer, stream_t *s) } break; + case MATROSKA_ID_CHAPTERSEGMENTUID: + l = ebml_read_length(s, &i); + len -= l + i; + if (l != sizeof(chapter.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] chapter segment uid invalid length %"PRIu64"\n", + l); + stream_skip(s, l); + } else { + stream_read(s, chapter.segment_uid, l); + chapter.has_segment_uid = true; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter segment uid "); + for (int i = 0; i < l; i++) + mp_msg(MSGT_DEMUX, MSGL_V, "%02x ", chapter.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + break; + default: ebml_read_skip(s, &l); len -= l; @@ -1128,6 +1167,15 @@ static uint64_t read_one_chapter(demuxer_t *demuxer, stream_t *s) name = strdup("(unnamed)"); int cid = demuxer_add_chapter(demuxer, name, start, end); + struct matroska_data *m = &demuxer->matroska_data; + m->ordered_chapters = talloc_realloc(demuxer, m->ordered_chapters, + struct matroska_chapter, + m->num_ordered_chapters + 1); + chapter.start = start; + chapter.end = end; + // Will be undone later if this is a normal chapter rather than ordered + m->ordered_chapters[m->num_ordered_chapters] = chapter; + m->num_ordered_chapters++; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d." "%03d to %02d:%02d:%02d.%03d, %s\n", @@ -1160,13 +1208,23 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); length = ebml_read_length(s, NULL); + bool have_edition = false; while (length > 0) { id = ebml_read_id(s, &i); length -= i; switch (id) { - case MATROSKA_ID_EDITIONENTRY:; + case MATROSKA_ID_EDITIONENTRY: + if (have_edition) { + mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Multiple edition entries" + " - ignoring all but first!\n"); + ebml_read_skip(s, &l); + length -= l; + break; + } + have_edition = true; uint64_t editionlen = ebml_read_length(s, &i); length -= editionlen + i; + bool ordered = false; while (editionlen > 0) { id = ebml_read_id(s, &i); editionlen -= i; @@ -1174,12 +1232,25 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) case MATROSKA_ID_CHAPTERATOM: l = read_one_chapter(demuxer, s); break; + case MATROSKA_ID_EDITIONFLAGORDERED: + ordered = ebml_read_uint(s, &l); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] Ordered chapter flag: %d\n", ordered); + break; + default: ebml_read_skip(s, &l); break; } editionlen -= l; } + if (!ordered) { + // The chapters should be interpreted as normal ones, + // so undo the addition of this information. + talloc_free(demuxer->matroska_data.ordered_chapters); + demuxer->matroska_data.ordered_chapters = NULL; + demuxer->matroska_data.num_ordered_chapters = 0; + } break; default: diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 4815c8b7d9..8d1f1d0b88 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "stream/stream.h" @@ -187,6 +188,18 @@ typedef struct demux_chapter char* name; } demux_chapter_t; +struct matroska_data { + unsigned char segment_uid[16]; + // Ordered chapter information if any + struct matroska_chapter { + uint64_t start; + uint64_t end; + bool has_segment_uid; + unsigned char segment_uid[16]; + } *ordered_chapters; + int num_ordered_chapters; +}; + typedef struct demux_attachment { char* name; @@ -220,10 +233,12 @@ typedef struct demuxer { demux_chapter_t* chapters; int num_chapters; - + demux_attachment_t* attachments; int num_attachments; + struct matroska_data matroska_data; + void* priv; // fileformat-dependent data char** info; struct MPOpts *opts; diff --git a/libmpdemux/ebml.h b/libmpdemux/ebml.h index c4d7256d91..345f08b46a 100644 --- a/libmpdemux/ebml.h +++ b/libmpdemux/ebml.h @@ -54,6 +54,7 @@ #define MATROSKA_ID_WRITINGAPP 0x5741 #define MATROSKA_ID_MUXINGAPP 0x4D80 #define MATROSKA_ID_DATEUTC 0x4461 +#define MATROSKA_ID_SEGMENTUID 0x73A4 /* ID in the tracks master */ #define MATROSKA_ID_TRACKENTRY 0xAE @@ -126,11 +127,13 @@ /* IDs in the chapters master */ #define MATROSKA_ID_EDITIONENTRY 0x45B9 +#define MATROSKA_ID_EDITIONFLAGORDERED 0x45DD #define MATROSKA_ID_CHAPTERATOM 0xB6 #define MATROSKA_ID_CHAPTERTIMESTART 0x91 #define MATROSKA_ID_CHAPTERTIMEEND 0x92 #define MATROSKA_ID_CHAPTERDISPLAY 0x80 #define MATROSKA_ID_CHAPSTRING 0x85 +#define MATROSKA_ID_CHAPTERSEGMENTUID 0x6E67 /* IDs in the cluster master */ #define MATROSKA_ID_CLUSTERTIMECODE 0xE7 -- 2.11.4.GIT