summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-04-10 20:23:40 +0200
committerMichael Niedermayer <michaelni@gmx.at>2014-04-10 21:25:15 +0200
commit6e573b77597c1039667b5d7916551b488aeef828 (patch)
treeb3c7256418744bf78ee5f7e8aac5cc9e9a2d0896 /libavformat
parentc486cfab792e53de3f5fc9f5082909ce687a3fe8 (diff)
parent9a07fac678a8540d076e635061bbaa4ed09a9431 (diff)
Merge commit '9a07fac678a8540d076e635061bbaa4ed09a9431'
* commit '9a07fac678a8540d076e635061bbaa4ed09a9431': mov: read hydrogenaudio replaygain information Conflicts: libavformat/Makefile libavformat/mov.c See: 37a15f3e669372075c88254e070c971aecb485aa Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/Makefile2
-rw-r--r--libavformat/mov.c97
2 files changed, 98 insertions, 1 deletions
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 0fac33efe7..18b8817f2a 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -220,7 +220,7 @@ OBJS-$(CONFIG_MLP_MUXER) += rawenc.o
OBJS-$(CONFIG_MM_DEMUXER) += mm.o
OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o
OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.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 rtp.o
OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o
diff --git a/libavformat/mov.c b/libavformat/mov.c
index d10bac5678..79bc918cea 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -47,6 +47,7 @@
#include "libavcodec/get_bits.h"
#include "id3v1.h"
#include "mov_chan.h"
+#include "replaygain.h"
#if CONFIG_ZLIB
#include <zlib.h>
@@ -2508,6 +2509,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) {
@@ -3051,6 +3134,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('h','v','c','C'), mov_read_glbl },
{ MKTAG('u','u','i','d'), mov_read_uuid },
{ MKTAG('C','i','n', 0x8e), mov_read_targa_y216 },
+{ MKTAG('-','-','-','-'), mov_read_custom },
{ 0, NULL }
};
@@ -3509,6 +3593,19 @@ static int mov_read_header(AVFormatContext *s)
ff_rfps_calculate(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;
}