[FFmpeg-devel] [PATCH 3/3 v2] mov: Export spherical information
James Almer
jamrial at gmail.com
Wed Nov 16 05:09:14 EET 2016
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.giovara at 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;
> + }
More information about the ffmpeg-devel
mailing list