diff options
author | Anton Khirnov <anton@khirnov.net> | 2014-04-01 23:22:21 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2014-04-10 13:53:32 +0200 |
commit | 9a07fac678a8540d076e635061bbaa4ed09a9431 (patch) | |
tree | 312cd41ac04bf43ba69a877e0e2c70f9d42a74ab | |
parent | ad8159e0fe2bfc1c34739f0956ce464f9859b5a7 (diff) | |
download | ffmpeg-9a07fac678a8540d076e635061bbaa4ed09a9431.tar.gz |
mov: read hydrogenaudio replaygain information
-rw-r--r-- | libavformat/Makefile | 2 | ||||
-rw-r--r-- | libavformat/mov.c | 97 |
2 files changed, 98 insertions, 1 deletions
diff --git a/libavformat/Makefile b/libavformat/Makefile index 6784d51e98..a7f03f973a 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -179,7 +179,7 @@ OBJS-$(CONFIG_MLP_MUXER) += rawenc.o OBJS-$(CONFIG_MM_DEMUXER) += mm.o OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o pcm.o OBJS-$(CONFIG_MMF_MUXER) += mmf.o -OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.o +OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.o replaygain.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o isom.o avc.o hevc.o \ movenchint.o mov_chan.o OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o diff --git a/libavformat/mov.c b/libavformat/mov.c index 2900b1edc0..30f7f6e264 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -45,6 +45,7 @@ #include "libavcodec/get_bits.h" #include "id3v1.h" #include "mov_chan.h" +#include "replaygain.h" #if CONFIG_ZLIB #include <zlib.h> @@ -2236,6 +2237,88 @@ static int mov_read_ilst(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } +static int mov_read_replaygain(MOVContext *c, AVIOContext *pb, int size) +{ + int64_t end = avio_tell(pb) + size; + uint8_t *key = NULL, *val = NULL; + int i; + + for (i = 0; i < 2; i++) { + uint8_t **p; + uint32_t len, tag; + + if (end - avio_tell(pb) <= 12) + break; + + len = avio_rb32(pb); + tag = avio_rl32(pb); + avio_skip(pb, 4); // flags + + if (len < 12 || len - 12 > end - avio_tell(pb)) + break; + len -= 12; + + if (tag == MKTAG('n', 'a', 'm', 'e')) + p = &key; + else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) { + avio_skip(pb, 4); + len -= 4; + p = &val; + } else + break; + + *p = av_malloc(len + 1); + if (!*p) + break; + avio_read(pb, *p, len); + (*p)[len] = 0; + } + + if (key && val) { + av_dict_set(&c->fc->metadata, key, val, + AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + key = val = NULL; + } + + avio_seek(pb, end, SEEK_SET); + av_freep(&key); + av_freep(&val); + return 0; +} + +static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int64_t end = avio_tell(pb) + atom.size; + uint32_t tag, len; + + if (atom.size < 8) + goto fail; + + len = avio_rb32(pb); + tag = avio_rl32(pb); + + if (len > atom.size) + goto fail; + + if (tag == MKTAG('m', 'e', 'a', 'n') && len > 12) { + uint8_t domain[128]; + int domain_len; + + avio_skip(pb, 4); // flags + len -= 12; + + domain_len = avio_get_str(pb, len, domain, sizeof(domain)); + avio_skip(pb, len - domain_len); + if (!strcmp(domain, "org.hydrogenaudio.replaygain")) + return mov_read_replaygain(c, pb, end - avio_tell(pb)); + } + +fail: + av_log(c->fc, AV_LOG_VERBOSE, + "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size); + return 0; +} + static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) { while (atom.size > 8) { @@ -2665,6 +2748,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('d','v','c','1'), mov_read_dvc1 }, { MKTAG('s','b','g','p'), mov_read_sbgp }, { MKTAG('h','v','c','C'), mov_read_glbl }, +{ MKTAG('-','-','-','-'), mov_read_custom }, { 0, NULL } }; @@ -2958,6 +3042,19 @@ static int mov_read_header(AVFormatContext *s) } } + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + + if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) + continue; + + err = ff_replaygain_export(st, s->metadata); + if (err < 0) { + mov_read_close(s); + return err; + } + } + return 0; } |