[vlc-devel] [PATCH] demux: mp4: support 360° v2 spatial metadata

Steve Lhomme robux4 at videolabs.io
Wed Nov 16 17:17:00 CET 2016


as found here https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md
---
 modules/demux/mp4/essetup.c | 36 ++++++++++++++++++++++++++
 modules/demux/mp4/libmp4.c  | 62 +++++++++++++++++++++++++++++++++++++++++++++
 modules/demux/mp4/libmp4.h  | 43 +++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+)

diff --git a/modules/demux/mp4/essetup.c b/modules/demux/mp4/essetup.c
index d85bd8b..e497676 100644
--- a/modules/demux/mp4/essetup.c
+++ b/modules/demux/mp4/essetup.c
@@ -346,6 +346,7 @@ int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
     }
 
     /* Set 360 video mode */
+    p_track->fmt.video.projection_mode = PROJECTION_MODE_RECTANGULAR;
     const MP4_Box_t *p_uuid = MP4_BoxGet( p_track->p_track, "uuid" );
     for( ; p_uuid; p_uuid = p_uuid->p_next)
     {
@@ -355,6 +356,41 @@ int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
             p_track->fmt.video.projection_mode = p_uuid->data.p_360->i_projection_mode;
     }
 
+    const MP4_Box_t *p_st3d = MP4_BoxGet( p_sample, "st3d" );
+    if (p_st3d && BOXDATA(p_st3d))
+    {
+        switch( BOXDATA(p_st3d)->i_stereo_mode )
+        {
+        case ST3D_MONOSCOPIC:
+            p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
+            break;
+        case ST3D_STEREOSCOPIC_TOP_BOTTOM:
+            p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
+            break;
+        case ST3D_STEREOSCOPIC_LEFT_RIGHT:
+            p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
+            break;
+        }
+    }
+
+    const MP4_Box_t *p_prhd = MP4_BoxGet( p_sample, "sv3d/proj/prhd" );
+    if (p_prhd && BOXDATA(p_prhd))
+    {
+        p_track->fmt.video.f_pose_yaw_degrees
+                = BOXDATA(p_prhd)->f_pose_yaw_degrees;
+        p_track->fmt.video.f_pose_pitch_degrees
+                = BOXDATA(p_prhd)->f_pose_pitch_degrees;
+        p_track->fmt.video.f_pose_roll_degrees
+                = BOXDATA(p_prhd)->f_pose_roll_degrees;
+    }
+
+    const MP4_Box_t *p_equi = MP4_BoxGet( p_sample, "sv3d/proj/equi" );
+    const MP4_Box_t *p_cbmp = MP4_BoxGet( p_sample, "sv3d/proj/cbmp" );
+    if (p_equi && BOXDATA(p_equi))
+        p_track->fmt.video.projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
+    else if (p_cbmp && BOXDATA(p_cbmp))
+        p_track->fmt.video.projection_mode = PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD;
+
     /* It's a little ugly but .. there are special cases */
     switch( p_sample->i_type )
     {
diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index 7f7903a..9ab5bf8 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -767,6 +767,58 @@ static int MP4_ReadBox_uuid( stream_t *p_stream, MP4_Box_t *p_box )
     return 1;
 }
 
+static int MP4_ReadBox_st3d( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_st3d_t, NULL );
+
+    MP4_Box_data_st3d_t *p_data = p_box->data.p_st3d;
+    MP4_GET1BYTE( p_data->i_stereo_mode );
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_prhd( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_prhd_t, NULL );
+
+    MP4_Box_data_prhd_t *p_data = p_box->data.p_prhd;
+    int32_t fixed16_16;
+    MP4_GET4BYTES( fixed16_16 );
+    p_data->f_pose_yaw_degrees   = (float) fixed16_16 / 65536.0f;
+
+    MP4_GET4BYTES( fixed16_16 );
+    p_data->f_pose_pitch_degrees = (float) fixed16_16 / 65536.0f;
+
+    MP4_GET4BYTES( fixed16_16 );
+    p_data->f_pose_roll_degrees  = (float) fixed16_16 / 65536.0f;
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_equi( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_equi_t, NULL );
+
+    MP4_Box_data_equi_t *p_data = p_box->data.p_equi;
+    MP4_GET4BYTES( p_data->i_projection_bounds_top );
+    MP4_GET4BYTES( p_data->i_projection_bounds_bottom );
+    MP4_GET4BYTES( p_data->i_projection_bounds_left );
+    MP4_GET4BYTES( p_data->i_projection_bounds_right );
+
+    MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_cbmp( stream_t *p_stream, MP4_Box_t *p_box )
+{
+    MP4_READBOX_ENTER( MP4_Box_data_cbmp_t, NULL );
+
+    MP4_Box_data_cbmp_t *p_data = p_box->data.p_cbmp;
+    MP4_GET4BYTES( p_data->i_layout );
+    MP4_GET4BYTES( p_data->i_padding );
+
+    MP4_READBOX_EXIT( 1 );
+}
+
 static void MP4_FreeBox_sidx( MP4_Box_t *p_box )
 {
     FREENULL( p_box->data.p_sidx->p_items );
@@ -4411,6 +4463,16 @@ static const struct
     { ATOM_mfro,    MP4_ReadBox_mfro,        ATOM_mfra },
     { ATOM_uuid,    MP4_ReadBox_uuid,        0 },
 
+    /* spatial/360°/VR */
+    { ATOM_st3d,    MP4_ReadBox_st3d,        ATOM_avc1 },
+    { ATOM_st3d,    MP4_ReadBox_st3d,        ATOM_mp4v },
+    { ATOM_sv3d,    MP4_ReadBoxContainer,    ATOM_avc1 },
+    { ATOM_sv3d,    MP4_ReadBoxContainer,    ATOM_mp4v },
+    { ATOM_proj,    MP4_ReadBoxContainer,    ATOM_sv3d },
+    { ATOM_prhd,    MP4_ReadBox_prhd,        ATOM_proj },
+    { ATOM_equi,    MP4_ReadBox_equi,        ATOM_proj },
+    { ATOM_cbmp,    MP4_ReadBox_cbmp,        ATOM_proj },
+
     /* Last entry */
     { 0,              MP4_ReadBox_default,   0 }
 };
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index 9a30de0..42e3e02 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -118,6 +118,13 @@ typedef int64_t stime_t;
 #define ATOM_tfra VLC_FOURCC( 't', 'f', 'r', 'a' )
 #define ATOM_keys VLC_FOURCC( 'k', 'e', 'y', 's' )
 
+#define ATOM_st3d VLC_FOURCC( 's', 't', '3', 'd' )
+#define ATOM_sv3d VLC_FOURCC( 's', 'v', '3', 'd' )
+#define ATOM_proj VLC_FOURCC( 'p', 'r', 'o', 'j' )
+#define ATOM_prhd VLC_FOURCC( 'p', 'r', 'h', 'd' )
+#define ATOM_cbmp VLC_FOURCC( 'c', 'b', 'm', 'p' )
+#define ATOM_equi VLC_FOURCC( 'e', 'q', 'u', 'i' )
+
 #define ATOM_nmhd VLC_FOURCC( 'n', 'm', 'h', 'd' )
 #define ATOM_mp2v VLC_FOURCC( 'm', 'p', '2', 'v' )
 #define ATOM_mp4v VLC_FOURCC( 'm', 'p', '4', 'v' )
@@ -1544,6 +1551,38 @@ typedef struct
     uint32_t i_projection_mode;
 } MP4_Box_data_360_t;
 
+
+typedef struct
+{
+    enum {
+        ST3D_MONOSCOPIC = 0,
+        ST3D_STEREOSCOPIC_TOP_BOTTOM = 1,
+        ST3D_STEREOSCOPIC_LEFT_RIGHT = 2,
+    } e_stereo_mode;
+    uint8_t i_stereo_mode;
+} MP4_Box_data_st3d_t;
+
+typedef struct
+{
+    float f_pose_yaw_degrees;
+    float f_pose_pitch_degrees;
+    float f_pose_roll_degrees;
+} MP4_Box_data_prhd_t;
+
+typedef struct
+{
+    uint32_t i_projection_bounds_top;
+    uint32_t i_projection_bounds_bottom;
+    uint32_t i_projection_bounds_left;
+    uint32_t i_projection_bounds_right;
+} MP4_Box_data_equi_t;
+
+typedef struct
+{
+    uint32_t i_layout;
+    uint32_t i_padding;
+} MP4_Box_data_cbmp_t;
+
 /*
 typedef struct MP4_Box_data__s
 {
@@ -1650,6 +1689,10 @@ typedef union MP4_Box_data_s
     MP4_Box_data_ASF_t  *p_asf;  /* flip4mac asf streams indicator */
 
     MP4_Box_data_360_t  *p_360;
+    MP4_Box_data_st3d_t *p_st3d;
+    MP4_Box_data_prhd_t *p_prhd;
+    MP4_Box_data_equi_t *p_equi;
+    MP4_Box_data_cbmp_t *p_cbmp;
 
     /* for generic handlers */
     MP4_Box_data_binary_t *p_binary;
-- 
2.10.1



More information about the vlc-devel mailing list