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>
... | ... |
@@ -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 " |