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. Signed-off-by: Anton Khirnov <anton@khirnov.net>tags/n2.7
@@ -89,12 +89,17 @@ const CodecTags ff_mkv_codec_tags[]={ | |||||
{"" , AV_CODEC_ID_NONE} | {"" , AV_CODEC_ID_NONE} | ||||
}; | }; | ||||
const CodecMime ff_mkv_mime_tags[] = { | |||||
{"text/plain" , AV_CODEC_ID_TEXT}, | |||||
const CodecMime ff_mkv_image_mime_tags[] = { | |||||
{"image/gif" , AV_CODEC_ID_GIF}, | {"image/gif" , AV_CODEC_ID_GIF}, | ||||
{"image/jpeg" , AV_CODEC_ID_MJPEG}, | {"image/jpeg" , AV_CODEC_ID_MJPEG}, | ||||
{"image/png" , AV_CODEC_ID_PNG}, | {"image/png" , AV_CODEC_ID_PNG}, | ||||
{"image/tiff" , AV_CODEC_ID_TIFF}, | {"image/tiff" , AV_CODEC_ID_TIFF}, | ||||
{"" , AV_CODEC_ID_NONE} | |||||
}; | |||||
const CodecMime ff_mkv_mime_tags[] = { | |||||
{"text/plain" , AV_CODEC_ID_TEXT}, | |||||
{"application/x-truetype-font", AV_CODEC_ID_TTF}, | {"application/x-truetype-font", AV_CODEC_ID_TTF}, | ||||
{"application/x-font" , AV_CODEC_ID_TTF}, | {"application/x-font" , AV_CODEC_ID_TTF}, | ||||
@@ -254,6 +254,7 @@ typedef struct CodecTags{ | |||||
extern const CodecTags ff_mkv_codec_tags[]; | extern const CodecTags ff_mkv_codec_tags[]; | ||||
extern const CodecMime ff_mkv_mime_tags[]; | extern const CodecMime ff_mkv_mime_tags[]; | ||||
extern const CodecMime ff_mkv_image_mime_tags[]; | |||||
extern const AVMetadataConv ff_mkv_metadata_conv[]; | extern const AVMetadataConv ff_mkv_metadata_conv[]; | ||||
int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); | int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); | ||||
@@ -1887,22 +1887,45 @@ static int matroska_read_header(AVFormatContext *s) | |||||
av_dict_set(&st->metadata, "filename", attachments[j].filename, 0); | av_dict_set(&st->metadata, "filename", attachments[j].filename, 0); | ||||
av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0); | av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0); | ||||
st->codec->codec_id = AV_CODEC_ID_NONE; | st->codec->codec_id = AV_CODEC_ID_NONE; | ||||
st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; | |||||
st->codec->extradata = av_malloc(attachments[j].bin.size); | |||||
if (!st->codec->extradata) | |||||
break; | |||||
st->codec->extradata_size = attachments[j].bin.size; | |||||
memcpy(st->codec->extradata, attachments[j].bin.data, | |||||
attachments[j].bin.size); | |||||
for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { | |||||
if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime, | |||||
strlen(ff_mkv_mime_tags[i].str))) { | |||||
st->codec->codec_id = ff_mkv_mime_tags[i].id; | |||||
for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { | |||||
if (!strncmp(ff_mkv_image_mime_tags[i].str, attachments[j].mime, | |||||
strlen(ff_mkv_image_mime_tags[i].str))) { | |||||
st->codec->codec_id = ff_mkv_image_mime_tags[i].id; | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
attachments[j].stream = st; | attachments[j].stream = st; | ||||
if (st->codec->codec_id != AV_CODEC_ID_NONE) { | |||||
st->disposition |= AV_DISPOSITION_ATTACHED_PIC; | |||||
st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |||||
av_init_packet(&st->attached_pic); | |||||
if ((res = av_new_packet(&st->attached_pic, attachments[j].bin.size)) < 0) | |||||
return res; | |||||
memcpy(st->attached_pic.data, attachments[j].bin.data, attachments[j].bin.size); | |||||
st->attached_pic.stream_index = st->index; | |||||
st->attached_pic.flags |= AV_PKT_FLAG_KEY; | |||||
} else { | |||||
st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; | |||||
st->codec->extradata = av_malloc(attachments[j].bin.size); | |||||
if (!st->codec->extradata) | |||||
break; | |||||
st->codec->extradata_size = attachments[j].bin.size; | |||||
memcpy(st->codec->extradata, attachments[j].bin.data, | |||||
attachments[j].bin.size); | |||||
for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { | |||||
if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime, | |||||
strlen(ff_mkv_mime_tags[i].str))) { | |||||
st->codec->codec_id = ff_mkv_mime_tags[i].id; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -1098,6 +1098,11 @@ static int mkv_write_attachments(AVFormatContext *s) | |||||
mimetype = ff_mkv_mime_tags[i].str; | mimetype = ff_mkv_mime_tags[i].str; | ||||
break; | break; | ||||
} | } | ||||
for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) | |||||
if (ff_mkv_image_mime_tags[i].id == st->codec->codec_id) { | |||||
mimetype = ff_mkv_image_mime_tags[i].str; | |||||
break; | |||||
} | |||||
} | } | ||||
if (!mimetype) { | if (!mimetype) { | ||||
av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and " | av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and " | ||||