Browse Source

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
tags/v0.5
Anton Khirnov Aurelien Jacobs 17 years ago
parent
commit
f5275b3ce7
2 changed files with 170 additions and 0 deletions
  1. +13
    -0
      libavformat/matroska.h
  2. +157
    -0
      libavformat/matroskadec.c

+ 13
- 0
libavformat/matroska.h 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,


+ 157
- 0
libavformat/matroskadec.c 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);


Loading…
Cancel
Save