From patchwork Wed Mar 29 18:01:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 3178 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.44.195 with SMTP id s186csp1205906vss; Wed, 29 Mar 2017 11:01:57 -0700 (PDT) X-Received: by 10.223.161.220 with SMTP id v28mr1827777wrv.54.1490810517798; Wed, 29 Mar 2017 11:01:57 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id m204si7895wma.86.2017.03.29.11.01.57; Wed, 29 Mar 2017 11:01:57 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 69E2A6899C4; Wed, 29 Mar 2017 21:01:30 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qt0-f193.google.com (mail-qt0-f193.google.com [209.85.216.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D68AB6882D1 for ; Wed, 29 Mar 2017 21:01:23 +0300 (EEST) Received: by mail-qt0-f193.google.com with SMTP id r5so3021196qtb.2 for ; Wed, 29 Mar 2017 11:01:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=TjBLCmCZ57/NOoQt1XH1nTIBrrDoDRpnXc5o7McQ4zI=; b=T4M97mkT7weWj6bJ06bOVt+qysniaWE1ggL6BUeD8kQsliuPgK2S4DIKYvgFKX1Y7x XYXegBW+gU1/C1WesU3V5jp/snl2FW9qcF2iBPgdzyuA7yVChiKzJfA5LqcCRbbKySmQ Ufzcq3gGvNF+rGl2fPlTvSFqF3gpJ8d2MrbQu5i9zdo7L5t71Pz+1KT/kExCwU+4pK6S fc9ye6rk5ElEigOHlSCJKOIzxLQRQjgIXLYMQCllkhq1UXB9moA+a8vN8gdI+PXCcGJs Rq7HD3yAnqUejiALZxf3AdS0pfr3wSWn0P3Arci49StrunqhBietM/7qtgQWdYq9TEeF +yMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=TjBLCmCZ57/NOoQt1XH1nTIBrrDoDRpnXc5o7McQ4zI=; b=Vr2cUiG0Dz1gkCJY5KEx6kVF4Y3dcp+XK3EnrTWzsiSCE6St3i7k3In/4Y2YwsRs2V aLcPGYiYJ8/DZDiVjMWTsx7+FlKpsJc7gNntKt+OYxCZhlN/BxEZNOvmbZZtfZxYlPGh ytdUvhDwB3O+z0g5ga5jaFncteDgEU/Y8f5AcHAtf57lwfNJvulPCN4uIjmNFhXwO5JC mEdwF5TYIApTnjpvPjMFjehvtdU6bzEIw+ntEdLI//RMHGAkE1aZ+NMej++TCpPSruf2 bAIxLcyjWe4ZKmNKREtQd9DpkY0OqYHPCvGuEkpnNkuNEooWZmOsI5TTSFgnUZq+6/Sy c5ig== X-Gm-Message-State: AFeK/H28ns9kVXTQ3CT+T/L5s+bUvlFbiiqVhkmBRA2hnYXVwN3TYA6ySpNoacvdnfY0lg== X-Received: by 10.237.42.98 with SMTP id k31mr2032763qtf.232.1490810504916; Wed, 29 Mar 2017 11:01:44 -0700 (PDT) Received: from localhost.localdomain ([181.231.62.139]) by smtp.gmail.com with ESMTPSA id f128sm5357633qkd.62.2017.03.29.11.01.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 29 Mar 2017 11:01:44 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Wed, 29 Mar 2017 15:01:24 -0300 Message-Id: <20170329180124.7544-1-jamrial@gmail.com> X-Mailer: git-send-email 2.12.1 Subject: [FFmpeg-devel] [PATCH][RFC] avutil/spherical: add a flag to signal tiled/padded projections X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Vittorio Giovara MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" A new field is added to AVSphericalMapping for this purpose, and is used by both Equirectangular and Cubemap projections. This is a replacement for duplicate projection enums like AV_SPHERICAL_EQUIRECTANGULAR_TILE, which are therefore removed. Signed-off-by: James Almer --- This patch depends on the av_spherical_projection_name() patchset for simplicity purposes. Ok, this is an RFC mainly because of the API/ABI break it represents. The AV_SPHERICAL_EQUIRECTANGULAR_TILE projection is a month and a half old and not present in any release, plus a major bump is queued as part of the merges, so i personally think this change is acceptable as is for such an niche and recent feature. If not then i can deprecate said projection enum value instead and keep the current muxer functionality for it for a while. It will need a lot of preprocessor guards, though. The reason for this change is that eventually, a new projection enum for padded cubemap may be suggested with the same arguments as the ones used to introduce the one for tiled equirectangular. Then if any new real projections are added, we'd could end up with duplicate enums for them as well, when setting a single shared flag would be enough. Stereo3D avoided a lot of duplicate types with the inverted flag, so i figured the same should be done here. Improved doxy and/or flag name is extremely welcome (Read: needed). doc/APIchanges | 4 ++++ ffprobe.c | 4 +++- libavformat/dump.c | 6 ++++-- libavformat/matroskadec.c | 11 +++++++---- libavformat/matroskaenc.c | 10 ++++------ libavformat/mov.c | 10 ++++++---- libavformat/movenc.c | 2 -- libavutil/spherical.c | 2 -- libavutil/spherical.h | 28 ++++++++++++++++------------ tests/ref/fate/matroska-spherical-mono | 3 ++- tests/ref/fate/mov-spherical-mono | 3 ++- 11 files changed, 48 insertions(+), 35 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f600777072..7453e80711 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -16,6 +16,10 @@ libavutil: 2015-08-28 API changes, most recent first: 2017-xx-xx - xxxxxxx - lavu 55.xx.xxx - spherical.h + Add flags field to AVSphericalMapping and AV_SPHERICAL_FLAG_CROPPED flag. + Remove AV_SPHERICAL_EQUIRECTANGULAR_TILE AVSphericalProjection. + +2017-xx-xx - xxxxxxx - lavu 55.xx.xxx - spherical.h Add av_spherical_projection_name() 2017-03-xx - xxxxxxx - lavu 55.52.100 - avutil.h diff --git a/ffprobe.c b/ffprobe.c index ad3b77d74d..8e242ed680 100644 --- a/ffprobe.c +++ b/ffprobe.c @@ -1874,11 +1874,13 @@ static void print_pkt_side_data(WriterContext *w, const AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; print_str("projection", av_spherical_projection_name(spherical->projection)); if (spherical->projection == AV_SPHERICAL_CUBEMAP) { + print_int("padded", !!(spherical->flags & AV_SPHERICAL_FLAG_CROPPED)); print_int("padding", spherical->padding); - } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { + } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) { size_t l, t, r, b; av_spherical_tile_bounds(spherical, par->width, par->height, &l, &t, &r, &b); + print_int("tiled", !!(spherical->flags & AV_SPHERICAL_FLAG_CROPPED)); print_int("bound_left", l); print_int("bound_top", t); print_int("bound_right", r); diff --git a/libavformat/dump.c b/libavformat/dump.c index e27d1b9422..37b46ae305 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -356,7 +356,6 @@ static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData * av_log(ctx, AV_LOG_INFO, "%s", av_spherical_projection_name(spherical->projection)); if (spherical->projection != AV_SPHERICAL_EQUIRECTANGULAR && - spherical->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE && spherical->projection != AV_SPHERICAL_CUBEMAP) { return; } @@ -366,7 +365,10 @@ static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData * roll = ((double)spherical->roll) / (1 << 16); av_log(ctx, AV_LOG_INFO, " (%f/%f/%f) ", yaw, pitch, roll); - if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) { + if (!(spherical->flags & AV_SPHERICAL_FLAG_CROPPED)) + return; + + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) { size_t l, t, r, b; av_spherical_tile_bounds(spherical, par->width, par->height, &l, &t, &r, &b); diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 2e2a814b4f..9e1b5f8d45 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1915,7 +1915,7 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) size_t spherical_size; uint32_t l = 0, t = 0, r = 0, b = 0; uint32_t padding = 0; - int ret; + int ret, flags = 0; GetByteContext gb; bytestream2_init(&gb, track->video.projection.private.data, @@ -1930,6 +1930,7 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) switch (track->video.projection.type) { case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: + projection = AV_SPHERICAL_EQUIRECTANGULAR; if (track->video.projection.private.size == 20) { t = bytestream2_get_be32(&gb); b = bytestream2_get_be32(&gb); @@ -1949,9 +1950,7 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) } if (l || t || r || b) - projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE; - else - projection = AV_SPHERICAL_EQUIRECTANGULAR; + flags |= AV_SPHERICAL_FLAG_CROPPED; break; case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP: if (track->video.projection.private.size < 4) { @@ -1966,6 +1965,9 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) } projection = AV_SPHERICAL_CUBEMAP; padding = bytestream2_get_be32(&gb); + + if (padding) + flags |= AV_SPHERICAL_FLAG_CROPPED; } else { av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); return AVERROR_INVALIDDATA; @@ -1979,6 +1981,7 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) if (!spherical) return AVERROR(ENOMEM); spherical->projection = projection; + spherical->flags = flags; spherical->yaw = (int32_t)(track->video.projection.yaw * (1 << 16)); spherical->pitch = (int32_t)(track->video.projection.pitch * (1 << 16)); diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index af941ceb8f..0adbe3b46b 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -936,17 +936,15 @@ static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, AVStr switch (spherical->projection) { case AV_SPHERICAL_EQUIRECTANGULAR: - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, - MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); - break; - case AV_SPHERICAL_EQUIRECTANGULAR_TILE: { AVIOContext b; uint8_t private[20]; - ffio_init_context(&b, private, sizeof(private), - 1, NULL, NULL, NULL, NULL); put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); + if (!(spherical->flags & AV_SPHERICAL_FLAG_CROPPED)) + break; + ffio_init_context(&b, private, sizeof(private), + 1, NULL, NULL, NULL, NULL); avio_wb32(&b, 0); // version + flags avio_wb32(&b, spherical->bound_top); avio_wb32(&b, spherical->bound_bottom); diff --git a/libavformat/mov.c b/libavformat/mov.c index 127aec1d1d..3bbf3507d1 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4634,7 +4634,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; MOVStreamContext *sc; - int size, layout; + int size, layout, flags = 0; int32_t yaw, pitch, roll; uint32_t l = 0, t = 0, r = 0, b = 0; uint32_t tag, padding = 0; @@ -4705,6 +4705,8 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) } projection = AV_SPHERICAL_CUBEMAP; padding = avio_rb32(pb); + if (padding) + flags |= AV_SPHERICAL_FLAG_CROPPED; break; case MKTAG('e','q','u','i'): t = avio_rb32(pb); @@ -4719,10 +4721,9 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_INVALIDDATA; } + projection = AV_SPHERICAL_EQUIRECTANGULAR; if (l || t || r || b) - projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE; - else - projection = AV_SPHERICAL_EQUIRECTANGULAR; + flags |= AV_SPHERICAL_FLAG_CROPPED; break; default: av_log(c->fc, AV_LOG_ERROR, "Unknown projection type\n"); @@ -4734,6 +4735,7 @@ static int mov_read_sv3d(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR(ENOMEM); sc->spherical->projection = projection; + sc->spherical->flags = flags; sc->spherical->yaw = yaw; sc->spherical->pitch = pitch; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a54aa879e9..fd96701d11 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1640,7 +1640,6 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT; if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR && - spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE && spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) { av_log(pb, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection); return 0; @@ -1670,7 +1669,6 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa switch (spherical_mapping->projection) { case AV_SPHERICAL_EQUIRECTANGULAR: - case AV_SPHERICAL_EQUIRECTANGULAR_TILE: avio_wb32(pb, 28); /* size */ ffio_wfourcc(pb, "equi"); avio_wb32(pb, 0); /* version = 0 & flags = 0 */ diff --git a/libavutil/spherical.c b/libavutil/spherical.c index 1d06e7c552..29a386787e 100644 --- a/libavutil/spherical.c +++ b/libavutil/spherical.c @@ -54,8 +54,6 @@ void av_spherical_tile_bounds(const AVSphericalMapping *map, static const char *spherical_projection_names[] = { [AV_SPHERICAL_EQUIRECTANGULAR] = "equirectangular", [AV_SPHERICAL_CUBEMAP] = "cubemap", - [AV_SPHERICAL_EQUIRECTANGULAR_TILE] = "tiled equirectangular", - }; const char *av_spherical_projection_name(enum AVSphericalProjection projection) diff --git a/libavutil/spherical.h b/libavutil/spherical.h index 2c8dd3cd97..e628c3621a 100644 --- a/libavutil/spherical.h +++ b/libavutil/spherical.h @@ -63,16 +63,14 @@ enum AVSphericalProjection { * to the back. */ AV_SPHERICAL_CUBEMAP, - - /** - * Video represents a portion of a sphere mapped on a flat surface - * using equirectangular projection. The @ref bounding fields indicate - * the position of the current video in a larger surface. - */ - AV_SPHERICAL_EQUIRECTANGULAR_TILE, }; /** + * Projection has padding/cropping + */ +#define AV_SPHERICAL_FLAG_CROPPED (1 << 0) + +/** * This structure describes how to handle spherical videos, outlining * information about projection, initial layout, and any other view modifier. * @@ -160,9 +158,10 @@ typedef struct AVSphericalMapping { * original_height = tile->height + bound_top + bound_bottom; * @endcode * - * @note These values are valid only for the tiled equirectangular - * projection type (@ref AV_SPHERICAL_EQUIRECTANGULAR_TILE), - * and should be ignored in all other cases. + * @note These values are valid only for the equirectangular projection + * type (@ref AV_SPHERICAL_EQUIRECTANGULAR) when the + * (@ref AV_SPHERICAL_FLAG_CROPPED) flag is set, and should be + * ignored in all other cases. */ uint32_t bound_left; ///< Distance from the left edge uint32_t bound_top; ///< Distance from the top edge @@ -176,10 +175,15 @@ typedef struct AVSphericalMapping { * Number of pixels to pad from the edge of each cube face. * * @note This value is valid for only for the cubemap projection type - * (@ref AV_SPHERICAL_CUBEMAP), and should be ignored in all other - * cases. + * (@ref AV_SPHERICAL_CUBEMAP) when the (@ref AV_SPHERICAL_FLAG_CROPPED) + * flag is set, and should be ignored in all other cases. */ uint32_t padding; + + /** + * Additional information about the projection. + */ + int flags; } AVSphericalMapping; /** diff --git a/tests/ref/fate/matroska-spherical-mono b/tests/ref/fate/matroska-spherical-mono index bd57d94514..078c7f5248 100644 --- a/tests/ref/fate/matroska-spherical-mono +++ b/tests/ref/fate/matroska-spherical-mono @@ -6,7 +6,8 @@ inverted=0 [/SIDE_DATA] [SIDE_DATA] side_data_type=Spherical Mapping -projection=tiled equirectangular +projection=equirectangular +tiled=1 bound_left=148 bound_top=73 bound_right=147 diff --git a/tests/ref/fate/mov-spherical-mono b/tests/ref/fate/mov-spherical-mono index bd57d94514..078c7f5248 100644 --- a/tests/ref/fate/mov-spherical-mono +++ b/tests/ref/fate/mov-spherical-mono @@ -6,7 +6,8 @@ inverted=0 [/SIDE_DATA] [SIDE_DATA] side_data_type=Spherical Mapping -projection=tiled equirectangular +projection=equirectangular +tiled=1 bound_left=148 bound_top=73 bound_right=147