From c4d37cd9ef6e374bb888f6273259b10fac5bd909 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 3 Apr 2015 16:11:53 +0200 Subject: [PATCH] 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. Signed-off-by: Anton Khirnov --- libavformat/matroska.c | 9 ++++++-- libavformat/matroska.h | 1 + libavformat/matroskadec.c | 47 +++++++++++++++++++++++++++++---------- libavformat/matroskaenc.c | 5 +++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/libavformat/matroska.c b/libavformat/matroska.c index 47fdea6369..eca1e41f75 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -89,12 +89,17 @@ const CodecTags ff_mkv_codec_tags[]={ {"" , 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/jpeg" , AV_CODEC_ID_MJPEG}, {"image/png" , AV_CODEC_ID_PNG}, {"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-font" , AV_CODEC_ID_TTF}, diff --git a/libavformat/matroska.h b/libavformat/matroska.h index d8f4f8ebec..a7a22a96af 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -254,6 +254,7 @@ typedef struct CodecTags{ extern const CodecTags ff_mkv_codec_tags[]; extern const CodecMime ff_mkv_mime_tags[]; +extern const CodecMime ff_mkv_image_mime_tags[]; extern const AVMetadataConv ff_mkv_metadata_conv[]; int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index d352c8bd2f..7dac7beb99 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -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, "mimetype", attachments[j].mime, 0); 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; } } + 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; + } + } + } } } diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 49e5bf3067..91c4459dad 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1098,6 +1098,11 @@ static int mkv_write_attachments(AVFormatContext *s) mimetype = ff_mkv_mime_tags[i].str; 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) { av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and "