Browse code

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

Evgeniy Stepanov authored on 2008/01/28 00:43:17
Showing 8 changed files
... ...
@@ -2776,6 +2776,7 @@ static void opt_input_file(const char *filename)
2776 2776
             if(subtitle_disable)
2777 2777
                 ic->streams[i]->discard = AVDISCARD_ALL;
2778 2778
             break;
2779
+        case CODEC_TYPE_ATTACHMENT:
2779 2780
         case CODEC_TYPE_UNKNOWN:
2780 2781
             break;
2781 2782
         default:
... ...
@@ -2825,6 +2826,7 @@ static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
2825 2825
                 has_subtitle = 1;
2826 2826
                 break;
2827 2827
             case CODEC_TYPE_DATA:
2828
+            case CODEC_TYPE_ATTACHMENT:
2828 2829
             case CODEC_TYPE_UNKNOWN:
2829 2830
                 break;
2830 2831
             default:
... ...
@@ -33,8 +33,8 @@
33 33
 #define AV_STRINGIFY(s)         AV_TOSTRING(s)
34 34
 #define AV_TOSTRING(s) #s
35 35
 
36
-#define LIBAVCODEC_VERSION_INT  ((51<<16)+(49<<8)+0)
37
-#define LIBAVCODEC_VERSION      51.49.0
36
+#define LIBAVCODEC_VERSION_INT  ((51<<16)+(50<<8)+0)
37
+#define LIBAVCODEC_VERSION      51.50.0
38 38
 #define LIBAVCODEC_BUILD        LIBAVCODEC_VERSION_INT
39 39
 
40 40
 #define LIBAVCODEC_IDENT        "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
... ...
@@ -284,6 +284,9 @@ enum CodecID {
284 284
     CODEC_ID_XSUB,
285 285
     CODEC_ID_SSA,
286 286
 
287
+    /* other specific kind of codecs (generaly used for attachments) */
288
+    CODEC_ID_TTF= 0x18000,
289
+
287 290
     CODEC_ID_MPEG2TS= 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS
288 291
                                 * stream (only used by libavformat) */
289 292
 };
... ...
@@ -300,6 +303,7 @@ enum CodecType {
300 300
     CODEC_TYPE_AUDIO,
301 301
     CODEC_TYPE_DATA,
302 302
     CODEC_TYPE_SUBTITLE,
303
+    CODEC_TYPE_ATTACHMENT,
303 304
     CODEC_TYPE_NB
304 305
 };
305 306
 
... ...
@@ -1219,6 +1219,10 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
1219 1219
         snprintf(buf, buf_size, "Subtitle: %s", codec_name);
1220 1220
         bitrate = enc->bit_rate;
1221 1221
         break;
1222
+    case CODEC_TYPE_ATTACHMENT:
1223
+        snprintf(buf, buf_size, "Attachment: %s", codec_name);
1224
+        bitrate = enc->bit_rate;
1225
+        break;
1222 1226
     default:
1223 1227
         snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type);
1224 1228
         return;
... ...
@@ -21,8 +21,8 @@
21 21
 #ifndef FFMPEG_AVFORMAT_H
22 22
 #define FFMPEG_AVFORMAT_H
23 23
 
24
-#define LIBAVFORMAT_VERSION_INT ((52<<16)+(5<<8)+0)
25
-#define LIBAVFORMAT_VERSION     52.5.0
24
+#define LIBAVFORMAT_VERSION_INT ((52<<16)+(6<<8)+0)
25
+#define LIBAVFORMAT_VERSION     52.6.0
26 26
 #define LIBAVFORMAT_BUILD       LIBAVFORMAT_VERSION_INT
27 27
 
28 28
 #define LIBAVFORMAT_IDENT       "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
... ...
@@ -347,6 +347,8 @@ typedef struct AVStream {
347 347
 
348 348
 #define MAX_REORDER_DELAY 4
349 349
     int64_t pts_buffer[MAX_REORDER_DELAY+1];
350
+
351
+    char *filename; /**< source filename of the stream */
350 352
 } AVStream;
351 353
 
352 354
 #define AV_PROGRAM_RUNNING 1
... ...
@@ -71,3 +71,15 @@ const CodecTags ff_mkv_codec_tags[]={
71 71
     {""                 , CODEC_ID_NONE}
72 72
 /* TODO: AC3-9/10 (?), Real, Musepack, Quicktime */
73 73
 };
74
+
75
+const CodecMime ff_mkv_mime_tags[] = {
76
+    {"text/plain"                 , CODEC_ID_TEXT},
77
+    {"image/gif"                  , CODEC_ID_GIF},
78
+    {"image/jpeg"                 , CODEC_ID_MJPEG},
79
+    {"image/png"                  , CODEC_ID_PNG},
80
+    {"image/tiff"                 , CODEC_ID_TIFF},
81
+    {"application/x-truetype-font", CODEC_ID_TTF},
82
+    {"application/x-font"         , CODEC_ID_TTF},
83
+
84
+    {""                           , CODEC_ID_NONE}
85
+};
... ...
@@ -55,6 +55,7 @@
55 55
 #define MATROSKA_ID_CUES       0x1C53BB6B
56 56
 #define MATROSKA_ID_TAGS       0x1254C367
57 57
 #define MATROSKA_ID_SEEKHEAD   0x114D9B74
58
+#define MATROSKA_ID_ATTACHMENTS 0x1941A469
58 59
 #define MATROSKA_ID_CLUSTER    0x1F43B675
59 60
 
60 61
 /* IDs in the info master */
... ...
@@ -138,6 +139,13 @@
138 138
 #define MATROSKA_ID_BLOCKDURATION 0x9B
139 139
 #define MATROSKA_ID_BLOCKREFERENCE 0xFB
140 140
 
141
+/* IDs in the attachments master */
142
+#define MATROSKA_ID_ATTACHEDFILE        0x61A7
143
+#define MATROSKA_ID_FILENAME            0x466E
144
+#define MATROSKA_ID_FILEMIMETYPE        0x4660
145
+#define MATROSKA_ID_FILEDATA            0x465C
146
+#define MATROSKA_ID_FILEUID             0x46AE
147
+
141 148
 typedef enum {
142 149
   MATROSKA_TRACK_TYPE_VIDEO    = 0x1,
143 150
   MATROSKA_TRACK_TYPE_AUDIO    = 0x2,
... ...
@@ -185,6 +193,11 @@ typedef struct CodecTags{
185 185
     enum CodecID id;
186 186
 }CodecTags;
187 187
 
188
+typedef struct CodecMime{
189
+    char str[32];
190
+    enum CodecID id;
191
+}CodecMime;
192
+
188 193
 #define MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC   "V_MS/VFW/FOURCC"
189 194
 #define MATROSKA_CODEC_ID_AUDIO_ACM          "A_MS/ACM"
190 195
 
... ...
@@ -192,5 +205,6 @@ typedef struct CodecTags{
192 192
 #define EBML_MAX_DEPTH 16
193 193
 
194 194
 extern const CodecTags ff_mkv_codec_tags[];
195
+extern const CodecMime ff_mkv_mime_tags[];
195 196
 
196 197
 #endif /* FFMPEG_MATROSKA_H */
... ...
@@ -1865,6 +1865,119 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
1865 1865
     return res;
1866 1866
 }
1867 1867
 
1868
+static int
1869
+matroska_parse_attachments(AVFormatContext *s)
1870
+{
1871
+    MatroskaDemuxContext *matroska = s->priv_data;
1872
+    int res = 0;
1873
+    uint32_t id;
1874
+
1875
+    av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\n");
1876
+
1877
+    while (res == 0) {
1878
+        if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
1879
+            res = AVERROR(EIO);
1880
+            break;
1881
+        } else if (matroska->level_up) {
1882
+            matroska->level_up--;
1883
+            break;
1884
+        }
1885
+
1886
+        switch (id) {
1887
+        case MATROSKA_ID_ATTACHEDFILE: {
1888
+            char* name = NULL;
1889
+            char* mime = NULL;
1890
+            uint8_t* data = NULL;
1891
+            int i, data_size = 0;
1892
+            AVStream *st;
1893
+
1894
+            if ((res = ebml_read_master(matroska, &id)) < 0)
1895
+                break;
1896
+
1897
+            while (res == 0) {
1898
+                if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
1899
+                    res = AVERROR(EIO);
1900
+                    break;
1901
+                } else if (matroska->level_up) {
1902
+                    matroska->level_up--;
1903
+                    break;
1904
+                }
1905
+
1906
+                switch (id) {
1907
+                case MATROSKA_ID_FILENAME:
1908
+                    res = ebml_read_utf8 (matroska, &id, &name);
1909
+                    break;
1910
+
1911
+                case MATROSKA_ID_FILEMIMETYPE:
1912
+                    res = ebml_read_ascii (matroska, &id, &mime);
1913
+                    break;
1914
+
1915
+                case MATROSKA_ID_FILEDATA:
1916
+                    res = ebml_read_binary(matroska, &id, &data, &data_size);
1917
+                    break;
1918
+
1919
+                default:
1920
+                    av_log(matroska->ctx, AV_LOG_INFO,
1921
+                           "Unknown attachedfile ID 0x%x\n", id);
1922
+                case EBML_ID_VOID:
1923
+                    res = ebml_read_skip(matroska);
1924
+                    break;
1925
+                }
1926
+
1927
+                if (matroska->level_up) {
1928
+                    matroska->level_up--;
1929
+                    break;
1930
+                }
1931
+            }
1932
+
1933
+            if (!(name && mime && data && data_size > 0)) {
1934
+                av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
1935
+                break;
1936
+            }
1937
+
1938
+            st = av_new_stream(s, matroska->num_streams++);
1939
+            if (st == NULL)
1940
+                return AVERROR(ENOMEM);
1941
+            st->filename = av_strdup(name);
1942
+            st->codec->codec_id = CODEC_ID_NONE;
1943
+            st->codec->codec_type = CODEC_TYPE_ATTACHMENT;
1944
+            st->codec->extradata = av_malloc(data_size);
1945
+            if(st->codec->extradata == NULL)
1946
+                return AVERROR(ENOMEM);
1947
+            st->codec->extradata_size = data_size;
1948
+            memcpy(st->codec->extradata, data, data_size);
1949
+
1950
+            for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) {
1951
+                if (!strncmp(ff_mkv_mime_tags[i].str, mime,
1952
+                             strlen(ff_mkv_mime_tags[i].str))) {
1953
+                    st->codec->codec_id = ff_mkv_mime_tags[i].id;
1954
+                    break;
1955
+                }
1956
+            }
1957
+
1958
+            av_log(matroska->ctx, AV_LOG_DEBUG, "new attachment: %s, %s, size %d \n", name, mime, data_size);
1959
+            break;
1960
+        }
1961
+
1962
+        default:
1963
+            av_log(matroska->ctx, AV_LOG_INFO,
1964
+                   "Unknown attachments ID 0x%x\n", id);
1965
+            /* fall-through */
1966
+
1967
+        case EBML_ID_VOID:
1968
+            res = ebml_read_skip(matroska);
1969
+            break;
1970
+        }
1971
+
1972
+        if (matroska->level_up) {
1973
+            matroska->level_up--;
1974
+            break;
1975
+        }
1976
+    }
1977
+
1978
+    return res;
1979
+}
1980
+
1868 1981
 #define ARRAY_SIZE(x)  (sizeof(x)/sizeof(*x))
1869 1982
 
1870 1983
 static int
... ...
@@ -2007,6 +2120,13 @@ matroska_read_header (AVFormatContext    *s,
2007 2007
                 break;
2008 2008
             }
2009 2009
 
2010
+            case MATROSKA_ID_ATTACHMENTS: {
2011
+                if ((res = ebml_read_master(matroska, &id)) < 0)
2012
+                    break;
2013
+                res = matroska_parse_attachments(s);
2014
+                break;
2015
+            }
2016
+
2010 2017
             case MATROSKA_ID_CLUSTER: {
2011 2018
                 /* Do not read the master - this will be done in the next
2012 2019
                  * call to matroska_read_packet. */
... ...
@@ -2112,6 +2112,7 @@ void av_close_input_stream(AVFormatContext *s)
2112 2112
         av_free(st->index_entries);
2113 2113
         av_free(st->codec->extradata);
2114 2114
         av_free(st->codec);
2115
+        av_free(st->filename);
2115 2116
         av_free(st);
2116 2117
     }
2117 2118
     for(i=s->nb_programs-1; i>=0; i--) {