patch by eugeni _dot_ stepanov _at_ gmail.com and myself Originally committed as revision 11635 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -2776,6 +2776,7 @@ static void opt_input_file(const char *filename) | |||
| if(subtitle_disable) | |||
| ic->streams[i]->discard = AVDISCARD_ALL; | |||
| break; | |||
| case CODEC_TYPE_ATTACHMENT: | |||
| case CODEC_TYPE_UNKNOWN: | |||
| break; | |||
| default: | |||
| @@ -2825,6 +2826,7 @@ static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr, | |||
| has_subtitle = 1; | |||
| break; | |||
| case CODEC_TYPE_DATA: | |||
| case CODEC_TYPE_ATTACHMENT: | |||
| case CODEC_TYPE_UNKNOWN: | |||
| break; | |||
| default: | |||
| @@ -33,8 +33,8 @@ | |||
| #define AV_STRINGIFY(s) AV_TOSTRING(s) | |||
| #define AV_TOSTRING(s) #s | |||
| #define LIBAVCODEC_VERSION_INT ((51<<16)+(49<<8)+0) | |||
| #define LIBAVCODEC_VERSION 51.49.0 | |||
| #define LIBAVCODEC_VERSION_INT ((51<<16)+(50<<8)+0) | |||
| #define LIBAVCODEC_VERSION 51.50.0 | |||
| #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT | |||
| #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) | |||
| @@ -284,6 +284,9 @@ enum CodecID { | |||
| CODEC_ID_XSUB, | |||
| CODEC_ID_SSA, | |||
| /* other specific kind of codecs (generaly used for attachments) */ | |||
| CODEC_ID_TTF= 0x18000, | |||
| CODEC_ID_MPEG2TS= 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS | |||
| * stream (only used by libavformat) */ | |||
| }; | |||
| @@ -300,6 +303,7 @@ enum CodecType { | |||
| CODEC_TYPE_AUDIO, | |||
| CODEC_TYPE_DATA, | |||
| CODEC_TYPE_SUBTITLE, | |||
| CODEC_TYPE_ATTACHMENT, | |||
| CODEC_TYPE_NB | |||
| }; | |||
| @@ -1219,6 +1219,10 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) | |||
| snprintf(buf, buf_size, "Subtitle: %s", codec_name); | |||
| bitrate = enc->bit_rate; | |||
| break; | |||
| case CODEC_TYPE_ATTACHMENT: | |||
| snprintf(buf, buf_size, "Attachment: %s", codec_name); | |||
| bitrate = enc->bit_rate; | |||
| break; | |||
| default: | |||
| snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type); | |||
| return; | |||
| @@ -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 @@ typedef struct AVStream { | |||
| #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 | |||
| @@ -71,3 +71,15 @@ const CodecTags ff_mkv_codec_tags[]={ | |||
| {"" , 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} | |||
| }; | |||
| @@ -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 @@ typedef struct CodecTags{ | |||
| 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 @@ typedef struct CodecTags{ | |||
| #define EBML_MAX_DEPTH 16 | |||
| extern const CodecTags ff_mkv_codec_tags[]; | |||
| extern const CodecMime ff_mkv_mime_tags[]; | |||
| #endif /* FFMPEG_MATROSKA_H */ | |||
| @@ -1865,6 +1865,119 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) | |||
| 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 @@ matroska_read_header (AVFormatContext *s, | |||
| 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. */ | |||
| @@ -2112,6 +2112,7 @@ void av_close_input_stream(AVFormatContext *s) | |||
| 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--) { | |||