summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <wyskas@gmail.com>2008-05-22 22:07:09 +0000
committerAurelien Jacobs <aurel@gnuage.org>2008-05-22 22:07:09 +0000
commitf5275b3ce749ecb47c04fff49f8a29bcfbe13254 (patch)
treed84804f14b6355366d9feae9749ba74084a49ec6
parent79d7836a5e213d547629555e3f1157e7197aef68 (diff)
demux chapters out of matroska
patch by Anton Khirnov wyskas _at_ gmail _dot_ com Originally committed as revision 13241 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavformat/matroska.h13
-rw-r--r--libavformat/matroskadec.c157
2 files changed, 170 insertions, 0 deletions
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index c4a5c23274..592e4b140d 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -57,6 +57,7 @@
#define MATROSKA_ID_SEEKHEAD 0x114D9B74
#define MATROSKA_ID_ATTACHMENTS 0x1941A469
#define MATROSKA_ID_CLUSTER 0x1F43B675
+#define MATROSKA_ID_CHAPTERS 0x1043A770
/* IDs in the info master */
#define MATROSKA_ID_TIMECODESCALE 0x2AD7B1
@@ -155,6 +156,18 @@
#define MATROSKA_ID_FILEDATA 0x465C
#define MATROSKA_ID_FILEUID 0x46AE
+/* IDs in the chapters master */
+#define MATROSKA_ID_EDITIONENTRY 0x45B9
+#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_EDITIONUID 0x45BC
+#define MATROSKA_ID_EDITIONFLAGHIDDEN 0x45BD
+#define MATROSKA_ID_CHAPTERUID 0x73C4
+#define MATROSKA_ID_CHAPTERFLAGHIDDEN 0x98
+
typedef enum {
MATROSKA_TRACK_TYPE_NONE = 0x0,
MATROSKA_TRACK_TYPE_VIDEO = 0x1,
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 9c65a5b9cc..2b6f2ba494 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2139,6 +2139,156 @@ matroska_parse_attachments(AVFormatContext *s)
return res;
}
+static int
+matroska_parse_chapters(AVFormatContext *s)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int res = 0;
+ uint32_t id;
+
+ av_log(s, AV_LOG_DEBUG, "parsing chapters...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_EDITIONENTRY: {
+ uint64_t end = AV_NOPTS_VALUE, start = AV_NOPTS_VALUE;
+ char* title = NULL;
+ /* if there is more than one chapter edition
+ we take only the first one */
+ if(s->chapters) {
+ ebml_read_skip(matroska);
+ break;
+ }
+
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_CHAPTERATOM:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_CHAPTERTIMEEND:
+ res = ebml_read_uint(matroska, &id, &end);
+ break;
+
+ case MATROSKA_ID_CHAPTERTIMESTART:
+ res = ebml_read_uint(matroska, &id, &start);
+ break;
+
+ case MATROSKA_ID_CHAPTERDISPLAY:
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_CHAPSTRING:
+ res = ebml_read_utf8(matroska, &id, &title);
+ break;
+
+ default:
+ av_log(s, AV_LOG_INFO, "Ignoring unknown Chapter display ID 0x%x\n", id);
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+ break;
+
+ default:
+ av_log(s, AV_LOG_INFO, "Ignoring unknown Chapter atom ID 0x%x\n", id);
+ case MATROSKA_ID_CHAPTERUID:
+ case MATROSKA_ID_CHAPTERFLAGHIDDEN:
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if(start != AV_NOPTS_VALUE && end != AV_NOPTS_VALUE)
+ res = ff_new_chapter(s, start * AV_TIME_BASE / 1000000000 , end * AV_TIME_BASE / 1000000000, title ? title : "(unnamed)");
+ av_free(title);
+ break;
+
+ default:
+ av_log(s, AV_LOG_INFO, "Ignoring unknown Edition entry ID 0x%x\n", id);
+ case MATROSKA_ID_EDITIONUID:
+ case MATROSKA_ID_EDITIONFLAGHIDDEN:
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ av_log(s, AV_LOG_INFO, "Expected an Edition entry (0x%x), but found 0x%x\n", MATROSKA_ID_EDITIONENTRY, id);
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
static int
@@ -2291,6 +2441,13 @@ matroska_read_header (AVFormatContext *s,
break;
}
+ case MATROSKA_ID_CHAPTERS: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ return res;
+ res = matroska_parse_chapters(s);
+ break;
+ }
+
default:
av_log(matroska->ctx, AV_LOG_INFO,
"Unknown matroska file header ID 0x%x\n", id);