PR #23008 opened by toots URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23008 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23008.patch
>From 94f82d7b8a69570306ed75a340788f4e3786988c Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Sun, 3 May 2026 16:18:28 -0500 Subject: [PATCH] avformat/id3v2: make ID3v2 parsing API public --- doc/APIchanges | 7 +++ libavformat/Makefile | 1 + libavformat/aacdec.c | 10 ++-- libavformat/adtsenc.c | 2 +- libavformat/aiffdec.c | 10 ++-- libavformat/aiffenc.c | 2 +- libavformat/asf.c | 10 ++-- libavformat/bonk.c | 8 +-- libavformat/demux.c | 12 ++-- libavformat/dsfdec.c | 8 +-- libavformat/flac_picture.c | 2 +- libavformat/flacenc.c | 2 +- libavformat/format.c | 4 +- libavformat/hls.c | 20 +++---- libavformat/id3v2.c | 25 ++++---- libavformat/id3v2.h | 111 ++++++++--------------------------- libavformat/id3v2_internal.h | 102 ++++++++++++++++++++++++++++++++ libavformat/id3v2enc.c | 2 +- libavformat/iff.c | 10 ++-- libavformat/mp3dec.c | 2 +- libavformat/mp3enc.c | 2 +- libavformat/omadec.c | 18 +++--- libavformat/omaenc.c | 2 +- libavformat/version.h | 4 +- libavformat/wavdec.c | 10 ++-- 25 files changed, 216 insertions(+), 170 deletions(-) create mode 100644 libavformat/id3v2_internal.h diff --git a/doc/APIchanges b/doc/APIchanges index f1cbbb41b8..813f78e899 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,13 @@ The last version increases of all libraries were on 2025-03-28 API changes, most recent first: +2026-05-03 - xxxxxxxxxx - lavf 62.14.100 - id3v2.h + Add avformat_id3v2_match(), avformat_id3v2_tag_len(), + avformat_id3v2_read_dict(), avformat_id3v2_read(), + avformat_id3v2_free_extra_meta(), avformat_id3v2_parse_apic(), + avformat_id3v2_parse_chapters(), avformat_id3v2_parse_priv_dict(), + avformat_id3v2_parse_priv() and related types as public API. + 2026-04-14 - 7faa6ee2aa - lavc 62.30.100 - packet.h Add AV_PKT_DATA_DYNAMIC_HDR_SMPTE_2094_APP5 side data type. diff --git a/libavformat/Makefile b/libavformat/Makefile index 7c2fcad93e..e8f28f7207 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -3,6 +3,7 @@ DESC = FFmpeg container format library HEADERS = avformat.h \ avio.h \ + id3v2.h \ version.h \ version_major.h \ diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index fef3c69f0b..4a6d75f327 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -142,13 +142,13 @@ static int handle_id3(AVFormatContext *s, AVPacket *pkt) ID3v2ExtraMeta *id3v2_extra_meta; int ret; - ret = av_append_packet(s->pb, pkt, ff_id3v2_tag_len(pkt->data) - pkt->size); + ret = av_append_packet(s->pb, pkt, avformat_id3v2_tag_len(pkt->data) - pkt->size); if (ret < 0) return ret; ffio_init_read_context(&pb, pkt->data, pkt->size); - ff_id3v2_read_dict(&pb.pub, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); - if ((ret = ff_id3v2_parse_priv_dict(&metadata, id3v2_extra_meta)) < 0) + avformat_id3v2_read_dict(&pb.pub, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); + if ((ret = avformat_id3v2_parse_priv_dict(&metadata, id3v2_extra_meta)) < 0) goto error; if (metadata) { @@ -159,7 +159,7 @@ static int handle_id3(AVFormatContext *s, AVPacket *pkt) error: av_packet_unref(pkt); - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); av_dict_free(&metadata); return ret; @@ -185,7 +185,7 @@ retry: ret = av_append_packet(s->pb, pkt, append); if (ret != append) return AVERROR_INVALIDDATA; - if (!ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { + if (!avformat_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { av_packet_unref(pkt); ret = adts_aac_resync(s); } else diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c index 0671224fc2..2e02cb475b 100644 --- a/libavformat/adtsenc.c +++ b/libavformat/adtsenc.c @@ -30,7 +30,7 @@ #include "libavutil/opt.h" #include "avformat.h" #include "apetag.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "mux.h" #define ADTS_HEADER_SIZE 7 diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 63194f2726..4edd6c7ed3 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -278,14 +278,14 @@ static int aiff_read_header(AVFormatContext *s) break; case MKTAG('I', 'D', '3', ' '): position = avio_tell(pb); - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); + avformat_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); if (id3v2_extra_meta) - if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 || - (ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) { - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + if ((ret = avformat_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 || + (ret = avformat_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) { + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); return ret; } - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); if (position + size > avio_tell(pb)) avio_skip(pb, position + size - avio_tell(pb)); break; diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 2cd1119409..933a6e5cd4 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -29,7 +29,7 @@ #include "aiff.h" #include "avio_internal.h" #include "isom.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "mux.h" typedef struct AIFFOutputContext { diff --git a/libavformat/asf.c b/libavformat/asf.c index 5c118d2dbe..26ad56eedf 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -21,7 +21,7 @@ #include "libavutil/mem.h" #include "asf.h" #include "demux.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "internal.h" /* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */ @@ -130,11 +130,11 @@ static int get_id3_tag(AVFormatContext *s, int len) { ID3v2ExtraMeta *id3v2_extra_meta; - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); + avformat_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, id3v2_extra_meta); - ff_id3v2_parse_chapters(s, id3v2_extra_meta); - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_parse_apic(s, id3v2_extra_meta); + avformat_id3v2_parse_chapters(s, id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); } return 0; } diff --git a/libavformat/bonk.c b/libavformat/bonk.c index cec89b8c17..fe370b40ef 100644 --- a/libavformat/bonk.c +++ b/libavformat/bonk.c @@ -72,11 +72,11 @@ static int bonk_read_header(AVFormatContext *s) break; } else if (t == MKTAG(' ','I','D','3')) { avio_seek(s->pb, -3, SEEK_CUR); - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &extra_meta, 0); + avformat_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &extra_meta, 0); if (extra_meta) { - ff_id3v2_parse_apic(s, extra_meta); - ff_id3v2_parse_priv(s, extra_meta); - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_parse_apic(s, extra_meta); + avformat_id3v2_parse_priv(s, extra_meta); + avformat_id3v2_free_extra_meta(&extra_meta); } avio_skip(s->pb, 8); } else { diff --git a/libavformat/demux.c b/libavformat/demux.c index a1909237f0..5a19a7dac9 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -317,7 +317,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, /* e.g. AVFMT_NOFILE formats will not have an AVIOContext */ if (s->pb && is_id3v2_format(s->iformat)) - ff_id3v2_read_dict(s->pb, &si->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); + avformat_id3v2_read_dict(s->pb, &si->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); if (ffifmt(s->iformat)->read_header) if ((ret = ffifmt(s->iformat)->read_header(s)) < 0) { @@ -335,13 +335,13 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, } if (id3v2_extra_meta) { - if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0) + if ((ret = avformat_id3v2_parse_apic(s, id3v2_extra_meta)) < 0) goto close; - if ((ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) + if ((ret = avformat_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) goto close; - if ((ret = ff_id3v2_parse_priv(s, id3v2_extra_meta)) < 0) + if ((ret = avformat_id3v2_parse_priv(s, id3v2_extra_meta)) < 0) goto close; - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); } if ((ret = avformat_queue_attached_pictures(s)) < 0) @@ -365,7 +365,7 @@ close: if (ffifmt(s->iformat)->read_close) ffifmt(s->iformat)->read_close(s); fail: - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); av_dict_free(&tmp); if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO)) avio_closep(&s->pb); diff --git a/libavformat/dsfdec.c b/libavformat/dsfdec.c index 87a5fd0272..20a0436910 100644 --- a/libavformat/dsfdec.c +++ b/libavformat/dsfdec.c @@ -56,12 +56,12 @@ static void read_id3(AVFormatContext *s, uint64_t id3pos) if (avio_seek(s->pb, id3pos, SEEK_SET) < 0) return; - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0); + avformat_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, id3v2_extra_meta); - ff_id3v2_parse_chapters(s, id3v2_extra_meta); + avformat_id3v2_parse_apic(s, id3v2_extra_meta); + avformat_id3v2_parse_chapters(s, id3v2_extra_meta); } - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); } static int dsf_read_header(AVFormatContext *s) diff --git a/libavformat/flac_picture.c b/libavformat/flac_picture.c index a81eb71482..347ceae214 100644 --- a/libavformat/flac_picture.c +++ b/libavformat/flac_picture.c @@ -26,7 +26,7 @@ #include "avio_internal.h" #include "demux.h" #include "flac_picture.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "internal.h" #define MAX_TRUNC_PICTURE_SIZE (500 * 1024 * 1024) diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index 711119efec..5159428fd6 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -28,7 +28,7 @@ #include "avformat.h" #include "avio_internal.h" #include "flacenc.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "internal.h" #include "mux.h" #include "version.h" diff --git a/libavformat/format.c b/libavformat/format.c index 83aa980a15..c9451cac6c 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -172,8 +172,8 @@ const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, if (!lpd.buf) lpd.buf = (unsigned char *) zerobuffer; - while (lpd.buf_size > 10 && ff_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) { - int id3len = ff_id3v2_tag_len(lpd.buf); + while (lpd.buf_size > 10 && avformat_id3v2_match(lpd.buf, ID3v2_DEFAULT_MAGIC)) { + int id3len = avformat_id3v2_tag_len(lpd.buf); if (lpd.buf_size > id3len + 16) { if (lpd.buf_size < 2LL*id3len + 16) nodat = ID3_ALMOST_GREATER_PROBE; diff --git a/libavformat/hls.c b/libavformat/hls.c index df13b139f1..25ce59be71 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -275,7 +275,7 @@ static void free_playlist_list(HLSContext *c) av_freep(&pls->renditions); av_freep(&pls->id3_buf); av_dict_free(&pls->id3_initial); - ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); + avformat_id3v2_free_extra_meta(&pls->id3_deferred_extra); av_freep(&pls->init_sec_buf); av_packet_free(&pls->pkt); av_freep(&pls->pb.pub.buffer); @@ -1165,7 +1165,7 @@ static void parse_id3(AVFormatContext *s, AVIOContext *pb, static const char id3_priv_owner_audio_setup[] = "com.apple.streaming.audioDescription"; ID3v2ExtraMeta *meta; - ff_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta); + avformat_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta); for (meta = *extra_meta; meta; meta = meta->next) { if (!strcmp(meta->tag, "PRIV")) { ID3v2ExtraMetaPRIV *priv = &meta->data.priv; @@ -1236,12 +1236,12 @@ static void handle_id3(AVIOContext *pb, struct playlist *pls) /* get picture attachment and set text metadata */ if (pls->ctx->nb_streams) - ff_id3v2_parse_apic(pls->ctx, extra_meta); + avformat_id3v2_parse_apic(pls->ctx, extra_meta); else /* demuxer not yet opened, defer picture attachment */ pls->id3_deferred_extra = extra_meta; - ff_id3v2_parse_priv_dict(&metadata, extra_meta); + avformat_id3v2_parse_priv_dict(&metadata, extra_meta); av_dict_copy(&pls->ctx->metadata, metadata, 0); pls->id3_initial = metadata; @@ -1254,7 +1254,7 @@ static void handle_id3(AVIOContext *pb, struct playlist *pls) } if (!pls->id3_deferred_extra) - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_free_extra_meta(&extra_meta); } static void intercept_id3(struct playlist *pls, uint8_t *buf, @@ -1291,9 +1291,9 @@ static void intercept_id3(struct playlist *pls, uint8_t *buf, if (*len < ID3v2_HEADER_SIZE) break; - if (ff_id3v2_match(buf, ID3v2_DEFAULT_MAGIC)) { + if (avformat_id3v2_match(buf, ID3v2_DEFAULT_MAGIC)) { int64_t maxsize = seg->size >= 0 ? seg->size : 1024*1024; - int taglen = ff_id3v2_tag_len(buf); + int taglen = avformat_id3v2_tag_len(buf); int tag_got_bytes = FFMIN(taglen, *len); int remaining = taglen - tag_got_bytes; @@ -2385,10 +2385,10 @@ static int hls_read_header(AVFormatContext *s) return ret; if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { - ff_id3v2_parse_apic(pls->ctx, pls->id3_deferred_extra); + avformat_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); + avformat_id3v2_parse_priv(pls->ctx, pls->id3_deferred_extra); + avformat_id3v2_free_extra_meta(&pls->id3_deferred_extra); } if (pls->is_id3_timestamped == -1) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 4942b1ffca..3023bb33d2 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -43,7 +43,7 @@ #include "avio_internal.h" #include "demux.h" #include "id3v1.h" -#include "id3v2.h" +#include "id3v2_internal.h" const AVMetadataConv ff_id3v2_34_metadata_conv[] = { { "TALB", "album" }, @@ -146,7 +146,7 @@ const CodecMime ff_id3v2_mime_tags[] = { { "", AV_CODEC_ID_NONE }, }; -int ff_id3v2_match(const uint8_t *buf, const char *magic) +int avformat_id3v2_match(const uint8_t *buf, const char *magic) { return buf[0] == magic[0] && buf[1] == magic[1] && @@ -159,7 +159,7 @@ int ff_id3v2_match(const uint8_t *buf, const char *magic) (buf[9] & 0x80) == 0; } -int ff_id3v2_tag_len(const uint8_t *buf) +int avformat_id3v2_tag_len(const uint8_t *buf) { int len = ((buf[6] & 0x7f) << 21) + ((buf[7] & 0x7f) << 14) + @@ -1122,7 +1122,7 @@ static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata, avio_seek(pb, off, SEEK_SET); break; } - found_header = ff_id3v2_match(buf, magic); + found_header = avformat_id3v2_match(buf, magic); if (found_header) { /* parse ID3v2 header */ len = ((buf[6] & 0x7f) << 21) | @@ -1143,19 +1143,19 @@ static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata, *extra_metap = extra_meta.head; } -void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, +void avformat_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, +void avformat_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) +void avformat_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta) { ID3v2ExtraMeta *current = *extra_meta, *next; const ID3v2EMFunc *extra_func; @@ -1171,7 +1171,7 @@ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta) *extra_meta = NULL; } -int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) +int avformat_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) { ID3v2ExtraMeta *cur; @@ -1202,7 +1202,7 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) return 0; } -int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *cur) +int avformat_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *cur) { AVRational time_base = {1, 1000}; int ret; @@ -1227,7 +1227,8 @@ int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *cur) return 0; } -int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta *extra_meta) +int avformat_id3v2_parse_priv_dict(AVDictionary **metadata, + ID3v2ExtraMeta *extra_meta) { ID3v2ExtraMeta *cur; int dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL; @@ -1267,7 +1268,7 @@ int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta *extra_meta return 0; } -int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) +int avformat_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) { - return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta); + return avformat_id3v2_parse_priv_dict(&s->metadata, extra_meta); } diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index 9afa5a2ddc..a49705efab 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -24,8 +24,6 @@ #include <stdint.h> #include "avformat.h" -#include "internal.h" -#include "metadata.h" #define ID3v2_HEADER_SIZE 10 @@ -34,26 +32,8 @@ */ #define ID3v2_DEFAULT_MAGIC "ID3" -#define ID3v2_FLAG_DATALEN 0x0001 -#define ID3v2_FLAG_UNSYNCH 0x0002 -#define ID3v2_FLAG_ENCRYPTION 0x0004 -#define ID3v2_FLAG_COMPRESSION 0x0008 - #define ID3v2_PRIV_METADATA_PREFIX "id3v2_priv." -enum ID3v2Encoding { - ID3v2_ENCODING_ISO8859 = 0, - ID3v2_ENCODING_UTF16BOM = 1, - ID3v2_ENCODING_UTF16BE = 2, - ID3v2_ENCODING_UTF8 = 3, -}; - -typedef struct ID3v2EncContext { - int version; ///< ID3v2 minor version, either 3 or 4 - int64_t size_pos; ///< offset of the tag total size - int len; ///< size of the tag written so far -} ID3v2EncContext; - typedef struct ID3v2ExtraMetaGEOB { uint32_t datasize; uint8_t *mime_type; @@ -98,23 +78,26 @@ typedef struct ID3v2ExtraMeta { * @param magic magic bytes to identify the header. * If in doubt, use ID3v2_DEFAULT_MAGIC. */ -int ff_id3v2_match(const uint8_t *buf, const char *magic); +int avformat_id3v2_match(const uint8_t *buf, const char *magic); /** * Get the length of an ID3v2 tag. * @param buf must be ID3v2_HEADER_SIZE bytes long and point to the start of an * already detected ID3v2 tag */ -int ff_id3v2_tag_len(const uint8_t *buf); +int avformat_id3v2_tag_len(const uint8_t *buf); /** - * Read an ID3v2 tag into specified dictionary and retrieve supported extra metadata. + * Read an ID3v2 tag into specified dictionary and retrieve supported + * extra metadata. * * @param metadata Parsed metadata is stored here - * @param[out] extra_meta If not NULL, extra metadata is parsed into a list of - * ID3v2ExtraMeta structs and *extra_meta points to the head of the list + * @param[out] extra_meta If not NULL, extra metadata is parsed into a + * list of ID3v2ExtraMeta structs and *extra_meta points to the head */ -void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, const char *magic, ID3v2ExtraMeta **extra_meta); +void avformat_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, + const char *magic, + ID3v2ExtraMeta **extra_meta); /** * Read an ID3v2 tag, including supported extra metadata. @@ -123,92 +106,44 @@ void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, const char *ma * * @param[out] extra_meta If not NULL, extra metadata is parsed into a list of * ID3v2ExtraMeta structs and *extra_meta points to the head of the list - * @param[opt] max_search_search restrict ID3 magic number search (bytes from start) + * @param[opt] max_search_size restrict ID3 magic number search + * (bytes from start) */ -void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta, - unsigned int max_search_size); - -/** - * Initialize an ID3v2 tag. - */ -void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, - const char *magic); - -/** - * Convert and write all global metadata from s into an ID3v2 tag. - */ -int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3); - -/** - * Write an attached picture from pkt into an ID3v2 tag. - */ -int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt); - -/** - * Finalize an opened ID3v2 tag. - */ -void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes); - -/** - * Write an ID3v2 tag containing all global metadata from s. - * @param id3v2_version Subversion of ID3v2; supported values are 3 and 4 - * @param magic magic bytes to identify the header - * If in doubt, use ID3v2_DEFAULT_MAGIC. - */ -int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, const char *magic); +void avformat_id3v2_read(AVFormatContext *s, const char *magic, + ID3v2ExtraMeta **extra_meta, + unsigned int max_search_size); /** * Free memory allocated parsing special (non-text) metadata. - * @param extra_meta Pointer to a pointer to the head of a ID3v2ExtraMeta list, *extra_meta is set to NULL. + * @param extra_meta Pointer to a pointer to the head of a ID3v2ExtraMeta + * list, *extra_meta is set to NULL. */ -void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta); +void avformat_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta); /** * Create a stream for each APIC (attached picture) extracted from the * ID3v2 header. */ -int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); +int avformat_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); /** * Create chapters for all CHAP tags found in the ID3v2 header. */ -int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); +int avformat_id3v2_parse_chapters(AVFormatContext *s, + ID3v2ExtraMeta *extra_meta); /** * Parse PRIV tags into a dictionary. The PRIV owner is the metadata key. The * PRIV data is the value, with non-printable characters escaped. */ -int ff_id3v2_parse_priv_dict(AVDictionary **d, ID3v2ExtraMeta *extra_meta); +int avformat_id3v2_parse_priv_dict(AVDictionary **d, + ID3v2ExtraMeta *extra_meta); /** * Add metadata for all PRIV tags in the ID3v2 header. The PRIV owner is the * metadata key. The PRIV data is the value, with non-printable characters * escaped. */ -int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); - -extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; -extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; - -/** - * A list of text information frames allowed in both ID3 v2.3 and v2.4 - * http://www.id3.org/id3v2.4.0-frames - * http://www.id3.org/id3v2.4.0-changes - */ -extern const char ff_id3v2_tags[][4]; - -/** - * ID3v2.4-only text information frames. - */ -extern const char ff_id3v2_4_tags[][4]; - -/** - * ID3v2.3-only text information frames. - */ -extern const char ff_id3v2_3_tags[][4]; - -extern const CodecMime ff_id3v2_mime_tags[]; - -extern const char * const ff_id3v2_picture_types[21]; +int avformat_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); #endif /* AVFORMAT_ID3V2_H */ diff --git a/libavformat/id3v2_internal.h b/libavformat/id3v2_internal.h new file mode 100644 index 0000000000..7de661ad91 --- /dev/null +++ b/libavformat/id3v2_internal.h @@ -0,0 +1,102 @@ +/* + * ID3v2 header parser - internal declarations + * Copyright (c) 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_ID3V2_INTERNAL_H +#define AVFORMAT_ID3V2_INTERNAL_H + +#include "id3v2.h" +#include "internal.h" +#include "metadata.h" + +#define ID3v2_FLAG_DATALEN 0x0001 +#define ID3v2_FLAG_UNSYNCH 0x0002 +#define ID3v2_FLAG_ENCRYPTION 0x0004 +#define ID3v2_FLAG_COMPRESSION 0x0008 + +enum ID3v2Encoding { + ID3v2_ENCODING_ISO8859 = 0, + ID3v2_ENCODING_UTF16BOM = 1, + ID3v2_ENCODING_UTF16BE = 2, + ID3v2_ENCODING_UTF8 = 3, +}; + +typedef struct ID3v2EncContext { + int version; ///< ID3v2 minor version, either 3 or 4 + int64_t size_pos; ///< offset of the tag total size + int len; ///< size of the tag written so far +} ID3v2EncContext; + +/** + * Initialize an ID3v2 tag. + */ +void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, + const char *magic); + +/** + * Convert and write all global metadata from s into an ID3v2 tag. + */ +int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3); + +/** + * Write an attached picture from pkt into an ID3v2 tag. + */ +int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, + AVPacket *pkt); + +/** + * Finalize an opened ID3v2 tag. + */ +void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes); + +/** + * Write an ID3v2 tag containing all global metadata from s. + * @param id3v2_version Subversion of ID3v2; supported values are 3 and 4 + * @param magic magic bytes to identify the header + * If in doubt, use ID3v2_DEFAULT_MAGIC. + */ +int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, + const char *magic); + +extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; +extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; + +/** + * A list of text information frames allowed in both ID3 v2.3 and v2.4 + * http://www.id3.org/id3v2.4.0-frames + * http://www.id3.org/id3v2.4.0-changes + */ +extern const char ff_id3v2_tags[][4]; + +/** + * ID3v2.4-only text information frames. + */ +extern const char ff_id3v2_4_tags[][4]; + +/** + * ID3v2.3-only text information frames. + */ +extern const char ff_id3v2_3_tags[][4]; + +extern const CodecMime ff_id3v2_mime_tags[]; + +extern const char * const ff_id3v2_picture_types[21]; + +#endif /* AVFORMAT_ID3V2_INTERNAL_H */ diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index ac907c2758..480d3204c2 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -27,7 +27,7 @@ #include "avformat.h" #include "avio.h" #include "avio_internal.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "mux.h" static void id3v2_put_size(AVIOContext *pb, int size) diff --git a/libavformat/iff.c b/libavformat/iff.c index 8dccd58b35..c1b4bc43e5 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -323,14 +323,14 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof) break; case MKTAG('I','D','3',' '): - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); + avformat_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); if (id3v2_extra_meta) { - if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 || - (ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) { - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + if ((ret = avformat_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 || + (ret = avformat_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) { + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); return ret; } - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); } if (size < avio_tell(pb) - orig_pos) { diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index 5b153c7c9e..9114278219 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -122,7 +122,7 @@ static int mp3_read_probe(const AVProbeData *p) if (first_frames>=7) return AVPROBE_SCORE_EXTENSION + 1; else if (max_frames>200 && p->buf_size < 2*max_framesizes)return AVPROBE_SCORE_EXTENSION; else if (max_frames>=4 && p->buf_size < 2*max_framesizes) return AVPROBE_SCORE_EXTENSION / 2; - else if (ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size) + else if (avformat_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*avformat_id3v2_tag_len(buf0) >= p->buf_size) return p->buf_size < PROBE_BUF_MAX ? AVPROBE_SCORE_EXTENSION / 4 : AVPROBE_SCORE_EXTENSION - 2; else if (first_frames > 1 && whole_used) return 5; else if (max_frames>=1 && p->buf_size < 10*max_framesizes) return 1; diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 724c7269dc..3928ca829d 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -22,7 +22,7 @@ #include "avformat.h" #include "avio_internal.h" #include "id3v1.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "mux.h" #include "rawenc.h" #include "libavutil/avstring.h" diff --git a/libavformat/omadec.c b/libavformat/omadec.c index 552a37df18..70db704b6a 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -414,21 +414,21 @@ static int oma_read_header(AVFormatContext *s) ID3v2ExtraMeta *extra_meta; OMAContext *oc = s->priv_data; - ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta, 0); - if ((ret = ff_id3v2_parse_chapters(s, extra_meta)) < 0) { - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta, 0); + if ((ret = avformat_id3v2_parse_chapters(s, extra_meta)) < 0) { + avformat_id3v2_free_extra_meta(&extra_meta); return ret; } ret = avio_read(s->pb, buf, EA3_HEADER_SIZE); if (ret < EA3_HEADER_SIZE) { - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_free_extra_meta(&extra_meta); return -1; } if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}), 3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_free_extra_meta(&extra_meta); av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); return AVERROR_INVALIDDATA; } @@ -438,11 +438,11 @@ static int oma_read_header(AVFormatContext *s) /* encrypted file */ eid = AV_RB16(&buf[6]); if (eid != -1 && eid != -128 && decrypt_init(s, extra_meta, buf) < 0) { - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_free_extra_meta(&extra_meta); return -1; } - ff_id3v2_free_extra_meta(&extra_meta); + avformat_id3v2_free_extra_meta(&extra_meta); codec_params = AV_RB24(&buf[33]); @@ -562,8 +562,8 @@ static int oma_read_probe(const AVProbeData *p) const uint8_t *buf = p->buf; unsigned tag_len = 0; - if (p->buf_size >= ID3v2_HEADER_SIZE && ff_id3v2_match(buf, ID3v2_EA3_MAGIC)) - tag_len = ff_id3v2_tag_len(buf); + if (p->buf_size >= ID3v2_HEADER_SIZE && avformat_id3v2_match(buf, ID3v2_EA3_MAGIC)) + tag_len = avformat_id3v2_tag_len(buf); /* This check cannot overflow as tag_len has at most 28 bits */ if (p->buf_size < tag_len + 5) diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c index b553bc3e9d..d71c8a2347 100644 --- a/libavformat/omaenc.c +++ b/libavformat/omaenc.c @@ -22,7 +22,7 @@ #include "avformat.h" #include "avio_internal.h" -#include "id3v2.h" +#include "id3v2_internal.h" #include "internal.h" #include "mux.h" #include "oma.h" diff --git a/libavformat/version.h b/libavformat/version.h index ff831498b3..14bf700274 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,8 +31,8 @@ #include "version_major.h" -#define LIBAVFORMAT_VERSION_MINOR 13 -#define LIBAVFORMAT_VERSION_MICRO 102 +#define LIBAVFORMAT_VERSION_MINOR 14 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index f56f9d5c59..2e5d98c7a0 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -565,13 +565,13 @@ static int wav_read_header(AVFormatContext *s) case MKTAG('I', 'D', '3', ' '): case MKTAG('i', 'd', '3', ' '): { ID3v2ExtraMeta *id3v2_extra_meta; - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0); + avformat_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, id3v2_extra_meta); - ff_id3v2_parse_chapters(s, id3v2_extra_meta); - ff_id3v2_parse_priv(s, id3v2_extra_meta); + avformat_id3v2_parse_apic(s, id3v2_extra_meta); + avformat_id3v2_parse_chapters(s, id3v2_extra_meta); + avformat_id3v2_parse_priv(s, id3v2_extra_meta); } - ff_id3v2_free_extra_meta(&id3v2_extra_meta); + avformat_id3v2_free_extra_meta(&id3v2_extra_meta); } break; case MKTAG('c', 'u', 'e', ' '): -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
