[FFmpeg-devel,2/2] avformat/matroskaenc: Write attached_pic as attachment

Submitted by Oliver Collyer via ffmpeg-devel on April 6, 2019, 10:02 a.m.

Details

Message ID 20190406100249.4540-3-andreas.rheinhardt@googlemail.com
State New
Headers show

Commit Message

Oliver Collyer via ffmpeg-devel April 6, 2019, 10:02 a.m.
This commit changes the way video streams with disposition
AV_DISPOSITION_ATTACHED_PIC and that actually contain an attached_pic
are handled: From now on, they will be written as attachment, not as
a Matroska Track.

The restriction to tracks that actually contain an attached_pic is
important. E.g. simply setting the disposition via FFmpeg does not
populate the attached_pic field. Such tracks are treated as video tracks
just as now.

If the stream originated from a non-Matroska container, then the user
must likely also populate the filename metadata key for this stream.

This fixes tickets #2270 and #4591 and partially fixes #7717.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com>
---
 libavformat/matroskaenc.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index b9f99c4463..8730062f81 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -179,6 +179,12 @@  typedef struct MatroskaMuxContext {
 /** Seek preroll value for opus */
 #define OPUS_SEEK_PREROLL 80000000
 
+/** To unify handling of attachments and attached pics */
+#define DISPOSITION_ATTACHED_PIC(st) ((st)->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && \
+                                      (st)->disposition & AV_DISPOSITION_ATTACHED_PIC)
+#define IS_ATTACHMENT(st) ((st)->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT || \
+                           DISPOSITION_ATTACHED_PIC(st) && (st)->attached_pic.data)
+
 static int ebml_id_size(unsigned int id)
 {
     return (av_log2(id + 1) - 1) / 7 + 1;
@@ -1191,10 +1197,12 @@  static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
     int j, ret;
     AVDictionaryEntry *tag;
 
-    if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
+    if (IS_ATTACHMENT(st)) {
         mkv->have_attachments = 1;
         return 0;
-    }
+    } else if (DISPOSITION_ATTACHED_PIC(st) && !st->attached_pic.data)
+        av_log(s, AV_LOG_ERROR, "Stream with attached pic disposition doesn't "
+                           "contain an attached pic. Treating as video track\n");
 
     if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
         if (!bit_depth && par->codec_id != AV_CODEC_ID_ADPCM_G726) {
@@ -1660,7 +1668,7 @@  static int mkv_write_tags(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
 
-        if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
+        if (IS_ATTACHMENT(st))
             continue;
 
         if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID))
@@ -1677,7 +1685,7 @@  static int mkv_write_tags(AVFormatContext *s)
             ebml_master tag_target;
             ebml_master tag;
 
-            if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
+            if (IS_ATTACHMENT(st))
                 continue;
 
             mkv_write_tag_targets(s, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &mkv->tags, &tag_target);
@@ -1762,7 +1770,7 @@  static int mkv_write_attachments(AVFormatContext *s)
         const char *mimetype = NULL;
         uint32_t fileuid;
 
-        if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
+        if (!IS_ATTACHMENT(st))
             continue;
 
         attachment = av_realloc_array(attachment, mkv->attachments->num_entries + 1, sizeof(mkv_attachment));
@@ -1817,7 +1825,10 @@  static int mkv_write_attachments(AVFormatContext *s)
                fileuid, mkv->attachments->num_entries);
 
         put_ebml_string(dyn_cp, MATROSKA_ID_FILEMIMETYPE, mimetype);
-        put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size);
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
+            put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size);
+        else
+            put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->attached_pic.data, st->attached_pic.size);
         put_ebml_uint(dyn_cp, MATROSKA_ID_FILEUID, fileuid);
         end_ebml_master(dyn_cp, attached_file);
 
@@ -2557,6 +2568,10 @@  static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt)
             avio_flush(s->pb);
         }
         return 1;
+    } else {
+        AVStream *st = s->streams[pkt->stream_index];
+        if (DISPOSITION_ATTACHED_PIC(st) && st->attached_pic.data)
+            return 0;
     }
     return mkv_write_packet(s, pkt);
 }