[FFmpeg-devel] [PATCH] avformat: add apic to AVStream

James Almer jamrial at gmail.com
Sun Mar 28 18:58:31 EEST 2021


As a replacement for attached_pic, which is in turn deprecated and scheduled
for removal.

Signed-off-by: James Almer <jamrial at gmail.com>
---
TODO: APIChanges entry and version bump.

Decided to use the name apic for the field, since it's how id3v2 and other
formats call it.

Also, in a fortunate coincidence, the first "non public" field in AVStream is a
unused void pointer that had to be left in place when the field was moved to
AVStreamInternal to keep every offset intact for the sake of ffmpeg accessing
fields after it, so I'm going to take advantage of it so this doesn't have to
wait until the major bump.

 libavformat/apetag.c       | 15 ++++++++++++---
 libavformat/asfdec_f.c     | 21 +++++++++++++++------
 libavformat/asfdec_o.c     | 21 +++++++++++++++------
 libavformat/avformat.h     | 21 ++++++++++++++++-----
 libavformat/flac_picture.c | 21 +++++++++++++++------
 libavformat/hls.c          |  6 +++---
 libavformat/id3v2.c        | 23 +++++++++++++++++------
 libavformat/matroskadec.c  |  9 ++++++++-
 libavformat/mov.c          | 31 +++++++++++++++++++++++--------
 libavformat/utils.c        | 14 ++++++++++++--
 libavformat/version.h      |  3 +++
 libavformat/wtvdec.c       | 13 ++++++++++---
 12 files changed, 149 insertions(+), 49 deletions(-)

diff --git a/libavformat/apetag.c b/libavformat/apetag.c
index 23ee6b516d..e0e96c3f4c 100644
--- a/libavformat/apetag.c
+++ b/libavformat/apetag.c
@@ -81,7 +81,7 @@ static int ape_tag_read_field(AVFormatContext *s)
         if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) {
             int ret;
 
-            ret = av_get_packet(s->pb, &st->attached_pic, size);
+            ret = av_get_packet(s->pb, st->apic, size);
             if (ret < 0) {
                 av_log(s, AV_LOG_ERROR, "Error reading cover art.\n");
                 return ret;
@@ -91,8 +91,17 @@ static int ape_tag_read_field(AVFormatContext *s)
             st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
             st->codecpar->codec_id   = id;
 
-            st->attached_pic.stream_index = st->index;
-            st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+            st->apic->stream_index   = st->index;
+            st->apic->flags         |= AV_PKT_FLAG_KEY;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+            ret = av_packet_ref(&st->attached_pic, st->apic);
+            if (ret < 0) {
+                av_packet_unref(st->apic);
+                return ret;
+            }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
         } else {
             if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
                 return ret;
diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c
index 2fae528f4d..838fc924d5 100644
--- a/libavformat/asfdec_f.c
+++ b/libavformat/asfdec_f.c
@@ -223,7 +223,7 @@ static int get_value(AVIOContext *pb, int type, int type2_size)
  * but in reality this is only loosely similar */
 static int asf_read_picture(AVFormatContext *s, int len)
 {
-    AVPacket pkt          = { 0 };
+    AVPacket *pkt = s->internal->parse_pkt;
     const CodecMime *mime = ff_id3v2_mime_tags;
     enum  AVCodecID id    = AV_CODEC_ID_NONE;
     char mimetype[64];
@@ -277,7 +277,7 @@ static int asf_read_picture(AVFormatContext *s, int len)
         return AVERROR(ENOMEM);
     len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len);
 
-    ret = av_get_packet(s->pb, &pkt, picsize);
+    ret = av_get_packet(s->pb, pkt, picsize);
     if (ret < 0)
         goto fail;
 
@@ -286,12 +286,21 @@ static int asf_read_picture(AVFormatContext *s, int len)
         ret = AVERROR(ENOMEM);
         goto fail;
     }
+    av_packet_move_ref(st->apic, pkt);
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
     st->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
     st->codecpar->codec_id        = id;
-    st->attached_pic              = pkt;
-    st->attached_pic.stream_index = st->index;
-    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+    st->apic->stream_index        = st->index;
+    st->apic->flags              |= AV_PKT_FLAG_KEY;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+    ret = av_packet_ref(&st->attached_pic, st->apic);
+    if (ret < 0) {
+        av_packet_unref(st->apic);
+        goto fail;
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     if (*desc)
         av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL);
@@ -304,7 +313,7 @@ static int asf_read_picture(AVFormatContext *s, int len)
 
 fail:
     av_freep(&desc);
-    av_packet_unref(&pkt);
+    av_packet_unref(pkt);
     return ret;
 }
 
diff --git a/libavformat/asfdec_o.c b/libavformat/asfdec_o.c
index 34ae541934..51577064b8 100644
--- a/libavformat/asfdec_o.c
+++ b/libavformat/asfdec_o.c
@@ -360,7 +360,7 @@ static int asf_set_metadata(AVFormatContext *s, const uint8_t *name,
  * but in reality this is only loosely similar */
 static int asf_read_picture(AVFormatContext *s, int len)
 {
-    AVPacket pkt          = { 0 };
+    AVPacket *pkt = s->internal->parse_pkt;
     const CodecMime *mime = ff_id3v2_mime_tags;
     enum  AVCodecID id    = AV_CODEC_ID_NONE;
     char mimetype[64];
@@ -414,7 +414,7 @@ static int asf_read_picture(AVFormatContext *s, int len)
         return AVERROR(ENOMEM);
     len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len);
 
-    ret = av_get_packet(s->pb, &pkt, picsize);
+    ret = av_get_packet(s->pb, pkt, picsize);
     if (ret < 0)
         goto fail;
 
@@ -424,12 +424,21 @@ static int asf_read_picture(AVFormatContext *s, int len)
         goto fail;
     }
 
+    av_packet_move_ref(st->apic, pkt);
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
     st->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
     st->codecpar->codec_id        = id;
-    st->attached_pic              = pkt;
-    st->attached_pic.stream_index = st->index;
-    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+    st->apic->stream_index        = st->index;
+    st->apic->flags              |= AV_PKT_FLAG_KEY;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+    ret = av_packet_ref(&st->attached_pic, st->apic);
+    if (ret < 0) {
+        av_packet_unref(st->apic);
+        goto fail;
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     if (*desc) {
         if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0)
@@ -444,7 +453,7 @@ static int asf_read_picture(AVFormatContext *s, int len)
 
 fail:
     av_freep(&desc);
-    av_packet_unref(&pkt);
+    av_packet_unref(pkt);
     return ret;
 }
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 765bc3b6f5..769d27d84a 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -947,14 +947,19 @@ typedef struct AVStream {
      */
     AVRational avg_frame_rate;
 
+#if FF_API_ATTACHED_PIC
     /**
      * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet
      * will contain the attached picture.
      *
      * decoding: set by libavformat, must not be modified by the caller.
      * encoding: unused
+     *
+     * @deprecated Use apic instead.
      */
+    attribute_deprecated
     AVPacket attached_pic;
+#endif
 
     /**
      * An array of side data that applies to the whole stream (i.e. the
@@ -1039,6 +1044,17 @@ typedef struct AVStream {
      */
     AVCodecParameters *codecpar;
 
+    /**
+     * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet
+     * will contain the attached picture. It is allocated and freed by
+     * libavformat in avformat_new_stream() and avformat_free_context()
+     * respectively.
+     *
+     * - demuxing: set by libavformat, must not be modified by the caller.
+     * - muxing: unused
+     */
+    AVPacket *apic;
+
     /*****************************************************************
      * All fields below this line are not part of the public API. They
      * may not be used outside of libavformat and can be changed and
@@ -1049,11 +1065,6 @@ typedef struct AVStream {
      *****************************************************************
      */
 
-#if LIBAVFORMAT_VERSION_MAJOR < 59
-    // kept for ABI compatibility only, do not access in any way
-    void *unused;
-#endif
-
     int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
 
     // Timestamp generation support:
diff --git a/libavformat/flac_picture.c b/libavformat/flac_picture.c
index f15cfa877a..f771df3fc2 100644
--- a/libavformat/flac_picture.c
+++ b/libavformat/flac_picture.c
@@ -165,12 +165,20 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size, int tr
         RETURN_ERROR(AVERROR(ENOMEM));
     }
 
-    av_packet_unref(&st->attached_pic);
-    st->attached_pic.buf          = data;
-    st->attached_pic.data         = data->data;
-    st->attached_pic.size         = len;
-    st->attached_pic.stream_index = st->index;
-    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+    av_packet_unref(st->apic);
+    st->apic->buf          = data;
+    st->apic->data         = data->data;
+    st->apic->size         = len;
+    st->apic->stream_index = st->index;
+    st->apic->flags       |= AV_PKT_FLAG_KEY;
+    data = NULL;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+    ret = av_packet_ref(&st->attached_pic, st->apic);
+    if (ret < 0)
+        goto fail;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;
     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
@@ -185,6 +193,7 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size, int tr
 
 fail:
     av_buffer_unref(&data);
+    av_packet_unref(st->apic);
     av_freep(&desc);
 
     return ret;
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 597bea7f25..2b18385496 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -1068,15 +1068,15 @@ static int id3_has_changed_values(struct playlist *pls, AVDictionary *metadata,
     }
 
     /* check if apic appeared */
-    if (apic && (pls->ctx->nb_streams != 2 || !pls->ctx->streams[1]->attached_pic.data))
+    if (apic && (pls->ctx->nb_streams != 2 || !pls->ctx->streams[1]->apic->data))
         return 1;
 
     if (apic) {
-        int size = pls->ctx->streams[1]->attached_pic.size;
+        int size = pls->ctx->streams[1]->apic->size;
         if (size != apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE)
             return 1;
 
-        if (memcmp(apic->buf->data, pls->ctx->streams[1]->attached_pic.data, size) != 0)
+        if (memcmp(apic->buf->data, pls->ctx->streams[1]->apic->data, size) != 0)
             return 1;
     }
 
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index f33b7ba93a..f8c10ab90c 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -1142,6 +1142,7 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
     for (cur = extra_meta; cur; cur = cur->next) {
         ID3v2ExtraMetaAPIC *apic;
         AVStream *st;
+        int ret;
 
         if (strcmp(cur->tag, "APIC"))
             continue;
@@ -1162,14 +1163,24 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
 
         av_dict_set(&st->metadata, "comment", apic->type, 0);
 
-        av_packet_unref(&st->attached_pic);
-        st->attached_pic.buf          = apic->buf;
-        st->attached_pic.data         = apic->buf->data;
-        st->attached_pic.size         = apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE;
-        st->attached_pic.stream_index = st->index;
-        st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+        av_packet_unref(st->apic);
+        st->apic->buf          = apic->buf;
+        st->apic->data         = apic->buf->data;
+        st->apic->size         = apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE;
+        st->apic->stream_index = st->index;
+        st->apic->flags       |= AV_PKT_FLAG_KEY;
 
         apic->buf = NULL;
+
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+        ret = av_packet_ref(&st->attached_pic, st->apic);
+        if (ret < 0) {
+            av_packet_unref(st->apic);
+            return ret;
+        }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     }
 
     return 0;
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 1dc188c946..92e3b8f183 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -3007,7 +3007,7 @@ static int matroska_read_header(AVFormatContext *s)
             attachments[j].stream = st;
 
             if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
-                AVPacket *pkt = &st->attached_pic;
+                AVPacket *pkt = st->apic;
 
                 st->disposition         |= AV_DISPOSITION_ATTACHED_PIC;
                 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
@@ -3019,6 +3019,13 @@ static int matroska_read_header(AVFormatContext *s)
                 pkt->size         = attachments[j].bin.size;
                 pkt->stream_index = st->index;
                 pkt->flags       |= AV_PKT_FLAG_KEY;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+                res = av_packet_ref(&st->attached_pic, pkt);
+                if (res < 0)
+                    goto fail;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
             } else {
                 st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
                 if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size))
diff --git a/libavformat/mov.c b/libavformat/mov.c
index cb818ebe0e..d99f922709 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -204,12 +204,21 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
         return AVERROR(ENOMEM);
     st->priv_data = sc;
 
-    ret = av_get_packet(pb, &st->attached_pic, len);
+    ret = av_get_packet(pb, st->apic, len);
     if (ret < 0)
         return ret;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+    ret = av_packet_ref(&st->attached_pic, st->apic);
+    if (ret < 0) {
+        av_packet_unref(st->apic);
+        return ret;
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
-    if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
-        if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
+    if (st->apic->size >= 8 && id != AV_CODEC_ID_BMP) {
+        if (AV_RB64(st->apic->data) == 0x89504e470d0a1a0a) {
             id = AV_CODEC_ID_PNG;
         } else {
             id = AV_CODEC_ID_MJPEG;
@@ -218,8 +227,8 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
 
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
 
-    st->attached_pic.stream_index = st->index;
-    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+    st->apic->stream_index        = st->index;
+    st->apic->flags              |= AV_PKT_FLAG_KEY;
 
     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     st->codecpar->codec_id   = id;
@@ -7229,11 +7238,17 @@ static void mov_read_chapters(AVFormatContext *s)
                     goto finish;
                 }
 
-                if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0)
+                if (av_get_packet(sc->pb, st->apic, sample->size) < 0)
                     goto finish;
 
-                st->attached_pic.stream_index = st->index;
-                st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+                st->apic->stream_index = st->index;
+                st->apic->flags       |= AV_PKT_FLAG_KEY;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+                if (av_packet_ref(&st->attached_pic, st->apic) < 0)
+                    goto finish;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
             }
         } else {
             st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 524765aeb4..9308b53106 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -457,7 +457,7 @@ int avformat_queue_attached_pictures(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++)
         if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC &&
             s->streams[i]->discard < AVDISCARD_ALL) {
-            if (s->streams[i]->attached_pic.size <= 0) {
+            if (s->streams[i]->apic->size <= 0) {
                 av_log(s, AV_LOG_WARNING,
                     "Attached picture on stream %d has invalid size, "
                     "ignoring\n", i);
@@ -466,7 +466,7 @@ int avformat_queue_attached_pictures(AVFormatContext *s)
 
             ret = avpriv_packet_list_put(&s->internal->raw_packet_buffer,
                                      &s->internal->raw_packet_buffer_end,
-                                     &s->streams[i]->attached_pic,
+                                     s->streams[i]->apic,
                                      av_packet_ref, 0);
             if (ret < 0)
                 return ret;
@@ -4371,8 +4371,14 @@ static void free_stream(AVStream **pst)
     if (st->parser)
         av_parser_close(st->parser);
 
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
     if (st->attached_pic.data)
         av_packet_unref(&st->attached_pic);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    av_packet_free(&st->apic);
 
     if (st->internal) {
         avcodec_free_context(&st->internal->avctx);
@@ -4530,6 +4536,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
     if (!st->codecpar)
         goto fail;
 
+    st->apic = av_packet_alloc();
+    if (!st->apic)
+        goto fail;
+
     st->internal->avctx = avcodec_alloc_context3(NULL);
     if (!st->internal->avctx)
         goto fail;
diff --git a/libavformat/version.h b/libavformat/version.h
index ced5600034..dce936794a 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -115,6 +115,9 @@
 #ifndef FF_API_LAVF_PRIV_OPT
 #define FF_API_LAVF_PRIV_OPT            (LIBAVFORMAT_VERSION_MAJOR < 60)
 #endif
+#ifndef FF_API_ATTACHED_PIC
+#define FF_API_ATTACHED_PIC             (LIBAVFORMAT_VERSION_MAJOR < 60)
+#endif
 
 
 #ifndef FF_API_R_FRAME_RATE
diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c
index 7def9d2348..05386add76 100644
--- a/libavformat/wtvdec.c
+++ b/libavformat/wtvdec.c
@@ -454,11 +454,18 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     st->codecpar->codec_id   = AV_CODEC_ID_MJPEG;
     st->id = -1;
-    ret = av_get_packet(pb, &st->attached_pic, filesize);
+    ret = av_get_packet(pb, st->apic, filesize);
     if (ret < 0)
         goto done;
-    st->attached_pic.stream_index = st->index;
-    st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
+    st->apic->stream_index = st->index;
+    st->apic->flags  |= AV_PKT_FLAG_KEY;
+#if FF_API_ATTACHED_PIC
+FF_DISABLE_DEPRECATION_WARNINGS
+    ret = av_packet_ref(&st->attached_pic, st->apic);
+    if (ret < 0)
+        goto done;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
 done:
     avio_seek(pb, pos + length, SEEK_SET);
-- 
2.31.0



More information about the ffmpeg-devel mailing list