mirror of https://git.ffmpeg.org/ffmpeg.git
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:
parent
79d7836a5e
commit
f5275b3ce7
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue