[FFmpeg-devel] [PATCH 4/7] avformat/vorbiscomment: Switch to AVIOContext from bytestream API

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Tue Apr 28 11:36:42 EEST 2020


ff_vorbiscomment_write() used up until now the bytestream API to write
VorbisComments. Therefore the caller had to provide a sufficiently large
buffer to write the output.

Yet two of the three callers (namely the FLAC and the Matroska muxer)
actually want the output to be written via an AVIOContext; therefore
they allocated buffers of the right size just for this purpose (i.e.
they get freed immediately afterwards). Only the Ogg muxer actually
wants a buffer. But given that it is easy to wrap a buffer into an
AVIOContext this commit changes ff_vorbiscomment_write() to use an
AVIOContext for its output.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
 libavformat/flacenc.c       | 18 ++++-----------
 libavformat/matroskaenc.c   | 18 ++++-----------
 libavformat/oggenc.c        | 12 +++++-----
 libavformat/vorbiscomment.c | 44 ++++++++++++++++++-------------------
 libavformat/vorbiscomment.h |  9 ++++----
 5 files changed, 40 insertions(+), 61 deletions(-)

diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c
index 0e88e18355..b947a3b067 100644
--- a/libavformat/flacenc.c
+++ b/libavformat/flacenc.c
@@ -29,7 +29,6 @@
 #include "id3v2.h"
 #include "internal.h"
 #include "vorbiscomment.h"
-#include "libavcodec/bytestream.h"
 
 
 typedef struct FlacMuxerContext {
@@ -62,25 +61,16 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
 {
     const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
     int64_t len;
-    uint8_t *p, *p0;
 
     ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
 
     len = ff_vorbiscomment_length(*m, vendor, NULL, 0);
     if (len >= ((1<<24) - 4))
         return AVERROR(EINVAL);
-    p0 = av_malloc(len+4);
-    if (!p0)
-        return AVERROR(ENOMEM);
-    p = p0;
-
-    bytestream_put_byte(&p, last_block ? 0x84 : 0x04);
-    bytestream_put_be24(&p, len);
-    ff_vorbiscomment_write(&p, *m, vendor, NULL, 0);
-
-    avio_write(pb, p0, len+4);
-    av_freep(&p0);
-    p = NULL;
+
+    avio_w8(pb, last_block ? 0x84 : 0x04);
+    avio_wb24(pb, len);
+    ff_vorbiscomment_write(pb, *m, vendor, NULL, 0);
 
     return 0;
 }
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 58bcdb904f..3513a1697a 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -624,7 +624,7 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
         const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ?
                              "Lavf" : LIBAVFORMAT_IDENT;
         AVDictionary *dict = NULL;
-        uint8_t buf[32], *data, *p;
+        uint8_t buf[32];
         int64_t len;
 
         snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
@@ -633,21 +633,11 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
         len = ff_vorbiscomment_length(dict, vendor, NULL, 0);
         av_assert1(len < (1 << 24) - 4);
 
-        data = av_malloc(len + 4);
-        if (!data) {
-            av_dict_free(&dict);
-            return AVERROR(ENOMEM);
-        }
-
-        data[0] = 0x84;
-        AV_WB24(data + 1, len);
-
-        p = data + 4;
-        ff_vorbiscomment_write(&p, dict, vendor, NULL, 0);
+        avio_w8(pb, 0x84);
+        avio_wb24(pb, len);
 
-        avio_write(pb, data, len + 4);
+        ff_vorbiscomment_write(pb, dict, vendor, NULL, 0);
 
-        av_freep(&data);
         av_dict_free(&dict);
     }
 
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index cc9a899a4c..3aff3c7a08 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -294,8 +294,9 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
                                         AVChapter **chapters, unsigned int nb_chapters)
 {
     const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
+    AVIOContext pb;
     int64_t size;
-    uint8_t *p, *p0;
+    uint8_t *p;
 
     ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
 
@@ -305,15 +306,14 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
     p = av_mallocz(size);
     if (!p)
         return NULL;
-    p0 = p;
 
-    p += offset;
-    ff_vorbiscomment_write(&p, *m, vendor, chapters, nb_chapters);
+    ffio_init_context(&pb, p + offset, size - offset, 1, NULL, NULL, NULL, NULL);
+    ff_vorbiscomment_write(&pb, *m, vendor, chapters, nb_chapters);
     if (framing_bit)
-        bytestream_put_byte(&p, 1);
+        avio_w8(&pb, 1);
 
     *header_len = size;
-    return p0;
+    return p;
 }
 
 static int ogg_build_flac_headers(AVCodecParameters *par,
diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c
index edaeae2772..a929634cc0 100644
--- a/libavformat/vorbiscomment.c
+++ b/libavformat/vorbiscomment.c
@@ -19,10 +19,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "avio.h"
 #include "avformat.h"
 #include "metadata.h"
 #include "vorbiscomment.h"
-#include "libavcodec/bytestream.h"
 #include "libavutil/dict.h"
 
 /**
@@ -62,13 +62,13 @@ int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string
     return len;
 }
 
-int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
+int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m,
                            const char *vendor_string,
                            AVChapter **chapters, unsigned int nb_chapters)
 {
     int cm_count = 0;
-    bytestream_put_le32(p, strlen(vendor_string));
-    bytestream_put_buffer(p, vendor_string, strlen(vendor_string));
+    avio_wl32(pb, strlen(vendor_string));
+    avio_write(pb, vendor_string, strlen(vendor_string));
     if (chapters && nb_chapters) {
         for (int i = 0; i < nb_chapters; i++) {
             cm_count += av_dict_count(chapters[i]->metadata) + 1;
@@ -77,16 +77,16 @@ int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
     if (m) {
         int count = av_dict_count(m) + cm_count;
         AVDictionaryEntry *tag = NULL;
-        bytestream_put_le32(p, count);
+        avio_wl32(pb, count);
         while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) {
             int64_t len1 = strlen(tag->key);
             int64_t len2 = strlen(tag->value);
             if (len1+1+len2 > UINT32_MAX)
                 return AVERROR(EINVAL);
-            bytestream_put_le32(p, len1+1+len2);
-            bytestream_put_buffer(p, tag->key, len1);
-            bytestream_put_byte(p, '=');
-            bytestream_put_buffer(p, tag->value, len2);
+            avio_wl32(pb, len1 + 1 + len2);
+            avio_write(pb, tag->key, len1);
+            avio_w8(pb, '=');
+            avio_write(pb, tag->value, len2);
         }
         for (int i = 0; i < nb_chapters; i++) {
             AVChapter *chp = chapters[i];
@@ -101,11 +101,11 @@ int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
             s  = s % 60;
             snprintf(chapter_number, sizeof(chapter_number), "%03d", i);
             snprintf(chapter_time, sizeof(chapter_time), "%02d:%02d:%02d.%03d", h, m, s, ms);
-            bytestream_put_le32(p, 10+1+12);
-            bytestream_put_buffer(p, "CHAPTER", 7);
-            bytestream_put_buffer(p, chapter_number, 3);
-            bytestream_put_byte(p, '=');
-            bytestream_put_buffer(p, chapter_time, 12);
+            avio_wl32(pb, 10 + 1 + 12);
+            avio_write(pb, "CHAPTER", 7);
+            avio_write(pb, chapter_number, 3);
+            avio_w8(pb, '=');
+            avio_write(pb, chapter_time, 12);
 
             tag = NULL;
             while ((tag = av_dict_get(chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
@@ -113,18 +113,18 @@ int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
                 int64_t len2 = strlen(tag->value);
                 if (len1+1+len2+10 > UINT32_MAX)
                     return AVERROR(EINVAL);
-                bytestream_put_le32(p, 10+len1+1+len2);
-                bytestream_put_buffer(p, "CHAPTER", 7);
-                bytestream_put_buffer(p, chapter_number, 3);
+                avio_wl32(pb, 10 + len1 + 1 + len2);
+                avio_write(pb, "CHAPTER", 7);
+                avio_write(pb, chapter_number, 3);
                 if (!strcmp(tag->key, "title"))
-                    bytestream_put_buffer(p, "NAME", 4);
+                    avio_write(pb, "NAME", 4);
                 else
-                    bytestream_put_buffer(p, tag->key, len1);
-                bytestream_put_byte(p, '=');
-                bytestream_put_buffer(p, tag->value, len2);
+                    avio_write(pb, tag->key, len1);
+                avio_w8(pb, '=');
+                avio_write(pb, tag->value, len2);
             }
         }
     } else
-        bytestream_put_le32(p, 0);
+        avio_wl32(pb, 0);
     return 0;
 }
diff --git a/libavformat/vorbiscomment.h b/libavformat/vorbiscomment.h
index af9bd75cd7..7cacd0b2a0 100644
--- a/libavformat/vorbiscomment.h
+++ b/libavformat/vorbiscomment.h
@@ -38,18 +38,17 @@ int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string
                                 AVChapter **chapters, unsigned int nb_chapters);
 
 /**
- * Write a VorbisComment into a buffer. The buffer, p, must have enough
- * data to hold the whole VorbisComment. The minimum size required can be
- * obtained by passing the same AVDictionary and vendor_string to
+ * Write a VorbisComment into an AVIOContext. The output size can be obtained
+ * in advance by passing the same chapters, AVDictionary and vendor_string to
  * ff_vorbiscomment_length()
  *
- * @param p The buffer in which to write.
+ * @param pb The AVIOContext to write the output.
  * @param m The metadata struct to write.
  * @param vendor_string The vendor string to write.
  * @param chapters The chapters to write.
  * @param nb_chapters The number of chapters to write.
  */
-int ff_vorbiscomment_write(uint8_t **p, const AVDictionary *m,
+int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m,
                            const char *vendor_string,
                            AVChapter **chapters, unsigned int nb_chapters);
 
-- 
2.20.1



More information about the ffmpeg-devel mailing list