From: softworkz <ffmpegagent@gmail.com> To: ffmpeg-devel@ffmpeg.org Cc: softworkz <softworkz@hotmail.com> Subject: [FFmpeg-devel] [PATCH] avformat/id3v2: Support null-separated multi-value properties Date: Sat, 01 Mar 2025 23:57:29 +0000 Message-ID: <pull.54.ffstaging.FFmpeg.1740873449247.ffmpegagent@gmail.com> (raw) From: softworkz <softworkz@hotmail.com> Fixes Trac ticket https://trac.ffmpeg.org/ticket/6949 Signed-off-by: softworkz <softworkz@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2025-03-01 23:57 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=pull.54.ffstaging.FFmpeg.1740873449247.ffmpegagent@gmail.com \ --to=ffmpegagent@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ --cc=softworkz@hotmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git