Commit 9a07fac6 authored by Anton Khirnov's avatar Anton Khirnov
Browse files

mov: read hydrogenaudio replaygain information

parent ad8159e0
......@@ -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
......
......@@ -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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment