From c70add61d1551bf31734f7ef7d87824ff5389280 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Mon, 7 Nov 2016 13:09:03 -0500 Subject: [PATCH 1/3] lavu: Add AVSphericalMapping type and frame side data While no decoder currently exports spherical information, this type represents a frame property that has to be passed through from container to frames. Signed-off-by: Vittorio Giovara --- doc/APIchanges | 4 ++ libavutil/Makefile | 2 + libavutil/frame.h | 6 ++ libavutil/spherical.c | 34 +++++++++++ libavutil/spherical.h | 137 ++++++++++++++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 6 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 libavutil/spherical.c create mode 100644 libavutil/spherical.h diff --git a/doc/APIchanges b/doc/APIchanges index 90c6500764..c330310cab 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2015-08-28 API changes, most recent first: +2016-xx-xx - xxxxxxx - lavu 55.30.0 - spherical.h + Add AV_FRAME_DATA_SPHERICAL value, av_spherical_alloc() API and + AVSphericalMapping type to export and describe spherical video properties. + 2016-xx-xx - xxxxxxx - lavf 57.10.0 - avformat.h Add av_stream_add_side_data(). diff --git a/libavutil/Makefile b/libavutil/Makefile index fbcf1a757f..28372c9bef 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -48,6 +48,7 @@ HEADERS = adler32.h \ replaygain.h \ samplefmt.h \ sha.h \ + spherical.h \ stereo3d.h \ time.h \ version.h \ @@ -102,6 +103,7 @@ OBJS = adler32.o \ rc4.o \ samplefmt.o \ sha.o \ + spherical.o \ stereo3d.o \ time.o \ tree.o \ diff --git a/libavutil/frame.h b/libavutil/frame.h index 12624d797f..4052199fd3 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -92,6 +92,12 @@ enum AVFrameSideDataType { * enum AVAudioServiceType defined in avcodec.h. */ AV_FRAME_DATA_AUDIO_SERVICE_TYPE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, }; enum AVActiveFormatDescription { diff --git a/libavutil/spherical.c b/libavutil/spherical.c new file mode 100644 index 0000000000..f6e53d1bd2 --- /dev/null +++ b/libavutil/spherical.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mem.h" +#include "spherical.h" + +AVSphericalMapping *av_spherical_alloc(size_t *size) +{ + AVSphericalMapping *spherical = av_mallocz(sizeof(AVSphericalMapping)); + if (!spherical) + return NULL; + + if (size) + *size = sizeof(*spherical); + + return spherical; +} diff --git a/libavutil/spherical.h b/libavutil/spherical.h new file mode 100644 index 0000000000..8ecaefd946 --- /dev/null +++ b/libavutil/spherical.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016 Vittorio Giovara + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Spherical video + */ + +#ifndef AVUTIL_SPHERICAL_H +#define AVUTIL_SPHERICAL_H + +/** + * @addtogroup lavu_video + * @{ + * + * @defgroup lavu_video_spherical Spherical video mapping + * @{ + */ + +/** + * @addtogroup lavu_video_spherical + * A spherical video file contains surfaces that need to be mapped onto a + * sphere. Depending on how the frame was converted, a different distortion + * transformation or surface recomposition function needs to be applied before + * the video should be mapped and displayed. + */ + +/** + * Projection of the video surface(s) on a sphere. + */ +enum AVSphericalProjection { + /** + * Video represents a sphere mapped on a flat surface using + * equirectangular projection. + */ + AV_SPHERICAL_EQUIRECTANGULAR, + + /** + * Video frame is split into 6 faces of a cube, and arranged on a + * 3x2 layout. Faces are oriented upwards for the front, left, right, + * and back faces. The up face is oriented so the top of the face is + * forwards and the down face is oriented so the top of the face is + * to the back. + */ + AV_SPHERICAL_CUBEMAP, +}; + +/** + * This structure describes how to handle spherical videos, outlining + * information about projection, initial layout, and any other view modifier. + * + * @note The struct must be allocated with av_spherical_alloc() and + * its size is not a part of the public ABI. + */ +typedef struct AVSphericalMapping { + /** + * Projection type. + */ + enum AVSphericalProjection projection; + + /** + * @name Initial orientation + * @{ + * There fields describe additional rotations applied to the sphere after + * the video frame is mapped onto it. The sphere is rotated around the + * viewer, who remains stationary. The order of transformation is always + * yaw, followed by pitch, and finally by roll. + * + * The coordinate system matches the one defined in OpenGL, where the + * forward vector (z) is coming out of screen, and it is equivalent to + * a rotation matrix of R = r_y(yaw) * r_x(pitch) * r_z(roll). + * + * A positive yaw rotates the portion of the sphere in front of the viewer + * toward their right. A positive pitch rotates the portion of the sphere + * in front of the viewer upwards. A positive roll tilts the portion of + * the sphere in front of the viewer to the viewer's right. + * + * These values are exported as 16.16 fixed point. + * + * See this equirectangular projection as example: + * + * @code{.unparsed} + * Yaw + * -180 0 180 + * 90 +-------------+-------------+ 180 + * | | | up + * P | | | y| forward + * i | ^ | | /z + * t 0 +-------------X-------------+ 0 Roll | / + * c | | | | / + * h | | | 0|/_____right + * | | | x + * -90 +-------------+-------------+ -180 + * + * X - the default camera center + * ^ - the default up vector + * @endcode + */ + int32_t yaw; ///< Rotation around the up vector [-180, 180]. + int32_t pitch; ///< Rotation around the right vector [-90, 90]. + int32_t roll; ///< Rotation around the forward vector [-180, 180]. + /** + * @} + */ +} AVSphericalMapping; + +/** + * Allocate a AVSphericalVideo structure and initialize its fields to default + * values. + * + * @return the newly allocated struct or NULL on failure + */ +AVSphericalMapping *av_spherical_alloc(size_t *size); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_SPHERICAL_H */ diff --git a/libavutil/version.h b/libavutil/version.h index f1102312ba..e9940f2518 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 29 +#define LIBAVUTIL_VERSION_MINOR 30 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 2fb6acd9c28907e4f8c0510099a4603ea6caf861 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 2 Nov 2016 11:28:54 -0400 Subject: [PATCH 2/3] lavc: Add spherical packet side data API Signed-off-by: Vittorio Giovara --- avprobe.c | 21 +++++++++++++++++++++ doc/APIchanges | 4 ++++ libavcodec/avcodec.h | 6 ++++++ libavcodec/decode.c | 1 + libavcodec/version.h | 4 ++-- libavformat/dump.c | 30 ++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 7 files changed, 65 insertions(+), 3 deletions(-) diff --git a/avprobe.c b/avprobe.c index ff28a0b343..8142ce2966 100644 --- a/avprobe.c +++ b/avprobe.c @@ -27,6 +27,7 @@ #include "libavutil/display.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "libavutil/dict.h" #include "libavutil/libm.h" @@ -766,6 +767,7 @@ static void show_stream(InputFile *ifile, InputStream *ist) for (i = 0; i < stream->nb_side_data; i++) { const AVPacketSideData* sd = &stream->side_data[i]; AVStereo3D *stereo; + AVSphericalMapping *spherical; switch (sd->type) { case AV_PKT_DATA_DISPLAYMATRIX: @@ -786,6 +788,25 @@ static void show_stream(InputFile *ifile, InputStream *ist) !!(stereo->flags & AV_STEREO3D_FLAG_INVERT)); probe_object_footer("stereo3d"); break; + case AV_PKT_DATA_SPHERICAL: + spherical = (AVSphericalMapping *)sd->data; + probe_object_header("spherical"); + + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) + probe_str("projection", "equirectangular"); + else if (spherical->projection == AV_SPHERICAL_CUBEMAP) + probe_str("projection", "cubemap"); + else + probe_str("projection", "unknown"); + + probe_object_header("orientation"); + probe_int("yaw", (double) spherical->yaw / (1 << 16)); + probe_int("pitch", (double) spherical->pitch / (1 << 16)); + probe_int("roll", (double) spherical->roll / (1 << 16)); + probe_object_footer("orientation"); + + probe_object_footer("spherical"); + break; } } probe_object_footer("sidedata"); diff --git a/doc/APIchanges b/doc/APIchanges index c330310cab..d5dc5edaa5 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,10 @@ libavutil: 2015-08-28 API changes, most recent first: +2016-xx-xx - xxxxxxx - lavc 57.29.0 - avcodec.h + Add AV_PKT_DATA_SPHERICAL packet side data to export AVSphericalMapping + information from containers. + 2016-xx-xx - xxxxxxx - lavu 55.30.0 - spherical.h Add AV_FRAME_DATA_SPHERICAL value, av_spherical_alloc() API and AVSphericalMapping type to export and describe spherical video properties. diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e75d300ba0..6e1ed74e08 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1289,6 +1289,12 @@ enum AVPacketSideDataType { * This side data corresponds to the AVCPBProperties struct. */ AV_PKT_DATA_CPB_PROPERTIES, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, }; typedef struct AVPacketSideData { diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 42bcee2d17..00085c3b4d 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -747,6 +747,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) } sd[] = { { AV_PKT_DATA_REPLAYGAIN , AV_FRAME_DATA_REPLAYGAIN }, { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX }, + { AV_PKT_DATA_SPHERICAL, AV_FRAME_DATA_SPHERICAL }, { AV_PKT_DATA_STEREO3D, AV_FRAME_DATA_STEREO3D }, { AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE }, }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 6f58bc8c51..adab9b47a3 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 28 -#define LIBAVCODEC_VERSION_MICRO 4 +#define LIBAVCODEC_VERSION_MINOR 30 +#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/dump.c b/libavformat/dump.c index 3b50f5d944..660df0a533 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -27,6 +27,7 @@ #include "libavutil/log.h" #include "libavutil/mathematics.h" #include "libavutil/replaygain.h" +#include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "avformat.h" @@ -306,6 +307,31 @@ static void dump_cpb(void *ctx, AVPacketSideData *sd) cpb->vbv_delay); } +static void dump_spherical(void *ctx, AVPacketSideData *sd) +{ + AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; + double yaw, pitch, roll; + + if (sd->size < sizeof(*spherical)) { + av_log(ctx, AV_LOG_INFO, "invalid data"); + return; + } + + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) + av_log(ctx, AV_LOG_INFO, "equirectangular "); + else if (spherical->projection == AV_SPHERICAL_CUBEMAP) + av_log(ctx, AV_LOG_INFO, "cubemap "); + else { + av_log(ctx, AV_LOG_WARNING, "unknown"); + return; + } + + yaw = ((double)spherical->yaw) / (1 << 16); + pitch = ((double)spherical->pitch) / (1 << 16); + roll = ((double)spherical->roll) / (1 << 16); + av_log(ctx, AV_LOG_INFO, "(%f/%f/%f) ", yaw, pitch, roll); +} + static void dump_sidedata(void *ctx, AVStream *st, const char *indent) { int i; @@ -354,6 +380,10 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent) av_log(ctx, AV_LOG_INFO, "cpb: "); dump_cpb(ctx, &sd); break; + case AV_PKT_DATA_SPHERICAL: + av_log(ctx, AV_LOG_INFO, "spherical: "); + dump_spherical(ctx, &sd); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", sd.type, sd.size); diff --git a/libavutil/version.h b/libavutil/version.h index e9940f2518..f1102312ba 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -54,7 +54,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 30 +#define LIBAVUTIL_VERSION_MINOR 29 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From e90137c045721a1635cc241eb1e1be1126389c38 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Wed, 2 Nov 2016 11:29:15 -0400 Subject: [PATCH 3/3] mov: Export spherical information This implements Spherical Video V1 and V2, as described in the spatial-media collection by Google. Signed-off-by: Vittorio Giovara --- Changelog | 1 + libavformat/isom.h | 6 + libavformat/mov.c | 262 ++++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 4 files changed, 270 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index cd0ffb5213..feb151cf3c 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,7 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version : +- Support for spherical videos version 12: diff --git a/libavformat/isom.h b/libavformat/isom.h index 1aa2091043..fa73ad91bb 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" @@ -145,6 +148,9 @@ typedef struct MOVStreamContext { int stsd_count; int32_t *display_matrix; + AVStereo3D *stereo3d; + AVSphericalMapping *spherical; + size_t spherical_size; } MOVStreamContext; typedef struct MOVContext { diff --git a/libavformat/mov.c b/libavformat/mov.c index 28adce76c3..7fe639dd5e 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -37,6 +37,8 @@ #include "libavutil/dict.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/spherical.h" +#include "libavutil/stereo3d.h" #include "libavcodec/ac3tab.h" #include "avformat.h" #include "internal.h" @@ -3174,6 +3176,242 @@ static int mov_read_elst(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 < 5) { + av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n"); + return AVERROR_INVALIDDATA; + } + avio_skip(pb, 4); /* version + flags */ + + mode = avio_r8(pb); + 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; + 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 < 8) { + 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')) { + av_log(c->fc, AV_LOG_ERROR, "Missing spherical video header\n"); + return 0; + } + avio_skip(pb, 4); /* version + flags */ + avio_skip(pb, avio_r8(pb)); /* 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')) { + av_log(c->fc, AV_LOG_ERROR, "Missing projection header box\n"); + return 0; + } + avio_skip(pb, 4); /* version + flags */ + + /* 16.16 fixed point */ + yaw = avio_rb32(pb); + pitch = avio_rb32(pb); + roll = avio_rb32(pb); + + size = avio_rb32(pb); + if (size > atom.size) + return AVERROR_INVALIDDATA; + + tag = avio_rl32(pb); + avio_skip(pb, 4); /* version + flags */ + switch (tag) { + case MKTAG('c','b','m','p'): + projection = AV_SPHERICAL_CUBEMAP; + break; + case MKTAG('e','q','u','i'): + projection = AV_SPHERICAL_EQUIRECTANGULAR; + break; + default: + av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n"); + return 0; + } + + sc->spherical = av_spherical_alloc(&sc->spherical_size); + if (!sc->spherical) + return AVERROR(ENOMEM); + + sc->spherical->projection = projection; + + sc->spherical->yaw = yaw; + sc->spherical->pitch = pitch; + sc->spherical->roll = roll; + + return 0; +} + +static int mov_parse_uuid_spherical(MOVStreamContext *sc, AVIOContext *pb, size_t len) +{ + int ret = 0; + uint8_t *buffer = av_malloc(len + 1); + const char *val; + + if (!buffer) + return AVERROR(ENOMEM); + buffer[len] = '\0'; + + ret = ffio_read_size(pb, buffer, len); + if (ret < 0) + goto out; + + /* Check for mandatory keys and values, try to support XML as best-effort */ + if (av_stristr(buffer, "") && + (val = av_stristr(buffer, "")) && + av_stristr(val, "true") && + (val = av_stristr(buffer, "")) && + av_stristr(val, "true") && + (val = av_stristr(buffer, "")) && + av_stristr(val, "equirectangular")) { + sc->spherical = av_spherical_alloc(&sc->spherical_size); + if (!sc->spherical) + goto out; + + sc->spherical->projection = AV_SPHERICAL_EQUIRECTANGULAR; + + if (av_stristr(buffer, "")) { + enum AVStereo3DType mode; + + if (av_stristr(buffer, "left-right")) + mode = AV_STEREO3D_SIDEBYSIDE; + else if (av_stristr(buffer, "top-bottom")) + mode = AV_STEREO3D_TOPBOTTOM; + else + mode = AV_STEREO3D_2D; + + sc->stereo3d = av_stereo3d_alloc(); + if (!sc->stereo3d) + goto out; + + sc->stereo3d->type = mode; + } + + /* orientation */ + val = av_stristr(buffer, ""); + if (val) + sc->spherical->yaw = strtol(val, NULL, 10) * (1 << 16); + val = av_stristr(buffer, ""); + if (val) + sc->spherical->pitch = strtol(val, NULL, 10) * (1 << 16); + val = av_stristr(buffer, ""); + if (val) + sc->spherical->roll = strtol(val, NULL, 10) * (1 << 16); + } + +out: + av_free(buffer); + return ret; +} + +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)) && !sc->spherical) { + size_t len = atom.size - sizeof(uuid); + ret = mov_parse_uuid_spherical(sc, pb, len); + if (ret < 0) + return ret; + if (!sc->spherical) + av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata found\n"); + } else { + int i; + av_log(c->fc, AV_LOG_VERBOSE, "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 }, @@ -3235,6 +3473,9 @@ 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('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */ +{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */ +{ MKTAG('u','u','i','d'), mov_read_uuid }, /* universal unique identifier */ { MKTAG('-','-','-','-'), mov_read_custom }, { 0, NULL } }; @@ -3463,6 +3704,9 @@ static int mov_read_close(AVFormatContext *s) av_free(sc->extradata[j]); av_freep(&sc->extradata); av_freep(&sc->extradata_size); + + av_freep(&sc->stereo3d); + av_freep(&sc->spherical); } if (mov->dv_demux) { @@ -3553,6 +3797,24 @@ static int mov_read_header(AVFormatContext *s) sc->display_matrix = NULL; } + if (sc->stereo3d) { + err = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D, + (uint8_t *)sc->stereo3d, + sizeof(*sc->stereo3d)); + if (err < 0) + return err; + + sc->stereo3d = NULL; + } + if (sc->spherical) { + err = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, + (uint8_t *)sc->spherical, + sc->spherical_size); + if (err < 0) + return err; + + sc->spherical = NULL; + } break; } } diff --git a/libavformat/version.h b/libavformat/version.h index c6085f8591..ad7997ec4f 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 10 -#define LIBAVFORMAT_VERSION_MICRO 0 +#define LIBAVFORMAT_VERSION_MICRO 1 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \