From b414cb892e5989e7df8c802914a15db76e6b2449 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Tue, 5 Aug 2008 00:40:24 +0000 Subject: [PATCH] matroskadec: use generic parser to parse attachments Originally committed as revision 14560 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/matroskadec.c | 133 ++++++++++++-------------------------- 1 file changed, 40 insertions(+), 93 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 8d2f9c2270..01b856a90e 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -158,6 +158,12 @@ typedef struct MatroskaSubtitleTrack { sizeof(MatroskaAudioTrack), \ sizeof(MatroskaSubtitleTrack))) +typedef struct { + char *filename; + char *mime; + EbmlBin bin; +} MatroskaAttachement; + typedef struct { uint64_t start; uint64_t end; @@ -190,6 +196,7 @@ typedef struct MatroskaDemuxContext { /* timescale in the file */ int64_t time_scale; + EbmlList attachments; EbmlList chapters; EbmlList index; @@ -238,6 +245,21 @@ static EbmlSyntax ebml_syntax[] = { { 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[] = { { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter,title) }, { EBML_ID_VOID, EBML_NONE }, @@ -1988,110 +2010,37 @@ static int matroska_parse_attachments(AVFormatContext *s) { MatroskaDemuxContext *matroska = s->priv_data; - int res = 0; - uint32_t id; + EbmlList *attachements_list = &matroska->attachments; + MatroskaAttachement *attachements; + int i, j, res; - av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\n"); + res = ebml_parse(matroska, matroska_attachments, matroska, MATROSKA_ID_ATTACHMENTS, 0); - 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_read_binary(matroska, &id, &data, &data_size); - break; - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown attachedfile ID 0x%x\n", id); - case MATROSKA_ID_FILEUID: - 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"); - break; - } - - st = av_new_stream(s, matroska->num_streams++); + attachements = attachements_list->elem; + for (j=0; jnb_elem; j++) { + if (!(attachements[j].filename && attachements[j].mime && + attachements[j].bin.data && attachements[j].bin.size > 0)) { + av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); + } else { + AVStream *st = av_new_stream(s, matroska->num_streams++); if (st == NULL) - return AVERROR(ENOMEM); - st->filename = av_strdup(name); + break; + st->filename = av_strdup(attachements[j].filename); st->codec->codec_id = CODEC_ID_NONE; 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) - return AVERROR(ENOMEM); - st->codec->extradata_size = data_size; - memcpy(st->codec->extradata, data, data_size); + break; + st->codec->extradata_size = attachements[j].bin.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++) { - 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))) { st->codec->codec_id = ff_mkv_mime_tags[i].id; 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: { - if ((res = ebml_read_master(matroska, &id)) < 0) - break; res = matroska_parse_attachments(s); break; }