[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