# HG changeset patch # User aurel # Date 1201448597 0 # Node ID 910ac68ab3b597bb9a4a6030151a920ed2c3a810 # Parent bc330130bdceb3227c4ec499a1e9ff44839cb4e8 Add support for Matroska attachments. patch by eugeni _dot_ stepanov _at_ gmail.com and myself diff -r bc330130bdce -r 910ac68ab3b5 avformat.h --- a/avformat.h Sat Jan 26 22:57:53 2008 +0000 +++ b/avformat.h Sun Jan 27 15:43:17 2008 +0000 @@ -21,8 +21,8 @@ #ifndef FFMPEG_AVFORMAT_H #define FFMPEG_AVFORMAT_H -#define LIBAVFORMAT_VERSION_INT ((52<<16)+(5<<8)+0) -#define LIBAVFORMAT_VERSION 52.5.0 +#define LIBAVFORMAT_VERSION_INT ((52<<16)+(6<<8)+0) +#define LIBAVFORMAT_VERSION 52.6.0 #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) @@ -347,6 +347,8 @@ #define MAX_REORDER_DELAY 4 int64_t pts_buffer[MAX_REORDER_DELAY+1]; + + char *filename; /**< source filename of the stream */ } AVStream; #define AV_PROGRAM_RUNNING 1 diff -r bc330130bdce -r 910ac68ab3b5 matroska.c --- a/matroska.c Sat Jan 26 22:57:53 2008 +0000 +++ b/matroska.c Sun Jan 27 15:43:17 2008 +0000 @@ -71,3 +71,15 @@ {"" , CODEC_ID_NONE} /* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */ }; + +const CodecMime ff_mkv_mime_tags[] = { + {"text/plain" , CODEC_ID_TEXT}, + {"image/gif" , CODEC_ID_GIF}, + {"image/jpeg" , CODEC_ID_MJPEG}, + {"image/png" , CODEC_ID_PNG}, + {"image/tiff" , CODEC_ID_TIFF}, + {"application/x-truetype-font", CODEC_ID_TTF}, + {"application/x-font" , CODEC_ID_TTF}, + + {"" , CODEC_ID_NONE} +}; diff -r bc330130bdce -r 910ac68ab3b5 matroska.h --- a/matroska.h Sat Jan 26 22:57:53 2008 +0000 +++ b/matroska.h Sun Jan 27 15:43:17 2008 +0000 @@ -55,6 +55,7 @@ #define MATROSKA_ID_CUES 0x1C53BB6B #define MATROSKA_ID_TAGS 0x1254C367 #define MATROSKA_ID_SEEKHEAD 0x114D9B74 +#define MATROSKA_ID_ATTACHMENTS 0x1941A469 #define MATROSKA_ID_CLUSTER 0x1F43B675 /* IDs in the info master */ @@ -138,6 +139,13 @@ #define MATROSKA_ID_BLOCKDURATION 0x9B #define MATROSKA_ID_BLOCKREFERENCE 0xFB +/* IDs in the attachments master */ +#define MATROSKA_ID_ATTACHEDFILE 0x61A7 +#define MATROSKA_ID_FILENAME 0x466E +#define MATROSKA_ID_FILEMIMETYPE 0x4660 +#define MATROSKA_ID_FILEDATA 0x465C +#define MATROSKA_ID_FILEUID 0x46AE + typedef enum { MATROSKA_TRACK_TYPE_VIDEO = 0x1, MATROSKA_TRACK_TYPE_AUDIO = 0x2, @@ -185,6 +193,11 @@ enum CodecID id; }CodecTags; +typedef struct CodecMime{ + char str[32]; + enum CodecID id; +}CodecMime; + #define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC "V_MS/VFW/FOURCC" #define MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM" @@ -192,5 +205,6 @@ #define EBML_MAX_DEPTH 16 extern const CodecTags ff_mkv_codec_tags[]; +extern const CodecMime ff_mkv_mime_tags[]; #endif /* FFMPEG_MATROSKA_H */ diff -r bc330130bdce -r 910ac68ab3b5 matroskadec.c --- a/matroskadec.c Sat Jan 26 22:57:53 2008 +0000 +++ b/matroskadec.c Sun Jan 27 15:43:17 2008 +0000 @@ -1865,6 +1865,119 @@ return res; } +static int +matroska_parse_attachments(AVFormatContext *s) +{ + MatroskaDemuxContext *matroska = s->priv_data; + int res = 0; + uint32_t id; + + 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_read_binary(matroska, &id, &data, &data_size); + break; + + default: + av_log(matroska->ctx, AV_LOG_INFO, + "Unknown attachedfile ID 0x%x\n", id); + 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++); + if (st == NULL) + return AVERROR(ENOMEM); + st->filename = av_strdup(name); + st->codec->codec_id = CODEC_ID_NONE; + st->codec->codec_type = CODEC_TYPE_ATTACHMENT; + st->codec->extradata = av_malloc(data_size); + if(st->codec->extradata == NULL) + return AVERROR(ENOMEM); + st->codec->extradata_size = data_size; + memcpy(st->codec->extradata, data, data_size); + + for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) { + if (!strncmp(ff_mkv_mime_tags[i].str, 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; + } + } + + return res; +} + #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) static int @@ -2007,6 +2120,13 @@ break; } + case MATROSKA_ID_ATTACHMENTS: { + if ((res = ebml_read_master(matroska, &id)) < 0) + break; + res = matroska_parse_attachments(s); + break; + } + case MATROSKA_ID_CLUSTER: { /* Do not read the master - this will be done in the next * call to matroska_read_packet. */ diff -r bc330130bdce -r 910ac68ab3b5 utils.c --- a/utils.c Sat Jan 26 22:57:53 2008 +0000 +++ b/utils.c Sun Jan 27 15:43:17 2008 +0000 @@ -2112,6 +2112,7 @@ av_free(st->index_entries); av_free(st->codec->extradata); av_free(st->codec); + av_free(st->filename); av_free(st); } for(i=s->nb_programs-1; i>=0; i--) {