From 12bc20502ad9124b4d922985b82edc45aa4064cb Mon Sep 17 00:00:00 2001 From: Victor Vasiliev Date: Fri, 25 Nov 2011 00:02:43 +0400 Subject: Generalize RIFF INFO tag support; support reading INFO tag in wav Signed-off-by: Ronald S. Bultje --- libavformat/Makefile | 4 ++-- libavformat/avi.c | 45 ---------------------------------- libavformat/avi.h | 9 ------- libavformat/avidec.c | 19 +++++++-------- libavformat/avienc.c | 6 ++--- libavformat/riff.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/riff.h | 6 +++++ libavformat/wav.c | 18 +++++++++++--- 8 files changed, 102 insertions(+), 73 deletions(-) delete mode 100644 libavformat/avi.c (limited to 'libavformat') diff --git a/libavformat/Makefile b/libavformat/Makefile index 3419148b56..64b2d823ed 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -39,8 +39,8 @@ OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o OBJS-$(CONFIG_ASS_MUXER) += assenc.o OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o OBJS-$(CONFIG_AU_MUXER) += au.o -OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o avi.o -OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o avi.o +OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o +OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o OBJS-$(CONFIG_AVISYNTH) += avisynth.o OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o diff --git a/libavformat/avi.c b/libavformat/avi.c deleted file mode 100644 index 9f36b27f35..0000000000 --- a/libavformat/avi.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * AVI common data - * Copyright (c) 2010 Anton Khirnov - * - * This file is part of Libav. - * - * Libav 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. - * - * Libav 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "avi.h" - -const AVMetadataConv ff_avi_metadata_conv[] = { - { "IART", "artist" }, - { "ICMT", "comment" }, - { "ICOP", "copyright" }, - { "ICRD", "date" }, - { "IGNR", "genre" }, - { "ILNG", "language" }, - { "INAM", "title" }, - { "IPRD", "album" }, - { "IPRT", "track" }, - { "ISFT", "encoder" }, - { "ITCH", "encoded_by"}, - { "strn", "title" }, - { 0 }, -}; - -const char ff_avi_tags[][5] = { - "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI", - "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD", - "IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH", - {0} -}; diff --git a/libavformat/avi.h b/libavformat/avi.h index 05e02977f6..e05db9c63f 100644 --- a/libavformat/avi.h +++ b/libavformat/avi.h @@ -21,8 +21,6 @@ #ifndef AVFORMAT_AVI_H #define AVFORMAT_AVI_H -#include "metadata.h" - #define AVIF_HASINDEX 0x00000010 // Index at end of file? #define AVIF_MUSTUSEINDEX 0x00000020 #define AVIF_ISINTERLEAVED 0x00000100 @@ -37,11 +35,4 @@ /* index flags */ #define AVIIF_INDEX 0x10 -extern const AVMetadataConv ff_avi_metadata_conv[]; - -/** - * A list of AVI info tags. - */ -extern const char ff_avi_tags[][5]; - #endif /* AVFORMAT_AVI_H */ diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 0cd84c0d6b..ee4265538e 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -79,6 +79,11 @@ static const char avi_headers[][8] = { { 0 } }; +static const AVMetadataConv avi_metadata_conv[] = { + { "strn", "title" }, + { 0 }, +}; + static int avi_load_index(AVFormatContext *s); static int guess_ni_flag(AVFormatContext *s); @@ -261,15 +266,6 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t AV_DICT_DONT_STRDUP_VAL); } -static void avi_read_info(AVFormatContext *s, uint64_t end) -{ - while (avio_tell(s->pb) < end) { - uint32_t tag = avio_rl32(s->pb); - uint32_t size = avio_rl32(s->pb); - avi_read_tag(s, NULL, tag, size); - } -} - static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; @@ -380,7 +376,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) goto end_of_header; } else if (tag1 == MKTAG('I', 'N', 'F', 'O')) - avi_read_info(s, list_end); + ff_read_riff_info(s, size - 4); else if (tag1 == MKTAG('n', 'c', 'd', 't')) avi_read_nikon(s, list_end); @@ -745,7 +741,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) clean_index(s); } - ff_metadata_conv_ctx(s, NULL, ff_avi_metadata_conv); + ff_metadata_conv_ctx(s, NULL, avi_metadata_conv); + ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); return 0; } diff --git a/libavformat/avienc.c b/libavformat/avienc.c index cf2e1d601d..b4521cd6ef 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -378,9 +378,9 @@ static int avi_write_header(AVFormatContext *s) list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "INFO"); - ff_metadata_conv(&s->metadata, ff_avi_metadata_conv, NULL); - for (i = 0; *ff_avi_tags[i]; i++) { - if ((t = av_dict_get(s->metadata, ff_avi_tags[i], NULL, AV_DICT_MATCH_CASE))) + ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL); + for (i = 0; *ff_riff_tags[i]; i++) { + if ((t = av_dict_get(s->metadata, ff_riff_tags[i], NULL, AV_DICT_MATCH_CASE))) avi_write_info_tag(s->pb, t->key, t->value); } ff_end_tag(pb, list2); diff --git a/libavformat/riff.c b/libavformat/riff.c index 29c3803173..2a989cd1bb 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -342,6 +342,28 @@ const AVCodecTag ff_codec_wav_tags[] = { { CODEC_ID_NONE, 0 }, }; +const AVMetadataConv ff_riff_info_conv[] = { + { "IART", "artist" }, + { "ICMT", "comment" }, + { "ICOP", "copyright" }, + { "ICRD", "date" }, + { "IGNR", "genre" }, + { "ILNG", "language" }, + { "INAM", "title" }, + { "IPRD", "album" }, + { "IPRT", "track" }, + { "ISFT", "encoder" }, + { "ITCH", "encoded_by"}, + { 0 }, +}; + +const char ff_riff_tags[][5] = { + "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI", + "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD", + "IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH", + {0} +}; + #if CONFIG_MUXERS int64_t ff_start_tag(AVIOContext *pb, const char *tag) { @@ -613,3 +635,49 @@ void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssiz *au_scale /= gcd; *au_rate /= gcd; } + +int ff_read_riff_info(AVFormatContext *s, int64_t size) +{ + int64_t start, end, cur; + AVIOContext *pb = s->pb; + + start = avio_tell(pb); + end = start + size; + + while ((cur = avio_tell(pb)) >= 0 && cur <= end - 8 /* = tag + size */) { + uint32_t chunk_code; + int64_t chunk_size; + char key[5] = {0}; + char *value; + + chunk_code = avio_rl32(pb); + chunk_size = avio_rl32(pb); + if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) { + av_log(s, AV_LOG_ERROR, "too big INFO subchunk\n"); + return AVERROR_INVALIDDATA; + } + + chunk_size += (chunk_size & 1); + + value = av_malloc(chunk_size + 1); + if (!value) { + av_log(s, AV_LOG_ERROR, "out of memory, unable to read INFO tag\n"); + return AVERROR(ENOMEM); + } + + AV_WL32(key, chunk_code); + + if (avio_read(pb, value, chunk_size) != chunk_size) { + av_freep(key); + av_freep(value); + av_log(s, AV_LOG_ERROR, "premature end of file while reading INFO tag\n"); + return AVERROR_INVALIDDATA; + } + + value[chunk_size] = 0; + + av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); + } + + return 0; +} diff --git a/libavformat/riff.h b/libavformat/riff.h index a2fa8b7b1c..3bd309f86b 100644 --- a/libavformat/riff.h +++ b/libavformat/riff.h @@ -31,6 +31,10 @@ #include "libavcodec/avcodec.h" #include "avio.h" #include "internal.h" +#include "metadata.h" + +extern const AVMetadataConv ff_riff_info_conv[]; +extern const char ff_riff_tags[][5]; int64_t ff_start_tag(AVIOContext *pb, const char *tag); void ff_end_tag(AVIOContext *pb, int64_t start); @@ -54,4 +58,6 @@ unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum CodecID id); enum CodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag); void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale); +int ff_read_riff_info(AVFormatContext *s, int64_t size); + #endif /* AVFORMAT_RIFF_H */ diff --git a/libavformat/wav.c b/libavformat/wav.c index 298880d590..3e03037a8b 100644 --- a/libavformat/wav.c +++ b/libavformat/wav.c @@ -33,7 +33,6 @@ #include "pcm.h" #include "riff.h" #include "avio.h" -#include "avio_internal.h" #include "metadata.h" typedef struct { @@ -224,7 +223,7 @@ AVOutputFormat ff_wav_muxer = { #if CONFIG_WAV_DEMUXER -static int64_t next_tag(AVIOContext *pb, unsigned int *tag) +static int64_t next_tag(AVIOContext *pb, uint32_t *tag) { *tag = avio_rl32(pb); return avio_rl32(pb); @@ -385,7 +384,7 @@ static int wav_read_header(AVFormatContext *s, int64_t size, av_uninit(data_size); int64_t sample_count=0; int rf64; - unsigned int tag; + uint32_t tag, list_type; AVIOContext *pb = s->pb; AVStream *st; WAVContext *wav = s->priv_data; @@ -467,6 +466,18 @@ static int wav_read_header(AVFormatContext *s, if ((ret = wav_parse_bext_tag(s, size)) < 0) return ret; break; + case MKTAG('L', 'I', 'S', 'T'): + list_type = avio_rl32(pb); + if (size <= 4) { + av_log(s, AV_LOG_ERROR, "too short LIST"); + return AVERROR_INVALIDDATA; + } + switch (list_type) { + case MKTAG('I', 'N', 'F', 'O'): + if ((ret = ff_read_riff_info(s, size - 4)) < 0) + return ret; + } + break; } /* seek to next tag unless we know that we'll run into EOF */ @@ -489,6 +500,7 @@ break_loop: st->duration = sample_count; ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); + ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); return 0; } -- cgit v1.2.3