From 218dfd7ca1924bc44a168b34ec3c07051823c2dc Mon Sep 17 00:00:00 2001
From: Aaron Colwell <acolwell@google.com>
Date: Mon, 6 Feb 2017 13:48:58 -0800
Subject: [PATCH] mov,matroskadec : Allow matroskadec & mov to share spherical
parsing logic.
- Extracts common spherical metadata parsing logic.
- Adds checks to enforce that only non-tiled equirect & non-padded cubemaps
are accepted.
---
libavformat/Makefile | 5 +--
libavformat/matroskadec.c | 39 ++++++++++++-----------
libavformat/mov.c | 35 +++++++++++---------
libavformat/mov_spherical.c | 78 +++++++++++++++++++++++++++++++++++++++++++++
libavformat/mov_spherical.h | 61 +++++++++++++++++++++++++++++++++++
5 files changed, 182 insertions(+), 36 deletions(-)
create mode 100644 libavformat/mov_spherical.c
create mode 100644 libavformat/mov_spherical.h
@@ -265,7 +265,8 @@ OBJS-$(CONFIG_M4V_MUXER) += rawenc.o
OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \
rmsipr.o flac_picture.o \
oggparsevorbis.o vorbiscomment.o \
- flac_picture.o replaygain.o
+ flac_picture.o replaygain.o \
+ mov_spherical.o
OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \
avc.o hevc.o \
flacenc_header.o avlanguage.o vorbiscomment.o wv.o \
@@ -283,7 +284,7 @@ OBJS-$(CONFIG_MLV_DEMUXER) += mlvdec.o riffdec.o
OBJS-$(CONFIG_MM_DEMUXER) += mm.o
OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o
OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o
-OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o replaygain.o
+OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_spherical.o replaygain.o
OBJS-$(CONFIG_MOV_MUXER) += movenc.o avc.o hevc.o vpcc.o \
movenchint.o mov_chan.o rtp.o \
movenccenc.o rawutils.o
@@ -54,6 +54,7 @@
#include "internal.h"
#include "isom.h"
#include "matroska.h"
+#include "mov_spherical.h"
#include "oggdec.h"
/* For ff_codec_get_id(). */
#include "riff.h"
@@ -1909,36 +1910,36 @@ static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) {
return 0;
}
-static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) {
+static int mkv_parse_video_projection(AVFormatContext *fc, AVStream *st, const MatroskaTrack *track) {
AVSphericalMapping *spherical;
- enum AVSphericalProjection projection;
size_t spherical_size;
- int ret;
+ int ret = 0;
+ AVIOContext pb;
+
+ spherical = av_spherical_alloc(&spherical_size);
+ if (!spherical)
+ return AVERROR(ENOMEM);
+
+ 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));
+ ffio_init_context(&pb, track->video.projection.private.data, track->video.projection.private.size,
+ 0, NULL, NULL, NULL, NULL);
switch (track->video.projection.type) {
case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR:
- projection = AV_SPHERICAL_EQUIRECTANGULAR;
+ ret = ff_mov_read_equi(fc, &pb, track->video.projection.private.size, spherical);
break;
case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP:
- if (track->video.projection.private.size < 4)
- return AVERROR_INVALIDDATA;
- projection = AV_SPHERICAL_CUBEMAP;
+ ret = ff_mov_read_cbmp(fc, &pb, track->video.projection.private.size, spherical);
break;
default:
- return 0;
+ ret = AVERROR_PATCHWELCOME;
}
- 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));
+ if (!ret)
+ ret = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, (uint8_t *)spherical, spherical_size);
- ret = av_stream_add_side_data(st, AV_PKT_DATA_SPHERICAL, (uint8_t *)spherical,
- spherical_size);
if (ret < 0) {
av_freep(&spherical);
return ret;
@@ -2427,7 +2428,7 @@ static int matroska_parse_tracks(AVFormatContext *s)
ret = mkv_parse_video_color(st, track);
if (ret < 0)
return ret;
- ret = mkv_parse_video_projection(st, track);
+ ret = mkv_parse_video_projection(matroska->ctx, st, track);
if (ret < 0)
return ret;
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
@@ -56,6 +56,7 @@
#include "libavcodec/get_bits.h"
#include "id3v1.h"
#include "mov_chan.h"
+#include "mov_spherical.h"
#include "replaygain.h"
#if CONFIG_ZLIB
@@ -4624,7 +4625,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int size;
int32_t yaw, pitch, roll;
uint32_t tag;
- enum AVSphericalProjection projection;
+ int ret = 0;
if (c->fc->nb_streams < 1)
return 0;
@@ -4676,32 +4677,36 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom)
roll = avio_rb32(pb);
size = avio_rb32(pb);
- if (size > atom.size)
+ if (size < 8 && size > atom.size)
return AVERROR_INVALIDDATA;
tag = avio_rl32(pb);
- avio_skip(pb, 4); /* version + flags */
+
+ sc->spherical = av_spherical_alloc(&sc->spherical_size);
+ if (!sc->spherical)
+ return AVERROR(ENOMEM);
+
+ sc->spherical->yaw = yaw;
+ sc->spherical->pitch = pitch;
+ sc->spherical->roll = roll;
+
switch (tag) {
case MKTAG('c','b','m','p'):
- projection = AV_SPHERICAL_CUBEMAP;
+ ret = ff_mov_read_cbmp(c->fc, pb, size - 8, sc->spherical);
break;
case MKTAG('e','q','u','i'):
- projection = AV_SPHERICAL_EQUIRECTANGULAR;
+ ret = ff_mov_read_equi(c->fc, pb, size - 8, sc->spherical);
break;
default:
av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n");
- return 0;
+ ret = AVERROR_PATCHWELCOME;
}
- 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;
+ if (ret < 0) {
+ av_freep(&sc->spherical);
+ sc->spherical_size = 0;
+ return ret;
+ }
return 0;
}
new file mode 100644
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Aaron Colwell
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "mov_spherical.h"
+
+int ff_mov_read_equi(AVFormatContext *fc, AVIOContext *pb, int64_t size,
+ AVSphericalMapping* spherical_mapping)
+{
+ uint32_t projection_bounds_top;
+ uint32_t projection_bounds_bottom;
+ uint32_t projection_bounds_left;
+ uint32_t projection_bounds_right;
+
+ if (size == 0) {
+ spherical_mapping->projection = AV_SPHERICAL_EQUIRECTANGULAR;
+ return 0;
+ }
+
+ if (size < 20)
+ return AVERROR_INVALIDDATA;
+
+ avio_skip(pb, 4); /* version + flags */
+ projection_bounds_top = avio_rb32(pb);
+ projection_bounds_bottom = avio_rb32(pb);
+ projection_bounds_left = avio_rb32(pb);
+ projection_bounds_right = avio_rb32(pb);
+
+ if (projection_bounds_top != 0 || projection_bounds_bottom != 0 ||
+ projection_bounds_left != 0 || projection_bounds_right != 0) {
+ av_log(fc, AV_LOG_ERROR, "Unsupported equirect bounds. top %u bottom %u left %u right %u\n",
+ projection_bounds_top, projection_bounds_bottom,
+ projection_bounds_left, projection_bounds_right);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ spherical_mapping->projection = AV_SPHERICAL_EQUIRECTANGULAR;
+ return 0;
+}
+
+int ff_mov_read_cbmp(AVFormatContext *fc, AVIOContext *pb, int64_t size,
+ AVSphericalMapping* spherical_mapping)
+{
+ uint32_t layout;
+ uint32_t padding;
+
+ if (size < 12)
+ return AVERROR_INVALIDDATA;
+
+ avio_skip(pb, 4); /* version + flags */
+ layout = avio_rb32(pb);
+ padding = avio_rb32(pb);
+
+ if (layout != 0 || padding != 0) {
+ av_log(fc, AV_LOG_ERROR, "Unsupported cubemap parameters. layout %u, padding %u\n",
+ layout, padding);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ spherical_mapping->projection = AV_SPHERICAL_CUBEMAP;
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Aaron Colwell
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * mov 'equi', 'cbmp' tag reading/writing.
+ * @author Aaron Colwell
+ */
+
+#ifndef AVFORMAT_MOV_SPHERICAL_H
+#define AVFORMAT_MOV_SPHERICAL_H
+
+#include <stdint.h>
+#include "libavcodec/avcodec.h"
+#include "libavformat/avformat.h"
+#include "libavformat/avio.h"
+#include "libavutil/spherical.h"
+
+/**
+ * Parses the contents of an 'equi' box and sets the appropriate fields in spherical_mapping.
+ *
+ * @param fc AVFormatContext
+ * @param pb AVIOContext containing 'equi' box data.
+ * @param size Remaining size in the 'equi' box
+ * @param spherical_mapping Structure updated with parsed data.
+ * @return 0 if ok, or negative AVERROR code on failure
+ *
+ */
+int ff_mov_read_equi(AVFormatContext *fc, AVIOContext *pb, int64_t size,
+ AVSphericalMapping* spherical_mapping);
+
+/**
+ * Parses the contents of an 'cbmp' box and sets the appropriate fields in spherical_mapping.
+ *
+ * @param fc AVFormatContext
+ * @param pb AVIOContext containing 'cbmp' box data.
+ * @param size Remaining size in the 'cbmp' box
+ * @param spherical_mapping Structure updated with parsed data.
+ * @return 0 if ok, or negative AVERROR code on failure
+ *
+ */
+int ff_mov_read_cbmp(AVFormatContext *fc, AVIOContext *pb, int64_t size,
+ AVSphericalMapping* spherical_mapping);
+
+#endif /* AVFORMAT_MOV_SPHERICAL_H */
--
2.11.0.483.g087da7b7c-goog