Signed-off-by: Vittorio Giovara
---
libavformat/isom.h | 4 +
libavformat/mov.c | 277 +
2 files changed, 281 insertions(+)
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 58f0a20..2e22575 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -28,6 +28,8 @@
#include "internal.h"
#include "dv.h"
+#include "libavutil/stereo3d.h"
+
/* isom.c */
extern const AVCodecTag ff_mp4_obj_type[];
extern const AVCodecTag ff_codec_movvideo_tags[];
@@ -145,6 +147,8 @@ typedef struct MOVStreamContext {
int stsd_count;
int32_t *display_matrix;
+AVSphericalVideo *spherical;
+AVStereo3D *stereo3d;
} MOVStreamContext;
typedef struct MOVContext {
diff --git a/libavformat/mov.c b/libavformat/mov.c
index fb2b7d6..d1f336b 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -37,6 +37,7 @@
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
+#include "libavutil/stereo3d.h"
#include "libavcodec/ac3tab.h"
#include "avformat.h"
#include "internal.h"
@@ -3154,6 +3155,242 @@ static int mov_read_elst(MOVContext *c, AVIOContext
*pb, MOVAtom atom)
return 0;
}
+static int mov_read_st3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+AVStream *st;
+MOVStreamContext *sc;
+enum AVStereo3DType type;
+int mode;
+
+if (c->fc->nb_streams < 1)
+return 0;
+
+st = c->fc->streams[c->fc->nb_streams - 1];
+sc = st->priv_data;
+
+if (atom.size < 1) {
+av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n");
+return AVERROR_INVALIDDATA;
+}
+
+mode = avio_r8(pb);
+switch(mode) {
+case 0:
+type = AV_STEREO3D_2D;
+break;
+case 1:
+type = AV_STEREO3D_TOPBOTTOM;
+break;
+case 2:
+type = AV_STEREO3D_SIDEBYSIDE;
+break;
+default:
+av_log(c->fc, AV_LOG_WARNING, "Unknown st3d mode value %d\n", mode);
+return 0;
+}
+
+sc->stereo3d = av_stereo3d_alloc();
+if (!sc->stereo3d)
+return AVERROR(ENOMEM);
+
+sc->stereo3d->type = type;
+return 0;
+}
+
+static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+AVStream *st;
+MOVStreamContext *sc;
+int size;
+int32_t yaw, pitch, roll;
+uint32_t tag;
+enum AVSphericalType type;
+
+if (c->fc->nb_streams < 1)
+return 0;
+
+st = c->fc->streams[c->fc->nb_streams - 1];
+sc = st->priv_data;
+
+if (atom.size < 4) {
+av_log(c->fc, AV_LOG_ERROR, "Empty spherical video box\n");
+return AVERROR_INVALIDDATA;
+}
+
+size = avio_rb32(pb);
+if (size > atom.size)
+return AVERROR_INVALIDDATA;
+
+tag = avio_rl32(pb);
+if (tag != MKTAG('s','v','h','d')) {
+av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n");
+return 0;
+}
+avio_skip(pb, size - 8); /* metadata_source */
+
+size = avio_rb32(pb);
+if (size > atom.size)
+return AVERROR_INVALIDDATA;
+
+tag = avio_rl32(pb);
+if (tag != MKTAG('p','r','o','j')) {
+av_log(c->fc, AV_LOG_ERROR, "Missing projection box\n");
+return 0;
+}
+
+size = avio_rb32(pb);
+if (size > atom.size)
+return AVERROR_INVALIDDATA;
+
+tag = avio_rl32(pb);
+if (tag != MKTAG('p','r','h','d')) {
+av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n");
+return 0;
+}
+
+/* 16.16 fixed point */
+yaw = avio_rb32(pb);
+pitch = avio_rb32(pb);
+roll = avio_rb32(pb);
+
+avio_skip(pb, size - 20);
+
+size = avio_rb32(pb);
+if (size > atom.size)
+return AVERROR_INVALIDDATA;
+
+tag = avio_rl32(pb);
+switch(tag) {
+case MKTAG('c','b','m','p'):
+type = AV_SPHERICAL_CUBEMAP;
+break;
+case MKTAG('e','q','u','i'):
+type = AV_SPHERICAL_EQUIRECTANGULAR;
+break;
+case MKTAG('m','s','h','p'):
+type = AV_SPHERICAL_MESH;
+break;
+default:
+av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n");
+return 0;
+}
+
+sc->spherical = av_spherical_alloc(NULL);
+if (!sc->spherical)
+return AVERROR(ENOMEM);
+
+sc->spherical->type = type;
+
+sc->spherical->yaw = ((double) yaw) / (1 << 16);
+sc->spherical->pitch = ((double) pitch) / (1 << 16);
+sc->spherical->roll = ((double) roll) / (1 << 16);
+
+return 0;
+}
+
+static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb,
size_t len)
+{
+int ret = 0;
+uint8_t *buffer = av_malloc(len + 1);
+const char *val;
+
+if (!buffer)
+return AVERROR(ENOMEM);
+buffer[len] = '\0';
+
+ret = ffio_read_size(pb, buffer, len);
+if (ret < 0)
+goto out;
+
+/* Check for mandatory keys and values, try to support XML as best-effort
*/
+if (av_stristr(buffer, "") &&
+(val = av_stristr(buffer, "")) &&
+av_stris