[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