> -----Original Message----- > From: softworkz <ffmpegag...@gmail.com> > Sent: Sonntag, 2. März 2025 00:57 > To: ffmpeg-devel@ffmpeg.org > Cc: softworkz <softwo...@hotmail.com>; softworkz <softwo...@hotmail.com> > Subject: [PATCH] avformat/id3v2: Support null-separated multi-value > properties > > From: softworkz <softwo...@hotmail.com> > > Fixes Trac ticket https://trac.ffmpeg.org/ticket/6949 > > Signed-off-by: softworkz <softwo...@hotmail.com> > --- > avformat/id3v2: Support null-separated multi-value properties > > Fixes Trac ticket https://trac.ffmpeg.org/ticket/6949 > > Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr- > ffstaging-54%2Fsoftworkz%2Fsubmit_id3v2-v1 > Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr- > ffstaging-54/softworkz/submit_id3v2-v1 > Pull-Request: https://github.com/ffstaging/FFmpeg/pull/54 > > libavformat/id3v2.c | 65 ++++++++++++++++++++++++++++----------------- > 1 file changed, 41 insertions(+), 24 deletions(-) > > diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c > index 29ee59e1f4..cebb4acd75 100644 > --- a/libavformat/id3v2.c > +++ b/libavformat/id3v2.c > @@ -327,39 +327,55 @@ static void read_ttag(AVFormatContext *s, > AVIOContext *pb, int taglen, > AVDictionary **metadata, const char *key) > { > uint8_t *dst; > - int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | > AV_DICT_DONT_STRDUP_VAL; > + int encoding, nb_values = 0; > unsigned genre; > + AVDictionaryEntry *tag = NULL; > > if (taglen < 1) > return; > > + tag = av_dict_get(*metadata, key, NULL, 0); > + if (tag) > + return; > + > encoding = avio_r8(pb); > taglen--; /* account for encoding type byte */ > > - if (decode_str(s, pb, encoding, &dst, &taglen) < 0) { > - av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", > key); > - return; > - } > + /* Read all null-terminated values */ > + while (taglen > 0) { > + int n = 0, dict_flags = AV_DICT_APPEND | > AV_DICT_DONT_STRDUP_VAL; > > - if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) > && > - (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]); > - } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) { > - /* dst now contains the key, need to get value */ > - key = dst; > if (decode_str(s, pb, encoding, &dst, &taglen) < 0) { > av_log(s, AV_LOG_ERROR, "Error reading frame %s, > skipped\n", key); > - av_freep(&key); > return; > } > - dict_flags |= AV_DICT_DONT_STRDUP_KEY; > - } else if (!*dst) > - av_freep(&dst); > > - if (dst) > - av_dict_set(metadata, key, dst, dict_flags); > + if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) && > + (sscanf(dst, "(%d)", &genre) == 1 || (sscanf(dst, "%d%n", > &genre, &n) == 1 && n == strlen(dst))) && > + genre <= ID3v1_GENRE_MAX) { > + av_freep(&dst); > + 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; > + if (decode_str(s, pb, encoding, &dst, &taglen) < 0) { > + av_log(s, AV_LOG_ERROR, "Error reading frame %s, > skipped\n", key); > + av_freep(&key); > + return; > + } > + } else if (!*dst) { > + av_freep(&dst); > + return; > + } > + > + if (dst) { > + if (nb_values > 0) > + av_dict_set(metadata, key, ";", dict_flags & > ~AV_DICT_DONT_STRDUP_VAL); > + > + av_dict_set(metadata, key, dst, dict_flags); > + nb_values++; > + } > + } > } > > static void read_uslt(AVFormatContext *s, AVIOContext *pb, int taglen, > @@ -372,7 +388,7 @@ static void read_uslt(AVFormatContext *s, > AVIOContext *pb, int taglen, > int encoding; > int ok = 0; > > - if (taglen < 4) > + if (taglen < 1) > goto error; > > encoding = avio_r8(pb); > @@ -383,10 +399,10 @@ static void read_uslt(AVFormatContext *s, > AVIOContext *pb, int taglen, > lang[3] = '\0'; > taglen -= 3; > > - if (decode_str(s, pb, encoding, &descriptor, &taglen) < 0 || taglen > < 0) > + if (decode_str(s, pb, encoding, &descriptor, &taglen) < 0) > goto error; > > - if (decode_str(s, pb, encoding, &text, &taglen) < 0 || taglen < 0) > + if (decode_str(s, pb, encoding, &text, &taglen) < 0) > goto error; > > // FFmpeg does not support hierarchical metadata, so concatenate > the keys. > @@ -1003,7 +1019,8 @@ static void id3v2_parse(AVIOContext *pb, > AVDictionary **metadata, > t++; > } > > - ffio_init_read_context(&pb_local, buffer, b - buffer); > + ffio_init_context(&pb_local, buffer, b - buffer, 0, > NULL, NULL, NULL, > + NULL); > tlen = b - buffer; > pbx = &pb_local.pub; // read from sync buffer > } > @@ -1039,7 +1056,7 @@ static void id3v2_parse(AVIOContext *pb, > AVDictionary **metadata, > av_log(s, AV_LOG_ERROR, "Failed to uncompress > tag: %d\n", err); > goto seek; > } > - ffio_init_read_context(&pb_local, > uncompressed_buffer, dlen); > + ffio_init_context(&pb_local, uncompressed_buffer, > dlen, 0, NULL, NULL, NULL, NULL); > tlen = dlen; > pbx = &pb_local.pub; // read from sync buffer > } > > base-commit: 0e7c2a6287f977c30e08e2a211385c6a80614fe8 > -- > ffmpeg-codebot
Is there any maintainer for avformat/id3v2 or somebody who would be able to review this? Thanks sw _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".