aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2008-01-27 15:43:17 +0000
committerAurelien Jacobs <aurel@gnuage.org>2008-01-27 15:43:17 +0000
commitf8d7c9d373a8aeede75454a5d51de958b2321478 (patch)
tree3417638f4bcfd2656c2bc4dad32b30b77bdd5975
parent20963a71565b3d11815d0f9914c16aab873bd58b (diff)
downloadffmpeg-f8d7c9d373a8aeede75454a5d51de958b2321478.tar.gz
Add support for Matroska attachments.
patch by eugeni _dot_ stepanov _at_ gmail.com and myself Originally committed as revision 11635 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--ffmpeg.c2
-rw-r--r--libavcodec/avcodec.h8
-rw-r--r--libavcodec/utils.c4
-rw-r--r--libavformat/avformat.h6
-rw-r--r--libavformat/matroska.c12
-rw-r--r--libavformat/matroska.h14
-rw-r--r--libavformat/matroskadec.c120
-rw-r--r--libavformat/utils.c1
8 files changed, 163 insertions, 4 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index 97526cbceb..a4800685eb 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -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:
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index bcf9fb6467..f8c81783aa 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -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
};
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 4a8cb8a603..4ebc7c324b 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -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;
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index cb6024500f..ddebb7714e 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -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
diff --git a/libavformat/matroska.c b/libavformat/matroska.c
index 382534e9bd..b62511f29f 100644
--- a/libavformat/matroska.c
+++ b/libavformat/matroska.c
@@ -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}
+};
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 43fbb9e9c5..370a8bfd89 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -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 */
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index cc45e9599c..d96b36edf8 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -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. */
diff --git a/libavformat/utils.c b/libavformat/utils.c
index d3e6afef57..ffb2d84818 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -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--) {