From 251849f06ce36ce8dc076e0fca2922119fa7e39e Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 6 Dec 2016 14:48:45 -0300 Subject: [PATCH] mkv: Add support for Spherical Video elements Signed-off-by: James Almer Signed-off-by: Vittorio Giovara --- libavformat/matroska.h | 14 ++++++++ libavformat/matroskadec.c | 69 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 91bb978422..4e9f96e530 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -118,6 +118,13 @@ #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3 #define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524 +#define MATROSKA_ID_VIDEOPROJECTION 0x7670 +#define MATROSKA_ID_VIDEOPROJECTIONTYPE 0x7671 +#define MATROSKA_ID_VIDEOPROJECTIONPRIVATE 0x7672 +#define MATROSKA_ID_VIDEOPROJECTIONPOSEYAW 0x7673 +#define MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH 0x7674 +#define MATROSKA_ID_VIDEOPROJECTIONPOSEROLL 0x7675 + /* IDs in the trackaudio master */ #define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5 #define MATROSKA_ID_AUDIOOUTSAMPLINGFREQ 0x78B5 @@ -256,6 +263,13 @@ typedef enum { MATROSKA_VIDEO_STEREOMODE_TYPE_NB, } MatroskaVideoStereoModeType; +typedef enum { + MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR = 0, + MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR = 1, + MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP = 2, + MATROSKA_VIDEO_PROJECTION_TYPE_MESH = 3, +} MatroskaVideoProjectionType; + /* * Matroska Codec IDs, strings */ 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; diff --git a/libavformat/version.h b/libavformat/version.h index 98faff77c0..fdf3e30851 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 11 -#define LIBAVFORMAT_VERSION_MICRO 1 +#define LIBAVFORMAT_VERSION_MICRO 2 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \