Browse code

matroskadec: export cover art correctly

Generally, libavformat exports cover art pictures as video streams with
1 packet and AV_DISPOSITION_ATTACHED_PIC set. Only matroskadec exported
it as attachment with codec_id set to AV_CODEC_ID_MJPEG.

Obviously, this should be consistent, so change the Matroska demuxer to
export a AV_DISPOSITION_ATTACHED_PIC pseudo video stream.

Matroska muxing is probably incorrect too. I know that it can create
broken files with an audio track and just 1 video frame when e.g.
remuxing mp3 with APIC to mkv. But for now this commit does not change
anything about muxing, and also continues to write attachments with
AV_CODEC_ID_MJPEG should the muxer application have special knowledge
that the Matroska is broken in this way.

Fixes trac #4423.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

wm4 authored on 2015/04/03 23:11:53
Showing 4 changed files
... ...
@@ -99,12 +99,17 @@ const CodecTags ff_mkv_codec_tags[]={
99 99
     {""                 , AV_CODEC_ID_NONE}
100 100
 };
101 101
 
102
-const CodecMime ff_mkv_mime_tags[] = {
103
-    {"text/plain"                 , AV_CODEC_ID_TEXT},
102
+const CodecMime ff_mkv_image_mime_tags[] = {
104 103
     {"image/gif"                  , AV_CODEC_ID_GIF},
105 104
     {"image/jpeg"                 , AV_CODEC_ID_MJPEG},
106 105
     {"image/png"                  , AV_CODEC_ID_PNG},
107 106
     {"image/tiff"                 , AV_CODEC_ID_TIFF},
107
+
108
+    {""                           , AV_CODEC_ID_NONE}
109
+};
110
+
111
+const CodecMime ff_mkv_mime_tags[] = {
112
+    {"text/plain"                 , AV_CODEC_ID_TEXT},
108 113
     {"application/x-truetype-font", AV_CODEC_ID_TTF},
109 114
     {"application/x-font"         , AV_CODEC_ID_TTF},
110 115
     {"application/vnd.ms-opentype", AV_CODEC_ID_OTF},
... ...
@@ -280,6 +280,7 @@ typedef struct CodecTags{
280 280
 
281 281
 extern const CodecTags ff_mkv_codec_tags[];
282 282
 extern const CodecMime ff_mkv_mime_tags[];
283
+extern const CodecMime ff_mkv_image_mime_tags[];
283 284
 extern const AVMetadataConv ff_mkv_metadata_conv[];
284 285
 extern const char * const ff_matroska_video_stereo_mode[MATROSKA_VIDEO_STEREOMODE_TYPE_NB];
285 286
 extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT];
... ...
@@ -2142,20 +2142,41 @@ static int matroska_read_header(AVFormatContext *s)
2142 2142
             av_dict_set(&st->metadata, "filename", attachments[j].filename, 0);
2143 2143
             av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0);
2144 2144
             st->codec->codec_id   = AV_CODEC_ID_NONE;
2145
-            st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
2146
-            if (ff_alloc_extradata(st->codec, attachments[j].bin.size))
2147
-                break;
2148
-            memcpy(st->codec->extradata, attachments[j].bin.data,
2149
-                   attachments[j].bin.size);
2150 2145
 
2151
-            for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
2152
-                if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime,
2153
-                             strlen(ff_mkv_mime_tags[i].str))) {
2154
-                    st->codec->codec_id = ff_mkv_mime_tags[i].id;
2146
+            for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
2147
+                if (!strncmp(ff_mkv_image_mime_tags[i].str, attachments[j].mime,
2148
+                             strlen(ff_mkv_image_mime_tags[i].str))) {
2149
+                    st->codec->codec_id = ff_mkv_image_mime_tags[i].id;
2150
+                    break;
2151
+                }
2152
+            }
2153
+
2154
+            if (st->codec->codec_id != AV_CODEC_ID_NONE) {
2155
+                st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;
2156
+                st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
2157
+
2158
+                av_init_packet(&st->attached_pic);
2159
+                if ((res = av_new_packet(&st->attached_pic, attachments[j].bin.size)) < 0)
2160
+                    return res;
2161
+                memcpy(st->attached_pic.data, attachments[j].bin.data, attachments[j].bin.size);
2162
+                st->attached_pic.stream_index = st->index;
2163
+                st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
2164
+            } else {
2165
+                st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
2166
+                if (ff_alloc_extradata(st->codec, attachments[j].bin.size))
2155 2167
                     break;
2168
+                memcpy(st->codec->extradata, attachments[j].bin.data,
2169
+                    attachments[j].bin.size);
2170
+
2171
+                for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
2172
+                    if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime,
2173
+                                strlen(ff_mkv_mime_tags[i].str))) {
2174
+                        st->codec->codec_id = ff_mkv_mime_tags[i].id;
2175
+                        break;
2176
+                    }
2156 2177
                 }
2178
+                attachments[j].stream = st;
2157 2179
             }
2158
-            attachments[j].stream = st;
2159 2180
         }
2160 2181
     }
2161 2182
 
... ...
@@ -1270,6 +1270,11 @@ static int mkv_write_attachments(AVFormatContext *s)
1270 1270
                     mimetype = ff_mkv_mime_tags[i].str;
1271 1271
                     break;
1272 1272
                 }
1273
+            for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++)
1274
+                if (ff_mkv_image_mime_tags[i].id == st->codec->codec_id) {
1275
+                    mimetype = ff_mkv_image_mime_tags[i].str;
1276
+                    break;
1277
+                }
1273 1278
         }
1274 1279
         if (!mimetype) {
1275 1280
             av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and "