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
This commit is contained in:
Anton Khirnov 2008-05-22 22:07:09 +00:00 committed by Aurelien Jacobs
parent 79d7836a5e
commit f5275b3ce7
2 changed files with 170 additions and 0 deletions

View File

@ -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,

View File

@ -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);