From 191e34cd67e46e125782073283346fda459d2146 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 11 Aug 2009 17:08:09 +0000 Subject: [PATCH] Move APE tag parsing into separate module. Based on patch by Matti Hamalainen (mhamalaistudentsoamk) Originally committed as revision 19629 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/Makefile | 2 +- libavformat/ape.c | 100 +---------------------------------- libavformat/apetag.c | 122 +++++++++++++++++++++++++++++++++++++++++++ libavformat/apetag.h | 33 ++++++++++++ 4 files changed, 158 insertions(+), 99 deletions(-) create mode 100644 libavformat/apetag.c create mode 100644 libavformat/apetag.h diff --git a/libavformat/Makefile b/libavformat/Makefile index 7280c77f2f..10b8fbeadf 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -17,7 +17,7 @@ OBJS-$(CONFIG_AIFF_MUXER) += aiff.o riff.o OBJS-$(CONFIG_AMR_DEMUXER) += amr.o OBJS-$(CONFIG_AMR_MUXER) += amr.o OBJS-$(CONFIG_APC_DEMUXER) += apc.o -OBJS-$(CONFIG_APE_DEMUXER) += ape.o +OBJS-$(CONFIG_APE_DEMUXER) += ape.o apetag.o OBJS-$(CONFIG_ASF_DEMUXER) += asfdec.o asf.o asfcrypt.o riff.o avlanguage.o OBJS-$(CONFIG_ASF_MUXER) += asfenc.o asf.o riff.o OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o diff --git a/libavformat/ape.c b/libavformat/ape.c index 02fd4fa1d1..cc2e657b99 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -24,6 +24,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "apetag.h" #define ENABLE_DEBUG 0 @@ -42,12 +43,6 @@ #define APE_EXTRADATA_SIZE 6 -/* APE tags */ -#define APE_TAG_VERSION 2000 -#define APE_TAG_FOOTER_BYTES 32 -#define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31) -#define APE_TAG_FLAG_IS_HEADER (1 << 29) - typedef struct { int64_t pos; int nblocks; @@ -91,97 +86,6 @@ typedef struct { uint32_t *seektable; } APEContext; -static int ape_tag_read_field(AVFormatContext *s) -{ - ByteIOContext *pb = s->pb; - uint8_t key[1024], value[1024]; - uint32_t size, flags; - int i, l, c; - - size = get_le32(pb); /* field size */ - flags = get_le32(pb); /* field flags */ - for (i = 0; i < sizeof(key) - 1; i++) { - c = get_byte(pb); - if (c < 0x20 || c > 0x7E) - break; - else - key[i] = c; - } - key[i] = 0; - if (c != 0) { - av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key); - return -1; - } - l = FFMIN(size, sizeof(value)-1); - get_buffer(pb, value, l); - value[l] = 0; - url_fskip(pb, size-l); - if (l < size) - av_log(s, AV_LOG_WARNING, "Too long '%s' tag was truncated.\n", key); - av_metadata_set(&s->metadata, key, value); - return 0; -} - -static void ape_parse_tag(AVFormatContext *s) -{ - ByteIOContext *pb = s->pb; - int file_size = url_fsize(pb); - uint32_t val, fields, tag_bytes; - uint8_t buf[8]; - int i; - - if (file_size < APE_TAG_FOOTER_BYTES) - return; - - url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET); - - get_buffer(pb, buf, 8); /* APETAGEX */ - if (strncmp(buf, "APETAGEX", 8)) { - return; - } - - val = get_le32(pb); /* APE tag version */ - if (val > APE_TAG_VERSION) { - av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION); - return; - } - - tag_bytes = get_le32(pb); /* tag size */ - if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) { - av_log(s, AV_LOG_ERROR, "Tag size is way too big\n"); - return; - } - - fields = get_le32(pb); /* number of fields */ - if (fields > 65536) { - av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields); - return; - } - - val = get_le32(pb); /* flags */ - if (val & APE_TAG_FLAG_IS_HEADER) { - av_log(s, AV_LOG_ERROR, "APE Tag is a header\n"); - return; - } - - url_fseek(pb, file_size - tag_bytes, SEEK_SET); - - for (i=0; ititle); - av_log(s, AV_LOG_DEBUG, "author = %s\n", s->author); - av_log(s, AV_LOG_DEBUG, "copyright = %s\n", s->copyright); - av_log(s, AV_LOG_DEBUG, "comment = %s\n", s->comment); - av_log(s, AV_LOG_DEBUG, "album = %s\n", s->album); - av_log(s, AV_LOG_DEBUG, "year = %d\n", s->year); - av_log(s, AV_LOG_DEBUG, "track = %d\n", s->track); - av_log(s, AV_LOG_DEBUG, "genre = %s\n", s->genre); -#endif -} - static int ape_probe(AVProbeData * p) { if (p->buf[0] == 'M' && p->buf[1] == 'A' && p->buf[2] == 'C' && p->buf[3] == ' ') @@ -384,7 +288,7 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) /* try to read APE tags */ if (!url_is_streamed(pb)) { - ape_parse_tag(s); + ff_ape_parse_tag(s); url_fseek(pb, 0, SEEK_SET); } diff --git a/libavformat/apetag.c b/libavformat/apetag.c new file mode 100644 index 0000000000..435dd3fdcf --- /dev/null +++ b/libavformat/apetag.c @@ -0,0 +1,122 @@ +/* + * APE tag handling + * Copyright (c) 2007 Benjamin Zores + * based upon libdemac from Dave Chapman. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" + +#define ENABLE_DEBUG 0 + +#define APE_TAG_VERSION 2000 +#define APE_TAG_FOOTER_BYTES 32 +#define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31) +#define APE_TAG_FLAG_IS_HEADER (1 << 29) + +static int ape_tag_read_field(AVFormatContext *s) +{ + ByteIOContext *pb = s->pb; + uint8_t key[1024], value[1024]; + uint32_t size, flags; + int i, l, c; + + size = get_le32(pb); /* field size */ + flags = get_le32(pb); /* field flags */ + for (i = 0; i < sizeof(key) - 1; i++) { + c = get_byte(pb); + if (c < 0x20 || c > 0x7E) + break; + else + key[i] = c; + } + key[i] = 0; + if (c != 0) { + av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key); + return -1; + } + l = FFMIN(size, sizeof(value)-1); + get_buffer(pb, value, l); + value[l] = 0; + url_fskip(pb, size-l); + if (l < size) + av_log(s, AV_LOG_WARNING, "Too long '%s' tag was truncated.\n", key); + av_metadata_set(&s->metadata, key, value); + return 0; +} + +void ff_ape_parse_tag(AVFormatContext *s) +{ + ByteIOContext *pb = s->pb; + int file_size = url_fsize(pb); + uint32_t val, fields, tag_bytes; + uint8_t buf[8]; + int i; + + if (file_size < APE_TAG_FOOTER_BYTES) + return; + + url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET); + + get_buffer(pb, buf, 8); /* APETAGEX */ + if (strncmp(buf, "APETAGEX", 8)) { + return; + } + + val = get_le32(pb); /* APE tag version */ + if (val > APE_TAG_VERSION) { + av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION); + return; + } + + tag_bytes = get_le32(pb); /* tag size */ + if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) { + av_log(s, AV_LOG_ERROR, "Tag size is way too big\n"); + return; + } + + fields = get_le32(pb); /* number of fields */ + if (fields > 65536) { + av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields); + return; + } + + val = get_le32(pb); /* flags */ + if (val & APE_TAG_FLAG_IS_HEADER) { + av_log(s, AV_LOG_ERROR, "APE Tag is a header\n"); + return; + } + + url_fseek(pb, file_size - tag_bytes, SEEK_SET); + + for (i=0; ititle); + av_log(s, AV_LOG_DEBUG, "author = %s\n", s->author); + av_log(s, AV_LOG_DEBUG, "copyright = %s\n", s->copyright); + av_log(s, AV_LOG_DEBUG, "comment = %s\n", s->comment); + av_log(s, AV_LOG_DEBUG, "album = %s\n", s->album); + av_log(s, AV_LOG_DEBUG, "year = %d\n", s->year); + av_log(s, AV_LOG_DEBUG, "track = %d\n", s->track); + av_log(s, AV_LOG_DEBUG, "genre = %s\n", s->genre); +#endif +} diff --git a/libavformat/apetag.h b/libavformat/apetag.h new file mode 100644 index 0000000000..8aaef68c38 --- /dev/null +++ b/libavformat/apetag.h @@ -0,0 +1,33 @@ +/* + * APE tag handling + * Copyright (c) 2007 Benjamin Zores + * based upon libdemac from Dave Chapman. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_APETAG_H +#define AVFORMAT_APETAG_H + +#include "avformat.h" + +/** + * Read and parse an APE tag + */ +void ff_ape_parse_tag(AVFormatContext *s); + +#endif /* AVFORMAT_ID3V2_H */