PR #21240 opened by nyh163925
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21240
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21240.patch

    Disabled by --disable-id3, default enabled.
    Turning off ID3 support when it is clear that the ID3
    protocol is not needed can save approximately 11kb of
    code size.


>From 7ba25a716484b4bd57cdbe35eabae8eee70a4686 Mon Sep 17 00:00:00 2001
From: niyinghao <[email protected]>
Date: Fri, 19 Dec 2025 20:57:10 +0800
Subject: [PATCH] avformat/id3: Add macro control ID3 protocol enable

    Disabled by --disable-id3, default enabled.
    Turning off ID3 support when it is clear that the ID3
    protocol is not needed can save approximately 11kb of
    code size.
---
 configure              |  2 +
 libavformat/id3v1.c    | 22 +++++++++-
 libavformat/id3v1.h    |  2 +-
 libavformat/id3v2.c    | 99 +++++++++++++++++++++++++++++++++++++++++-
 libavformat/id3v2enc.c | 26 +++++++++++
 libavformat/mov.c      |  6 ++-
 libavformat/mp3enc.c   |  6 ++-
 7 files changed, 156 insertions(+), 7 deletions(-)

diff --git a/configure b/configure
index 9458a1d964..69a61f8004 100755
--- a/configure
+++ b/configure
@@ -2101,6 +2101,7 @@ FEATURE_LIST="
     ftrapv
     gray
     hardcoded_tables
+    id3
     omx_rpi
     runtime_cpudetect
     safe_bitstream_reader
@@ -4294,6 +4295,7 @@ enable debug
 enable doc
 enable faan faandct faanidct
 enable iamf
+enable id3
 enable large_tests
 enable optimizations
 enable ptx_compression
diff --git a/libavformat/id3v1.c b/libavformat/id3v1.c
index 3189a48b8c..84c5a33108 100644
--- a/libavformat/id3v1.c
+++ b/libavformat/id3v1.c
@@ -20,10 +20,12 @@
  */
 
 #include "id3v1.h"
+
+#if CONFIG_ID3
 #include "libavutil/dict.h"
 
 /* See Genre List at http://id3.org/id3v2.3.0 */
-const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = {
+const char * const id3v1_genre_str[ID3v1_GENRE_MAX + 1] = {
       [0] = "Blues",
       [1] = "Classic Rock",
       [2] = "Country",
@@ -218,6 +220,11 @@ const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] 
= {
     [191] = "Psybient"
 };
 
+const char *ff_id3v1_genre_str(int genre)
+{
+    return (genre < 0 || genre > ID3v1_GENRE_MAX) ? NULL : 
id3v1_genre_str[genre];
+}
+
 static void get_string(AVFormatContext *s, const char *key,
                        const uint8_t *buf, int buf_size)
 {
@@ -271,7 +278,7 @@ static int parse_tag(AVFormatContext *s, const uint8_t *buf)
     }
     genre = buf[127];
     if (genre <= ID3v1_GENRE_MAX)
-        av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str[genre], 0);
+        av_dict_set(&s->metadata, "genre", ff_id3v1_genre_str(genre), 0);
     return 0;
 }
 
@@ -294,3 +301,14 @@ void ff_id3v1_read(AVFormatContext *s)
         }
     }
 }
+#else
+
+void ff_id3v1_read(AVFormatContext *s)
+{
+}
+
+const char *ff_id3v1_genre_str(int genre)
+{
+    return NULL;
+}
+#endif
diff --git a/libavformat/id3v1.h b/libavformat/id3v1.h
index b3ad16df6c..837c19db58 100644
--- a/libavformat/id3v1.h
+++ b/libavformat/id3v1.h
@@ -31,7 +31,7 @@
 /**
  * ID3v1 genres
  */
-extern const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1];
+const char *ff_id3v1_genre_str(int genre);
 
 /**
  * Read an ID3v1 tag
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 9d4a9802a9..806538d41c 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -28,6 +28,7 @@
 
 #include "config.h"
 
+#if CONFIG_ID3
 #if CONFIG_ZLIB
 #include <zlib.h>
 #endif
@@ -142,6 +143,10 @@ const CodecMime ff_id3v2_mime_tags[] = {
     { "PNG",        AV_CODEC_ID_PNG   }, /* ID3v2.2  */
     { "",           AV_CODEC_ID_NONE  },
 };
+#else
+#include "avio_internal.h"
+#include "id3v2.h"
+#endif
 
 int ff_id3v2_match(const uint8_t *buf, const char *magic)
 {
@@ -168,6 +173,7 @@ int ff_id3v2_tag_len(const uint8_t *buf)
     return len;
 }
 
+#if CONFIG_ID3
 static unsigned int get_size(AVIOContext *s, int len)
 {
     int v = 0;
@@ -351,7 +357,7 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, 
int taglen,
         (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) &&
         genre <= ID3v1_GENRE_MAX) {
         av_freep(&dst);
-        dst = av_strdup(ff_id3v1_genre_str[genre]);
+        dst = av_strdup(ff_id3v1_genre_str(genre));
     } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
         /* dst now contains the key, need to get value */
         key = dst;
@@ -1266,3 +1272,94 @@ int ff_id3v2_parse_priv(AVFormatContext *s, 
ID3v2ExtraMeta *extra_meta)
 {
     return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta);
 }
+
+#else
+
+static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata,
+                                AVFormatContext *s, const char *magic,
+                                ID3v2ExtraMeta **extra_metap, int64_t 
max_search_size)
+{
+    uint8_t buf[ID3v2_HEADER_SIZE];
+    int len, ret, found_header;
+    int64_t start, off, next;
+
+    if (extra_metap)
+        *extra_metap = NULL;
+
+    if (max_search_size && max_search_size < ID3v2_HEADER_SIZE)
+        return;
+
+    start = avio_tell(pb);
+    do {
+        /* save the current offset in case there's nothing to read/skip */
+        off = avio_tell(pb);
+        if (max_search_size && off - start >= max_search_size - 
ID3v2_HEADER_SIZE) {
+            avio_seek(pb, off, SEEK_SET);
+            break;
+        }
+
+        ret = ffio_ensure_seekback(pb, ID3v2_HEADER_SIZE);
+        if (ret >= 0)
+            ret = avio_read(pb, buf, ID3v2_HEADER_SIZE);
+
+        if (ret != ID3v2_HEADER_SIZE) {
+            avio_seek(pb, off, SEEK_SET);
+            break;
+        }
+        found_header = ff_id3v2_match(buf, magic);
+        if (found_header) {
+            /* parse ID3v2 header */
+            len = ((buf[6] & 0x7f) << 21) |
+                  ((buf[7] & 0x7f) << 14) |
+                  ((buf[8] & 0x7f) << 7) |
+                   (buf[9] & 0x7f);
+            avio_seek(pb, off + len, SEEK_SET);
+        } else
+            avio_seek(pb, off, SEEK_SET);
+    } while (found_header);
+}
+
+void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, const char 
*magic,
+                        ID3v2ExtraMeta **extra_meta)
+{
+    id3v2_read_internal(pb, metadata, NULL, magic, extra_meta, 0);
+}
+
+void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta 
**extra_meta,
+                   unsigned int max_search_size)
+{
+    id3v2_read_internal(s->pb, &s->metadata, s, magic, extra_meta, 
max_search_size);
+}
+
+void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
+{
+}
+
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
+{
+    return 0;
+}
+
+int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
+{
+    return 0;
+}
+
+int ff_id3v2_parse_priv_dict(AVDictionary **d, ID3v2ExtraMeta *extra_meta)
+{
+    return 0;
+}
+
+int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
+{
+    return 0;
+}
+
+const CodecMime ff_id3v2_mime_tags[] = {
+    { "", AV_CODEC_ID_NONE },
+};
+
+const char * const ff_id3v2_picture_types[] = {
+    "Other",
+};
+#endif
diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c
index ac907c2758..6bf1b64b52 100644
--- a/libavformat/id3v2enc.c
+++ b/libavformat/id3v2enc.c
@@ -30,6 +30,7 @@
 #include "id3v2.h"
 #include "mux.h"
 
+#if CONFIG_ID3
 static void id3v2_put_size(AVIOContext *pb, int size)
 {
     avio_w8(pb, size >> 21 & 0x7f);
@@ -455,3 +456,28 @@ int ff_id3v2_write_simple(struct AVFormatContext *s, int 
id3v2_version,
 
     return 0;
 }
+#else
+void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
+                    const char *magic)
+{
+}
+
+int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
+{
+    return 0;
+}
+
+int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket 
*pkt)
+{
+    return 0;
+}
+
+void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes)
+{
+}
+
+int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, const 
char *magic)
+{
+    return 0;
+}
+#endif
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 009ddfec80..19a57e3162 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -134,15 +134,17 @@ static int mov_metadata_int8_no_padding(MOVContext *c, 
AVIOContext *pb,
 static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
                              unsigned len, const char *key)
 {
+    const char *gnre;
     short genre;
 
     avio_r8(pb); // unknown
 
     genre = avio_r8(pb);
-    if (genre < 1 || genre > ID3v1_GENRE_MAX)
+    gnre  = ff_id3v1_genre_str(genre - 1);
+    if (genre < 1 || genre > ID3v1_GENRE_MAX || !gnre)
         return 0;
     c->fc->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
-    av_dict_set(&c->fc->metadata, key, ff_id3v1_genre_str[genre-1], 0);
+    av_dict_set(&c->fc->metadata, key, gnre, 0);
 
     return 0;
 }
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index 724c7269dc..e3c5db5571 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -52,6 +52,7 @@ static int id3v1_set_string(AVFormatContext *s, const char 
*key,
 static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
 {
     AVDictionaryEntry *tag;
+    const char *genre;
     int i, count = 0;
 
     memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */
@@ -82,7 +83,10 @@ static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
     buf[127] = 0xFF; /* default to unknown genre */
     if ((tag = av_dict_get(s->metadata, "TCON", NULL, 0))) { //genre
         for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
-            if (!av_strcasecmp(tag->value, ff_id3v1_genre_str[i])) {
+            if ((genre = ff_id3v1_genre_str(i)) == NULL)
+                break;
+
+            if (!av_strcasecmp(tag->value, genre)) {
                 buf[127] = i;
                 count++;
                 break;
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to