[FFmpeg-devel] [PATCH 2/3 v2] avformat: add a flag to enable exporting attached pictures

James Almer jamrial at gmail.com
Fri Apr 2 04:32:40 EEST 2021


Signed-off-by: James Almer <jamrial at gmail.com>
---
Fixed some silly bugs in apetag, matroska, mov, and added a missing check in
asf.

 libavformat/apetag.c         |  8 +++++---
 libavformat/asf.c            |  6 ++++--
 libavformat/avformat.h       |  1 +
 libavformat/dsfdec.c         |  3 ++-
 libavformat/flacdec.c        |  4 +++-
 libavformat/hls.c            | 10 ++++++----
 libavformat/matroskadec.c    | 35 +++++++++++++++++++++--------------
 libavformat/mov.c            |  5 +++++
 libavformat/oggparsevorbis.c |  3 ++-
 libavformat/options_table.h  |  3 ++-
 libavformat/utils.c          |  3 ++-
 libavformat/wavdec.c         |  3 ++-
 libavformat/wtvdec.c         |  3 ++-
 13 files changed, 57 insertions(+), 30 deletions(-)

diff --git a/libavformat/apetag.c b/libavformat/apetag.c
index 5a8144a27c..d82f14c773 100644
--- a/libavformat/apetag.c
+++ b/libavformat/apetag.c
@@ -74,7 +74,8 @@ static int ape_tag_read_field(AVFormatContext *s)
         }
         size -= ret;
 
-        if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) {
+        if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE &&
+            s->flags & AVFMT_FLAG_ATTACHED_PIC) {
             ret = ff_add_attached_pic(s, NULL, s->pb, NULL, size);
             if (ret < 0) {
                 av_log(s, AV_LOG_ERROR, "Error reading cover art.\n");
@@ -82,7 +83,7 @@ static int ape_tag_read_field(AVFormatContext *s)
             }
             st = s->streams[s->nb_streams - 1];
             st->codecpar->codec_id   = id;
-        } else {
+        } else if (id == AV_CODEC_ID_NONE) {
             st = avformat_new_stream(s, NULL);
             if (!st)
                 return AVERROR(ENOMEM);
@@ -90,7 +91,8 @@ static int ape_tag_read_field(AVFormatContext *s)
                 return ret;
             st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
         }
-        av_dict_set(&st->metadata, key, filename, 0);
+        if (st)
+            av_dict_set(&st->metadata, key, filename, 0);
     } else {
         value = av_malloc(size+1);
         if (!value)
diff --git a/libavformat/asf.c b/libavformat/asf.c
index cef0f9f646..eed756b0a1 100644
--- a/libavformat/asf.c
+++ b/libavformat/asf.c
@@ -259,7 +259,8 @@ static int get_id3_tag(AVFormatContext *s, int len)
 
     ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len);
     if (id3v2_extra_meta) {
-        ff_id3v2_parse_apic(s, id3v2_extra_meta);
+        if (s->flags & AVFMT_FLAG_ATTACHED_PIC)
+            ff_id3v2_parse_apic(s, id3v2_extra_meta);
         ff_id3v2_parse_chapters(s, id3v2_extra_meta);
         ff_id3v2_free_extra_meta(&id3v2_extra_meta);
     }
@@ -269,7 +270,8 @@ static int get_id3_tag(AVFormatContext *s, int len)
 int ff_asf_handle_byte_array(AVFormatContext *s, const char *name,
                              int val_len)
 {
-    if (!strcmp(name, "WM/Picture")) // handle cover art
+    if (!strcmp(name, "WM/Picture") &&
+        (s->flags & AVFMT_FLAG_ATTACHED_PIC)) // handle cover art
         return asf_read_picture(s, val_len);
     else if (!strcmp(name, "ID3")) // handle ID3 tag
         return get_id3_tag(s, val_len);
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 765bc3b6f5..11e993eacb 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1392,6 +1392,7 @@ typedef struct AVFormatContext {
 #define AVFMT_FLAG_FAST_SEEK   0x80000 ///< Enable fast, but inaccurate seeks for some formats
 #define AVFMT_FLAG_SHORTEST   0x100000 ///< Stop muxing when the shortest stream stops.
 #define AVFMT_FLAG_AUTO_BSF   0x200000 ///< Add bitstream filters as requested by the muxer
+#define AVFMT_FLAG_ATTACHED_PIC 0x400000 ///< Export attached pictures, like cover art
 
     /**
      * Maximum size of the data read from input for determining
diff --git a/libavformat/dsfdec.c b/libavformat/dsfdec.c
index 1df163e114..aba7f5714b 100644
--- a/libavformat/dsfdec.c
+++ b/libavformat/dsfdec.c
@@ -56,7 +56,8 @@ static void read_id3(AVFormatContext *s, uint64_t id3pos)
 
     ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0);
     if (id3v2_extra_meta) {
-        ff_id3v2_parse_apic(s, id3v2_extra_meta);
+        if (s->flags & AVFMT_FLAG_ATTACHED_PIC)
+            ff_id3v2_parse_apic(s, id3v2_extra_meta);
         ff_id3v2_parse_chapters(s, id3v2_extra_meta);
     }
     ff_id3v2_free_extra_meta(&id3v2_extra_meta);
diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c
index f7b21986dc..d85dad43b7 100644
--- a/libavformat/flacdec.c
+++ b/libavformat/flacdec.c
@@ -146,7 +146,9 @@ static int flac_read_header(AVFormatContext *s)
             }
             av_freep(&buffer);
         } else if (metadata_type == FLAC_METADATA_TYPE_PICTURE) {
-            ret = ff_flac_parse_picture(s, buffer, metadata_size, 1);
+            ret = 0;
+            if (s->flags & AVFMT_FLAG_ATTACHED_PIC)
+                ret = ff_flac_parse_picture(s, buffer, metadata_size, 1);
             av_freep(&buffer);
             if (ret < 0) {
                 av_log(s, AV_LOG_ERROR, "Error parsing attached picture.\n");
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 597bea7f25..90e2a2b43a 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -1104,9 +1104,10 @@ static void handle_id3(AVIOContext *pb, struct playlist *pls)
         pls->id3_found = 1;
 
         /* get picture attachment and set text metadata */
-        if (pls->ctx->nb_streams)
-            ff_id3v2_parse_apic(pls->ctx, extra_meta);
-        else
+        if (pls->ctx->nb_streams) {
+            if (pls->ctx->flags & AVFMT_FLAG_ATTACHED_PIC)
+                ff_id3v2_parse_apic(pls->ctx, extra_meta);
+        } else
             /* demuxer not yet opened, defer picture attachment */
             pls->id3_deferred_extra = extra_meta;
 
@@ -2018,7 +2019,8 @@ static int hls_read_header(AVFormatContext *s)
             goto fail;
 
         if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) {
-            ff_id3v2_parse_apic(pls->ctx, pls->id3_deferred_extra);
+            if (pls->ctx->flags & AVFMT_FLAG_ATTACHED_PIC)
+                ff_id3v2_parse_apic(pls->ctx, pls->id3_deferred_extra);
             avformat_queue_attached_pictures(pls->ctx);
             ff_id3v2_parse_priv(pls->ctx, pls->id3_deferred_extra);
             ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index e8c76f9cfb..d7fe45519b 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2988,29 +2988,26 @@ static int matroska_read_header(AVFormatContext *s)
               attachments[j].bin.data && attachments[j].bin.size > 0)) {
             av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
         } else {
-            AVStream *st = avformat_new_stream(s, NULL);
-            if (!st)
-                break;
-            av_dict_set(&st->metadata, "filename", attachments[j].filename, 0);
-            av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0);
-            if (attachments[j].description)
-                av_dict_set(&st->metadata, "title", attachments[j].description, 0);
-            st->codecpar->codec_id   = AV_CODEC_ID_NONE;
+            AVStream *st = NULL;
+            enum AVCodecID codec_id = AV_CODEC_ID_NONE;
 
             for (i = 0; mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
                 if (av_strstart(attachments[j].mime, mkv_image_mime_tags[i].str, NULL)) {
-                    st->codecpar->codec_id = mkv_image_mime_tags[i].id;
+                    codec_id = mkv_image_mime_tags[i].id;
                     break;
                 }
             }
 
-            attachments[j].stream = st;
-
-            if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
-                res = ff_add_attached_pic(s, st, NULL, &attachments[j].bin.buf, 0);
+            if (codec_id != AV_CODEC_ID_NONE && s->flags & AVFMT_FLAG_ATTACHED_PIC) {
+                res = ff_add_attached_pic(s, NULL, NULL, &attachments[j].bin.buf, 0);
                 if (res < 0)
                     goto fail;
-            } else {
+                st = s->streams[s->nb_streams - 1];
+                st->codecpar->codec_id   = codec_id;
+            } else if (codec_id == AV_CODEC_ID_NONE) {
+                st = avformat_new_stream(s, NULL);
+                if (!st)
+                    break;
                 st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
                 if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size))
                     break;
@@ -3024,6 +3021,16 @@ static int matroska_read_header(AVFormatContext *s)
                     }
                 }
             }
+
+            if (!st)
+                continue;
+
+            av_dict_set(&st->metadata, "filename", attachments[j].filename, 0);
+            av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0);
+            if (attachments[j].description)
+                av_dict_set(&st->metadata, "title", attachments[j].description, 0);
+
+            attachments[j].stream = st;
         }
     }
 
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 7805330bf9..b73457795c 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -196,6 +196,11 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
         return 0;
     }
 
+    if (!(c->fc->flags & AVFMT_FLAG_ATTACHED_PIC)) {
+        avio_skip(pb, len);
+        return 0;
+    }
+
     sc = av_mallocz(sizeof(*sc));
     if (!sc)
         return AVERROR(ENOMEM);
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 0e8c25c030..cc48374a99 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -75,7 +75,8 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
 int ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st,
                              const uint8_t *buf, int size)
 {
-    int updates = ff_vorbis_comment(as, &st->metadata, buf, size, 1);
+    int updates = ff_vorbis_comment(as, &st->metadata, buf, size,
+                                    !!(as->flags & AVFMT_FLAG_ATTACHED_PIC));
 
     if (updates > 0) {
         st->event_flags |= AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index b4141564c8..d54906327b 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -39,7 +39,7 @@ static const AVOption avformat_options[] = {
 {"probesize", "set probing size", OFFSET(probesize), AV_OPT_TYPE_INT64, {.i64 = 5000000 }, 32, INT64_MAX, D},
 {"formatprobesize", "number of bytes to probe file format", OFFSET(format_probesize), AV_OPT_TYPE_INT, {.i64 = PROBE_BUF_MAX}, 0, INT_MAX-1, D},
 {"packetsize", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, E},
-{"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = AVFMT_FLAG_AUTO_BSF }, INT_MIN, INT_MAX, D|E, "fflags"},
+{"fflags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = AVFMT_FLAG_AUTO_BSF | AVFMT_FLAG_ATTACHED_PIC}, INT_MIN, INT_MAX, D|E, "fflags"},
 {"flush_packets", "reduce the latency by flushing out packets immediately", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_FLUSH_PACKETS }, INT_MIN, INT_MAX, E, "fflags"},
 {"ignidx", "ignore index", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNIDX }, INT_MIN, INT_MAX, D, "fflags"},
 {"genpts", "generate pts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_GENPTS }, INT_MIN, INT_MAX, D, "fflags"},
@@ -59,6 +59,7 @@ static const AVOption avformat_options[] = {
 {"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
 {"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" },
 {"autobsf", "add needed bsfs automatically", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" },
+{"attached_pic", "export attached pictures", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_ATTACHED_PIC }, 0, 0, D, "fflags" },
 {"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D},
 {"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
 {"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 0834c80f4e..3624678193 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -655,7 +655,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
     if (id3v2_extra_meta) {
         if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||
             !strcmp(s->iformat->name, "tta") || !strcmp(s->iformat->name, "wav")) {
-            if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0)
+            if (s->flags & AVFMT_FLAG_ATTACHED_PIC &&
+                (ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0)
                 goto close;
             if ((ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0)
                 goto close;
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 8214ab8498..2179c55020 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -552,7 +552,8 @@ static int wav_read_header(AVFormatContext *s)
             ID3v2ExtraMeta *id3v2_extra_meta = NULL;
             ff_id3v2_read_dict(pb, &s->internal->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
             if (id3v2_extra_meta) {
-                ff_id3v2_parse_apic(s, id3v2_extra_meta);
+                if (s->flags & AVFMT_FLAG_ATTACHED_PIC)
+                    ff_id3v2_parse_apic(s, id3v2_extra_meta);
                 ff_id3v2_parse_chapters(s, id3v2_extra_meta);
                 ff_id3v2_parse_priv(s, id3v2_extra_meta);
             }
diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c
index 44ca86d517..80aa0e0f88 100644
--- a/libavformat/wtvdec.c
+++ b/libavformat/wtvdec.c
@@ -437,7 +437,8 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
     int64_t pos = avio_tell(pb);
 
     avio_get_str16le(pb, INT_MAX, mime, sizeof(mime));
-    if (strcmp(mime, "image/jpeg"))
+    if (strcmp(mime, "image/jpeg") ||
+        !(s->flags & AVFMT_FLAG_ATTACHED_PIC))
         goto done;
 
     avio_r8(pb);
-- 
2.31.0



More information about the ffmpeg-devel mailing list