Skip to content

Conversation

@softworkz
Copy link
Collaborator

@softworkz
Copy link
Collaborator Author

/submit

@ffmpeg-codebot
Copy link

ffmpeg-codebot bot commented Mar 1, 2025

Submitted as [email protected]

To fetch this version into FETCH_HEAD:

git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-54/softworkz/submit_id3v2-v1

To fetch this version to local tag pr-ffstaging-54/softworkz/submit_id3v2-v1:

git fetch --no-tags https://github.com/ffstaging/FFmpeg tag pr-ffstaging-54/softworkz/submit_id3v2-v1

@ffmpeg-codebot
Copy link

On the FFmpeg mailing list, Soft Works wrote (reply to this):



> -----Original Message-----
> From: softworkz <[email protected]>
> Sent: Sonntag, 2. März 2025 00:57
> To: [email protected]
> Cc: softworkz <[email protected]>; softworkz <[email protected]>
> Subject: [PATCH] avformat/id3v2: Support null-separated multi-value
> properties
> 
> From: softworkz <[email protected]>
> 
> Fixes Trac ticket https://trac.ffmpeg.org/ticket/6949
> 
> Signed-off-by: softworkz <[email protected]>
> ---
>     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
[email protected]
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
[email protected] with subject "unsubscribe".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant