As defined by Google's Spatial Audio RFC.
Signed-off-by: Vittorio Giovara <[email protected]>
---
libavformat/mov.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/libavformat/mov.c b/libavformat/mov.c
index c90b5fa108..48fd865411 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -3459,6 +3459,102 @@ static int mov_read_uuid(MOVContext *c, AVIOContext
*pb, MOVAtom atom)
return 0;
}
+static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ MOVStreamContext *sc;
+ int i, version, type;
+ int ambisonic_order, channel_order, normalization, channel_count;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+
+ st = c->fc->streams[c->fc->nb_streams - 1];
+ sc = st->priv_data;
+
+ if (atom.size < 16) {
+ av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ version = avio_r8(pb);
+ if (version) {
+ av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n",
version);
+ return 0;
+ }
+
+ type = avio_r8(pb);
+ if (type) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Unsupported ambisonic type %d\n", type);
+ return 0;
+ }
+
+ ambisonic_order = avio_rb32(pb);
+
+ channel_order = avio_r8(pb);
+ if (channel_order) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Unsupported channel_order %d\n", channel_order);
+ return 0;
+ }
+
+ normalization = avio_r8(pb);
+ if (normalization) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Unsupported normalization %d\n", normalization);
+ return 0;
+ }
+
+ channel_count = avio_rb32(pb);
+ if (ambisonic_order != sqrt(channel_count) - 1) {
+ av_log(c->fc, AV_LOG_ERROR,
+ "Invalid number of channels (%d / %d)\n",
+ channel_count, ambisonic_order);
+ return 0;
+ }
+
+ for (i = 0; i < channel_count; i++) {
+ if (i != avio_rb32(pb)) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Ambisonic channel reordering is not supported\n");
+ return 0;
+ }
+ }
+
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC;
+ st->codecpar->ch_layout.nb_channels = channel_count;
+
+ return 0;
+}
+
+static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ int version;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+
+ st = c->fc->streams[c->fc->nb_streams - 1];
+
+ if (atom.size < 5) {
+ av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ version = avio_r8(pb);
+ if (version) {
+ av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n",
version);
+ return 0;
+ }
+
+ st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
+
+ return 0;
+}
+
static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('a','v','s','s'), mov_read_extradata },
{ MKTAG('c','h','p','l'), mov_read_chpl },
@@ -3523,6 +3619,8 @@ static const MOVParseTableEntry mov_default_parse_table[]
= {
{ MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
{ MKTAG('u','u','i','d'), mov_read_uuid }, /* universal unique identifier */
+{ MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
+{ MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
{ MKTAG('-','-','-','-'), mov_read_custom },
{ 0, NULL }
};
--
2.13.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel