matroskadec: use generic parser to parse attachments

Originally committed as revision 14560 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Aurelien Jacobs 17 years ago
parent 6bbd7c7b79
commit b414cb892e
  1. 131
      libavformat/matroskadec.c

@ -158,6 +158,12 @@ typedef struct MatroskaSubtitleTrack {
sizeof(MatroskaAudioTrack), \ sizeof(MatroskaAudioTrack), \
sizeof(MatroskaSubtitleTrack))) sizeof(MatroskaSubtitleTrack)))
typedef struct {
char *filename;
char *mime;
EbmlBin bin;
} MatroskaAttachement;
typedef struct { typedef struct {
uint64_t start; uint64_t start;
uint64_t end; uint64_t end;
@ -190,6 +196,7 @@ typedef struct MatroskaDemuxContext {
/* timescale in the file */ /* timescale in the file */
int64_t time_scale; int64_t time_scale;
EbmlList attachments;
EbmlList chapters; EbmlList chapters;
EbmlList index; EbmlList index;
@ -238,6 +245,21 @@ static EbmlSyntax ebml_syntax[] = {
{ 0 } { 0 }
}; };
static EbmlSyntax matroska_attachment[] = {
{ MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachement,filename) },
{ MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachement,mime) },
{ MATROSKA_ID_FILEDATA, EBML_BIN, 0, offsetof(MatroskaAttachement,bin) },
{ MATROSKA_ID_FILEUID, EBML_NONE },
{ EBML_ID_VOID, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_attachments[] = {
{ MATROSKA_ID_ATTACHEDFILE, EBML_NEST, sizeof(MatroskaAttachement), offsetof(MatroskaDemuxContext,attachments), {.n=matroska_attachment} },
{ EBML_ID_VOID, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_chapter_display[] = { static EbmlSyntax matroska_chapter_display[] = {
{ MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter,title) }, { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter,title) },
{ EBML_ID_VOID, EBML_NONE }, { EBML_ID_VOID, EBML_NONE },
@ -1988,110 +2010,37 @@ static int
matroska_parse_attachments(AVFormatContext *s) matroska_parse_attachments(AVFormatContext *s)
{ {
MatroskaDemuxContext *matroska = s->priv_data; MatroskaDemuxContext *matroska = s->priv_data;
int res = 0; EbmlList *attachements_list = &matroska->attachments;
uint32_t id; MatroskaAttachement *attachements;
int i, j, res;
av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\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_ATTACHEDFILE: {
char* name = NULL;
char* mime = NULL;
uint8_t* data = NULL;
int i, data_size = 0;
AVStream *st;
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_FILENAME:
res = ebml_read_utf8 (matroska, &id, &name);
break;
case MATROSKA_ID_FILEMIMETYPE:
res = ebml_read_ascii (matroska, &id, &mime);
break;
case MATROSKA_ID_FILEDATA: res = ebml_parse(matroska, matroska_attachments, matroska, MATROSKA_ID_ATTACHMENTS, 0);
res = ebml_read_binary(matroska, &id, &data, &data_size);
break;
default: attachements = attachements_list->elem;
av_log(matroska->ctx, AV_LOG_INFO, for (j=0; j<attachements_list->nb_elem; j++) {
"Unknown attachedfile ID 0x%x\n", id); if (!(attachements[j].filename && attachements[j].mime &&
case MATROSKA_ID_FILEUID: attachements[j].bin.data && attachements[j].bin.size > 0)) {
case EBML_ID_VOID:
res = ebml_read_skip(matroska);
break;
}
if (matroska->level_up) {
matroska->level_up--;
break;
}
}
if (!(name && mime && data && data_size > 0)) {
av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
break; } else {
} AVStream *st = av_new_stream(s, matroska->num_streams++);
st = av_new_stream(s, matroska->num_streams++);
if (st == NULL) if (st == NULL)
return AVERROR(ENOMEM); break;
st->filename = av_strdup(name); st->filename = av_strdup(attachements[j].filename);
st->codec->codec_id = CODEC_ID_NONE; st->codec->codec_id = CODEC_ID_NONE;
st->codec->codec_type = CODEC_TYPE_ATTACHMENT; st->codec->codec_type = CODEC_TYPE_ATTACHMENT;
st->codec->extradata = av_malloc(data_size); st->codec->extradata = av_malloc(attachements[j].bin.size);
if(st->codec->extradata == NULL) if(st->codec->extradata == NULL)
return AVERROR(ENOMEM); break;
st->codec->extradata_size = data_size; st->codec->extradata_size = attachements[j].bin.size;
memcpy(st->codec->extradata, data, data_size); memcpy(st->codec->extradata, attachements[j].bin.data, attachements[j].bin.size);
for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) { for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) {
if (!strncmp(ff_mkv_mime_tags[i].str, mime, if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime,
strlen(ff_mkv_mime_tags[i].str))) { strlen(ff_mkv_mime_tags[i].str))) {
st->codec->codec_id = ff_mkv_mime_tags[i].id; st->codec->codec_id = ff_mkv_mime_tags[i].id;
break; break;
} }
} }
av_log(matroska->ctx, AV_LOG_DEBUG, "new attachment: %s, %s, size %d \n", name, mime, data_size);
break;
}
default:
av_log(matroska->ctx, AV_LOG_INFO,
"Unknown attachments ID 0x%x\n", id);
/* fall-through */
case EBML_ID_VOID:
res = ebml_read_skip(matroska);
break;
}
if (matroska->level_up) {
matroska->level_up--;
break;
} }
} }
@ -2246,8 +2195,6 @@ matroska_read_header (AVFormatContext *s,
} }
case MATROSKA_ID_ATTACHMENTS: { case MATROSKA_ID_ATTACHMENTS: {
if ((res = ebml_read_master(matroska, &id)) < 0)
break;
res = matroska_parse_attachments(s); res = matroska_parse_attachments(s);
break; break;
} }

Loading…
Cancel
Save