On 11/15/2016 1:56 PM, Vittorio Giovara wrote: > This implements Spherical Video V1 and V2, as described in the > spatial-media collection by Google. > > Signed-off-by: Vittorio Giovara <vittorio.giov...@gmail.com> > --- > Updated to use int32 for rotation. > Please CC. > Vittorio > > libavformat/isom.h | 7 ++ > libavformat/mov.c | 281 > ++++++++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 287 insertions(+), 1 deletion(-) > > diff --git a/libavformat/isom.h b/libavformat/isom.h > index 02bfedd..0fd9eb0 100644 > --- a/libavformat/isom.h > +++ b/libavformat/isom.h > @@ -24,6 +24,9 @@ > #ifndef AVFORMAT_ISOM_H > #define AVFORMAT_ISOM_H > > +#include "libavutil/spherical.h" > +#include "libavutil/stereo3d.h" > + > #include "avio.h" > #include "internal.h" > #include "dv.h" > @@ -177,6 +180,10 @@ typedef struct MOVStreamContext { > int stsd_count; > > int32_t *display_matrix; > + AVStereo3D *stereo3d; > + AVSphericalMapping *spherical; > + size_t spherical_size; > + > uint32_t format; > > int has_sidx; // If there is an sidx entry for this stream. > diff --git a/libavformat/mov.c b/libavformat/mov.c > index 6beb027..a017bc0 100644 > --- a/libavformat/mov.c > +++ b/libavformat/mov.c > @@ -42,6 +42,8 @@ > #include "libavutil/aes.h" > #include "libavutil/aes_ctr.h" > #include "libavutil/sha.h" > +#include "libavutil/spherical.h" > +#include "libavutil/stereo3d.h" > #include "libavutil/timecode.h" > #include "libavcodec/ac3tab.h" > #include "libavcodec/mpegaudiodecheader.h" > @@ -4497,8 +4499,230 @@ static int mov_read_tmcd(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);
If i'm reading the spec right, st3d is a FullBox so before the data you'll have the box's version and flags (1 byte and 3 bytes respectively). https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md > + 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; > + unsigned l, t, r, b; > + enum AVSphericalProjection projection; > + > + 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')) { Same for this one. > + 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')) { And this one > + 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); And all the possible cases for this one, except in here it seems to be 4 bytes for version and four for flags. Does Google offer samples to confirm this? > + switch (tag) { > + case MKTAG('c','b','m','p'): > + projection = AV_SPHERICAL_CUBEMAP; > + avio_skip(pb, 4); /* layout */ > + l = t = r = b = avio_rb32(pb); > + break; > + case MKTAG('e','q','u','i'): > + projection = AV_SPHERICAL_EQUIRECTANGULAR; > + t = avio_rb32(pb); > + b = avio_rb32(pb); > + l = avio_rb32(pb); > + r = avio_rb32(pb); > + break; > + default: > + av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n"); > + return 0; > + } _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel