[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