summaryrefslogtreecommitdiff
path: root/libavformat/matroskadec.c
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2016-12-06 14:48:45 -0300
committerVittorio Giovara <vittorio.giovara@gmail.com>2017-03-07 11:07:03 -0500
commit251849f06ce36ce8dc076e0fca2922119fa7e39e (patch)
tree0b2f227dd264a482f7ad1322380c3c5ec9199730 /libavformat/matroskadec.c
parenta825980f9f93af32c719497f9aab1e14248ab471 (diff)
mkv: Add support for Spherical Video elements
Signed-off-by: James Almer <jamrial@gmail.com> Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Diffstat (limited to 'libavformat/matroskadec.c')
-rw-r--r--libavformat/matroskadec.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 4e121b6afe..3dd54ebdf6 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -45,6 +45,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/lzo.h"
#include "libavutil/mathematics.h"
+#include "libavutil/spherical.h"
#include "libavcodec/bytestream.h"
#include "libavcodec/flac.h"
@@ -116,6 +117,14 @@ typedef struct MatroskaTrackEncoding {
MatroskaTrackCompression compression;
} MatroskaTrackEncoding;
+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;
@@ -126,6 +135,7 @@ typedef struct MatroskaTrackVideo {
uint64_t interlaced;
uint64_t field_order;
uint64_t stereo_mode;
+ MatroskaTrackVideoProjection projection;
} MatroskaTrackVideo;
typedef struct MatroskaTrackAudio {
@@ -309,6 +319,15 @@ static EbmlSyntax matroska_info[] = {
{ 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 EbmlSyntax matroska_track_video[] = {
{ MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) },
{ MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_width) },
@@ -316,6 +335,7 @@ static EbmlSyntax matroska_track_video[] = {
{ MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_width) },
{ MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_height) },
{ MATROSKA_ID_VIDEOCOLORSPACE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, fourcc) },
+ { 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 },
@@ -1576,6 +1596,51 @@ static void mkv_stereo_mode_display_mul(int stereo_mode,
}
}
+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:
+ projection = AV_SPHERICAL_EQUIRECTANGULAR;
+ break;
+ case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP:
+ if (track->video.projection.private.size < 4) {
+ av_log(NULL, AV_LOG_ERROR, "Missing projection private properties\n");
+ return AVERROR_INVALIDDATA;
+ }
+ projection = AV_SPHERICAL_CUBEMAP;
+ break;
+ default:
+ av_log(NULL, AV_LOG_WARNING,
+ "Unknown spherical metadata type %"PRIu64"\n",
+ track->video.projection.type);
+ 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) {
+ av_free(spherical);
+ return ret;
+ }
+
+ return 0;
+}
+
static int matroska_parse_tracks(AVFormatContext *s)
{
MatroskaDemuxContext *matroska = s->priv_data;
@@ -1908,6 +1973,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->sample_rate = track->audio.out_samplerate;