[FFmpeg-devel] Subject: [PATCH] Process compressed id3v2 tags.

Clément Bœsch ubitux at gmail.com
Fri Dec 2 10:39:27 CET 2011


On Thu, Dec 01, 2011 at 09:50:48PM -0800, Adrian Drzewiecki wrote:
> ID3v2.4 allows for zlib compressed tags, but libavformat skips them.
> Implement code to inflate compressed tags.
> ---
>  libavformat/id3v2.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++----
>  1 files changed, 89 insertions(+), 8 deletions(-)
> 
> diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
> index bb8819f..651b1db 100644
> --- a/libavformat/id3v2.c
> +++ b/libavformat/id3v2.c
> @@ -33,6 +33,8 @@
>  #include "libavutil/dict.h"
>  #include "avio_internal.h"
> 
> +#include <zlib.h>
> +

System header before internals one.

>  const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
>      { "TALB", "album"},
>      { "TCOM", "composer"},
> @@ -419,6 +421,16 @@ static const ID3v2EMFunc
> *get_extra_meta_func(const char *tag, int isv34)
>      return &id3v2_extra_meta_funcs[i];
>  }
> 
> +static void *ff_id3v2_zalloc(void *opaque, unsigned int items,
> unsigned int size)
> +{
> +    return av_malloc(items * size);
> +}
> +
> +static void ff_id3v2_zfree(void *opaque, void *ptr)
> +{
> +    av_free(ptr);
> +}
> +
>  static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t
> version, uint8_t flags, ID3v2ExtraMeta **extra_meta)
>  {
>      int isv34, unsync;
> @@ -476,6 +488,8 @@ static void ff_id3v2_parse(AVFormatContext *s, int
> len, uint8_t version, uint8_t
>      while (len >= taghdrlen) {
>          unsigned int tflags = 0;
>          int tunsync = 0;
> +	int tcomp = 0;
> +	int dlen;

Please don't use tabs.

> 
>          if (isv34) {
>              avio_read(s->pb, tag, 4);
> @@ -509,24 +523,91 @@ static void ff_id3v2_parse(AVFormatContext *s,
> int len, uint8_t version, uint8_t
>          if (tflags & ID3v2_FLAG_DATALEN) {
>              if (tlen < 4)
>                  break;
> -            avio_rb32(s->pb);
> +            dlen = avio_rb32(s->pb);
>              tlen -= 4;
> -        }
> +        } else
> +            dlen = tlen;
> +
> +	tcomp = tflags & ID3v2_FLAG_COMPRESSION;

ditto tabs

> 
> -        if (tflags & (ID3v2_FLAG_ENCRYPTION | ID3v2_FLAG_COMPRESSION)) {
> -            av_log(s, AV_LOG_WARNING, "Skipping encrypted/compressed
> ID3v2 frame %s.\n", tag);
> +        if (tflags & ID3v2_FLAG_ENCRYPTION) {
> +            av_log(s, AV_LOG_WARNING, "Skipping encrypted ID3v2 frame
> %s.\n", tag);
>              avio_skip(s->pb, tlen);
>          /* check for text tag or supported special meta tag */
>          } else if (tag[0] == 'T' || (extra_meta && (extra_func =
> get_extra_meta_func(tag, isv34)))) {
> -            if (unsync || tunsync) {
> +            if (unsync || tunsync || tcomp) {
>                  int i, j;
> -                av_fast_malloc(&buffer, &buffer_size, tlen);
> +                av_fast_malloc(&buffer, &buffer_size, dlen);
>                  if (!buffer) {
>                      av_log(s, AV_LOG_ERROR, "Failed to alloc %d
> bytes\n", tlen);
>                      goto seek;
>                  }
> -                for (i = 0, j = 0; i < tlen; i++, j++) {
> -                    buffer[j] = avio_r8(s->pb);
> +                if (tcomp) {
> +                    z_stream zstrm;
> +                    int err;
> +
> +                    av_log(s, AV_LOG_INFO, "Compresssed frame %s
> tlen=%d dlen=%d\n", tag, tlen, dlen);

Too much 's'. I wonder if AV_LOG_INFO is appropriate here too.

> +
> +                    zstrm.next_in = NULL;
> +                    zstrm.avail_in = 0;
> +                    zstrm.zalloc = ff_id3v2_zalloc;
> +                    zstrm.zfree = ff_id3v2_zfree;
> +                    zstrm.next_out = buffer;
> +                    zstrm.avail_out = buffer_size;
> +

z_stream zstrm = {
    .zalloc    = ff_id3v2_zalloc,
    .zfree     = ff_id3v2_zalloc,
    .next_out  = buffer,
    .avail_out = buffer_size,
};

> +                    err = inflateInit(&zstrm);
> +                    if (err != Z_OK) {
> +                        av_log(s, AV_LOG_ERROR, "inflate init failed:
> %d\n", err);
> +                        goto seek;
> +                    }
> +
> +                    for (;;) {
> +                        char buf[4096];
> +                        int n, end;
> +
> +                        n = sizeof *buf;
> +                        if (n > tlen)
> +                            n = tlen;
> +

FFMIN()?

[...]

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20111202/9abd6a0c/attachment.asc>


More information about the ffmpeg-devel mailing list