---
Updated to the new side data.
Vittorio

 libavformat/isom.h |  1 +
 libavformat/mov.c  | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index aec623b..1221446 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -138,6 +138,7 @@ typedef struct MOVStreamContext {
     MOVSbgp *rap_group;
 
     int32_t *display_matrix;
+    AVSphericalVideo *spherical;
 } MOVStreamContext;
 
 typedef struct MOVContext {
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 9d271f8..40a87c7 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -36,6 +36,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/dict.h"
 #include "libavutil/opt.h"
+#include "libavutil/stereo3d.h"
 #include "libavcodec/ac3tab.h"
 #include "avformat.h"
 #include "internal.h"
@@ -3082,6 +3083,75 @@ static int mov_read_elst(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
     return 0;
 }
 
+static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    AVStream *st;
+    MOVStreamContext *sc;
+    int ret;
+
+    uint8_t uuid[16];
+    static const uint8_t uuid_spherical[] = {
+        0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93,
+        0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd,
+    };
+
+    if (atom.size < sizeof(uuid) || atom.size == INT64_MAX)
+        return AVERROR_INVALIDDATA;
+
+    if (c->fc->nb_streams < 1)
+        return 0;
+    st = c->fc->streams[c->fc->nb_streams - 1];
+    sc = st->priv_data;
+
+    ret = ffio_read_size(pb, uuid, sizeof(uuid));
+    if (ret < 0)
+        return ret;
+
+    if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) {
+        size_t len = atom.size - sizeof(uuid);
+        uint8_t *buffer = av_malloc(len + 1);
+        if (!buffer)
+            return AVERROR(ENOMEM);
+        buffer[len] = '\0';
+
+        ret = ffio_read_size(pb, buffer, len);
+        if (ret < 0) {
+            av_free(buffer);
+            return ret;
+        }
+
+        /* Mandatory tags (StitchingSoftware ignored) */
+        if (av_stristr(buffer, 
"<GSpherical:Spherical>true</GSpherical:Spherical>") &&
+            av_stristr(buffer, 
"<GSpherical:Stitched>true</GSpherical:Stitched>") &&
+            av_stristr(buffer, 
"<GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType>")) {
+            sc->spherical = av_mallocz(sizeof(*sc->spherical));
+            if (!sc->spherical) {
+                av_free(buffer);
+                return AVERROR(ENOMEM);
+            }
+
+            sc->spherical->type = AV_SPHERICAL_EQUIRECTANGULAR;
+            sc->spherical->mode = AV_STEREO3D_2D;
+
+            if (av_stristr(buffer, 
"<GSpherical:StereoMode>left-right</GSpherical:StereoMode>"))
+                sc->spherical->mode = AV_STEREO3D_SIDEBYSIDE;
+            else if (av_stristr(buffer, 
"<GSpherical:StereoMode>top-bottom</GSpherical:StereoMode>"))
+                sc->spherical->mode = AV_STEREO3D_TOPBOTTOM;
+        } else {
+            av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata 
found\n");
+        }
+        av_free(buffer);
+    } else {
+        int i;
+        av_log(c->fc, AV_LOG_WARNING, "Unknown UUID found: 0x");
+        for (i = 0; i < sizeof(uuid); i++)
+            av_log(c->fc, AV_LOG_WARNING, "%02x", uuid[i]);
+        av_log(c->fc, AV_LOG_WARNING, "\n");
+    }
+
+    return 0;
+}
+
 static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('a','v','s','s'), mov_read_extradata },
 { MKTAG('c','h','p','l'), mov_read_chpl },
@@ -3143,6 +3213,7 @@ static const MOVParseTableEntry mov_default_parse_table[] 
= {
 { MKTAG('d','v','c','1'), mov_read_dvc1 },
 { MKTAG('s','b','g','p'), mov_read_sbgp },
 { MKTAG('h','v','c','C'), mov_read_glbl },
+{ MKTAG('u','u','i','d'), mov_read_uuid },
 { MKTAG('-','-','-','-'), mov_read_custom },
 { 0, NULL }
 };
@@ -3366,6 +3437,7 @@ static int mov_read_close(AVFormatContext *s)
         av_freep(&sc->stps_data);
         av_freep(&sc->rap_group);
         av_freep(&sc->display_matrix);
+        av_freep(&sc->spherical);
     }
 
     if (mov->dv_demux) {
@@ -3464,6 +3536,23 @@ static int mov_read_header(AVFormatContext *s)
                 sd->data = (uint8_t*)sc->display_matrix;
                 sc->display_matrix = NULL;
             }
+            if (sc->spherical) {
+                AVPacketSideData *sd, *tmp;
+
+                tmp = av_realloc_array(st->side_data,
+                                       st->nb_side_data + 1, sizeof(*tmp));
+                if (!tmp)
+                    return AVERROR(ENOMEM);
+
+                st->side_data = tmp;
+                st->nb_side_data++;
+
+                sd = &st->side_data[st->nb_side_data - 1];
+                sd->type = AV_PKT_DATA_SPHERICAL;
+                sd->size = sizeof(*sc->spherical);
+                sd->data = (uint8_t *)sc->spherical;
+                sc->spherical = NULL;
+            }
             break;
         }
     }
-- 
2.8.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to