diff mbox

[FFmpeg-devel,3/4] mov: Export spherical information

Message ID 63e37be9-b967-d25f-8a80-c39be11df000@gmail.com
State Accepted, archived
Headers show

Commit Message

James Almer Dec. 6, 2016, 6:05 p.m. UTC
On 12/6/2016 2:37 PM, Vittorio Giovara wrote:
> On Tue, Dec 6, 2016 at 11:06 AM, James Almer <jamrial@gmail.com> wrote:
>> On 11/30/2016 9:12 PM, James Almer wrote:
>>> On 11/30/2016 8:36 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@gmail.com>
>>>> ---
>>>> This addresses all comments from James.
>>>> Vittorio
>>>
>>> LGTM, at least the V2 part. Seems to follow the spec right now.
>>> Will trust you on the V1 part :P.
> 
> Hopefully V1 is going to disappear soon. Thanks for the review, I've
> sent a minor documentation update which reflects the latest change to
> the specification, I hope that is fine too.
> 
>>> I have written a Matroska implementation of this spec, for that
>>> matter. Will send it after this patchset is committed.
> 
> Oh cool, do you have or need a file to test (and/or add a fate)?

I wrote a muxer implementation and remuxed the mov file currently in
the FATE samples suite to test the demuxer implementation. You can
download it here: http://0x0.st/Lpj.mkv
I wont be sending the muxer implementation since i had to hack in
the projection specific private data to create that file, as it's
not part of AVSphericalMapping.

I could use an actual file created by Google to make sure i got it
right, but the spec is very clear and our Matroska de/muxers allow
one to add new elements with a few lines.

I'm attaching the demuxer implementation if you want to look at it
and test it.
diff mbox

Patch

From d29ead20c57011c141acd6bb522bedeed2755f1c Mon Sep 17 00:00:00 2001
From: James Almer <jamrial@gmail.com>
Date: Tue, 6 Dec 2016 14:48:45 -0300
Subject: [PATCH] avformat/matroskadec: add support for Spherical Video elements

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavformat/matroska.h    | 14 +++++++++++
 libavformat/matroskadec.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 13155e5..83c8246 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -153,6 +153,13 @@ 
 #define MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX 0x55D9
 #define MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN 0x55DA
 
+#define MATROSKA_ID_VIDEOPROJECTION 0x7670
+#define MATROSKA_ID_VIDEOPROJECTIONTYPE 0x7671
+#define MATROSKA_ID_VIDEOPROJECTIONPRIVATE 0x7672
+#define MATROSKA_ID_VIDEOPROJECTIONPOSEYAW 0x7673
+#define MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH 0x7674
+#define MATROSKA_ID_VIDEOPROJECTIONPOSEROLL 0x7675
+
 /* IDs in the trackaudio master */
 #define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
 #define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5
@@ -331,6 +338,13 @@  typedef enum {
   MATROSKA_COLOUR_CHROMASITINGVERT_NB
 } MatroskaColourChromaSitingVert;
 
+typedef enum {
+  MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR        = 0,
+  MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR    = 1,
+  MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP            = 2,
+  MATROSKA_VIDEO_PROJECTION_TYPE_MESH               = 3,
+} MatroskaVideoProjectionType;
+
 /*
  * Matroska Codec IDs, strings
  */
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 017a533..f4a452e 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -43,6 +43,7 @@ 
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/time_internal.h"
+#include "libavutil/spherical.h"
 
 #include "libavcodec/bytestream.h"
 #include "libavcodec/flac.h"
@@ -161,6 +162,14 @@  typedef struct MatroskaTrackVideoColor {
     MatroskaMasteringMeta mastering_meta;
 } MatroskaTrackVideoColor;
 
+typedef struct MatroskaTrackVideoProjection {
+    uint64_t type;
+    EbmlBin private;
+    double yaw;
+    double pitch;
+    double roll;
+} MatroskaTrackVideoProjection;
+
 typedef struct MatroskaTrackVideo {
     double   frame_rate;
     uint64_t display_width;
@@ -174,6 +183,7 @@  typedef struct MatroskaTrackVideo {
     uint64_t stereo_mode;
     uint64_t alpha_mode;
     MatroskaTrackVideoColor color;
+    MatroskaTrackVideoProjection projection;
 } MatroskaTrackVideo;
 
 typedef struct MatroskaTrackAudio {
@@ -424,6 +434,15 @@  static const EbmlSyntax matroska_track_video_color[] = {
     { 0 }
 };
 
+static const EbmlSyntax matroska_track_video_projection[] = {
+    { MATROSKA_ID_VIDEOPROJECTIONTYPE,        EBML_UINT,  0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } },
+    { MATROSKA_ID_VIDEOPROJECTIONPRIVATE,     EBML_BIN,   0, offsetof(MatroskaTrackVideoProjection, private) },
+    { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW,     EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f=0.0 } },
+    { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH,   EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f=0.0 } },
+    { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL,    EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f=0.0 } },
+    { 0 }
+};
+
 static const EbmlSyntax matroska_track_video[] = {
     { MATROSKA_ID_VIDEOFRAMERATE,      EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) },
     { MATROSKA_ID_VIDEODISPLAYWIDTH,   EBML_UINT,  0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } },
@@ -433,6 +452,7 @@  static const EbmlSyntax matroska_track_video[] = {
     { MATROSKA_ID_VIDEOCOLORSPACE,     EBML_BIN,   0, offsetof(MatroskaTrackVideo, color_space) },
     { MATROSKA_ID_VIDEOALPHAMODE,      EBML_UINT,  0, offsetof(MatroskaTrackVideo, alpha_mode) },
     { MATROSKA_ID_VIDEOCOLOR,          EBML_NEST,  0, offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } },
+    { MATROSKA_ID_VIDEOPROJECTION,     EBML_NEST,  0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } },
     { MATROSKA_ID_VIDEOPIXELCROPB,     EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPT,     EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPL,     EBML_NONE },
@@ -1879,6 +1899,44 @@  static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) {
     return 0;
 }
 
+static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) {
+    AVSphericalMapping *spherical;
+    enum AVSphericalProjection projection;
+    size_t spherical_size;
+    int ret;
+
+    switch (track->video.projection.type) {
+    case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR:
+        if (track->video.projection.private.size < 4)
+            return AVERROR_INVALIDDATA;
+        projection = AV_SPHERICAL_EQUIRECTANGULAR;
+        break;
+    case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP:
+        if (track->video.projection.private.size < 4)
+            return AVERROR_INVALIDDATA;
+        projection = AV_SPHERICAL_CUBEMAP;
+        break;
+    default:
+        return 0;
+    }
+
+    spherical = av_spherical_alloc(&spherical_size);
+    if (!spherical)
+        return AVERROR(ENOMEM);
+    spherical->projection = projection;
+
+    spherical->yaw   = (int32_t)(track->video.projection.yaw   * (1 << 16));
+    spherical->pitch = (int32_t)(track->video.projection.pitch * (1 << 16));
+    spherical->roll  = (int32_t)(track->video.projection.roll  * (1 << 16));
+
+    ret = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, (uint8_t *)spherical,
+                                  spherical_size);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
 static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id)
 {
     const AVCodecTag *codec_tags;
@@ -2361,6 +2419,10 @@  static int matroska_parse_tracks(AVFormatContext *s)
                 if (ret < 0)
                     return ret;
             }
+
+            ret = mkv_parse_video_projection(st, track);
+            if (ret < 0)
+                return ret;
         } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
             st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
             st->codecpar->codec_tag   = fourcc;
-- 
2.10.2