From patchwork Wed Aug 14 01:14:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugene Lyapustin X-Patchwork-Id: 14492 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 5FC394498E7 for ; Wed, 14 Aug 2019 04:19:52 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3DAE668A324; Wed, 14 Aug 2019 04:19:52 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lj1-f193.google.com (mail-lj1-f193.google.com [209.85.208.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E143C6802F5 for ; Wed, 14 Aug 2019 04:19:45 +0300 (EEST) Received: by mail-lj1-f193.google.com with SMTP id z17so14834908ljz.0 for ; Tue, 13 Aug 2019 18:19:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=OejlR6Hu2MZfSKfDRoqYbYHjfB10FTiwO59VcKal5uc=; b=FYC3WLuVga8AU/cQ3UcOZdishP/o5M3zILWYJn+1eJObAIGeBvhu2JP4oOu33Q2bFe v1esEcbBt1qj9lu4aGQn5xEIMZ/LaaLiB/V+2UFlsWg8xKh55MISi0K9czN1UO9ADmHz /4KZpsPdXr+kEu8DP+w28LBui1D62+iuZfzwKo/AlMaGyuAuBOiBCvihXbVt7RzoCPae LBbyiNn4HRETKyaQiQkFp6NyhJC5gWjPLGqA/Pqbzl0Pn532Kzp1i02jL5azaiyTOoEa 11l2iKSHv++Pv2I3Aq7cimL1JN4OrWeE+FWsamL+S0U8KTVKPjr/mr+QnMxJzR5Lyuod GItg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=OejlR6Hu2MZfSKfDRoqYbYHjfB10FTiwO59VcKal5uc=; b=NOk1HPj4tru2n/o7sO0R79mBFtyvB7lb44xcBSPPIojI4KoImoeEB/5QNNbmE3od4V MyuwYfRS/u+MT+3/8JAJg/jzo893DNeVQ3OS6MeJD+8KUu5zcvxsLO8M/9JGnd0sOlh/ 9Iy0Ap3v6kgrDTt54MA4R0dt0Mv6uzFWejo5ZaEZBhZEdzc/Wzc1pc1jOX/wRecAkpY/ s3S+7NH2Pe3vifMDCDXio2I944FyIxtJsuDd0tJJ8Q5qHy6Wnx8ZyGxPQMDDgVi025ST YJTTDiDChjChcpxBlcWBz+Wxk7ADEt/Smdm1evbpkNgxpfJGdS6El52v4QWWEu3xfkrK nk3g== X-Gm-Message-State: APjAAAWvfVR7CqICbWZbgckxdUHpXN/dTHDJVAkZIjihAntqTUuqlOTi sCGlwI2BEm21Ka02Bsr3yyGt5H8DUFo= X-Google-Smtp-Source: APXvYqyqlw0NzRYA98eHMmxlUQ8P1hsJ7XhFggsvlXK4LECNj35e/4GNqxXLQCLrVnr5yYBcjFr93A== X-Received: by 2002:a2e:a0d1:: with SMTP id f17mr2622199ljm.106.1565745252058; Tue, 13 Aug 2019 18:14:12 -0700 (PDT) Received: from unis-note.localdomain ([176.109.79.157]) by smtp.gmail.com with ESMTPSA id k124sm19966197lfd.60.2019.08.13.18.14.11 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 13 Aug 2019 18:14:11 -0700 (PDT) From: Eugene Lyapustin To: ffmpeg-devel@ffmpeg.org Date: Wed, 14 Aug 2019 04:14:04 +0300 Message-Id: <20190814011405.11354-2-unishifft@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190814011405.11354-1-unishifft@gmail.com> References: <20190814011405.11354-1-unishifft@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 2/3] avfilter/vf_v360: add padding option for cubemap 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Eugene Lyapustin --- doc/filters.texi | 18 +++++++- libavfilter/vf_v360.c | 100 ++++++++++++++++++++++++++++++++---------- 2 files changed, 93 insertions(+), 25 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 6168a3502a..6c70ffceb1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17905,6 +17905,20 @@ Cubemap with 3x2/6x1 layout. Format specific options: @table @option +@item in_pad +@item out_pad +Set padding proprtion for the input/output cubemap. Values in decimals. + +Example values: +@table @samp +@item 0 +No padding. +@item 0.01 +1% of face is padding. For example, with 1920x1280 resolution face size would be 640x640 and padding would be 3 pixels from each side. (640 * 0.01 = 6 pixels) +@end table + +Default value is @b{@samp{0}}. + @item in_forder @item out_forder Set order of faces for the input/output cubemap. Choose one direction for each position. @@ -18005,9 +18019,9 @@ Flip the output video horizontally/vertically/in-depth. Boolean values. @itemize @item -Convert equirectangular video to cubemap with 3x2 layout using bicubic interpolation: +Convert equirectangular video to cubemap with 3x2 layout and 1% padding using bicubic interpolation: @example -ffmpeg -i input.mkv -vf v360=e:c3x2:cubic output.mkv +ffmpeg -i input.mkv -vf v360=e:c3x2:cubic:out_pad=0.01 output.mkv @end example @item Extract back view of Equi-Angular Cubemap: diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index 5c377827b0..3c69f2cf3d 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -102,6 +102,8 @@ typedef struct V360Context { int in_cubemap_face_rotation[6]; int out_cubemap_face_rotation[6]; + float in_pad, out_pad; + float yaw, pitch, roll; int h_flip, v_flip, d_flip; @@ -155,6 +157,8 @@ static const AVOption v360_options[] = { {"out_forder", "output cubemap face order", OFFSET(out_forder), AV_OPT_TYPE_STRING, {.str="rludfb"}, 0, NB_DIRECTIONS-1, FLAGS, "out_forder"}, { "in_frot", "input cubemap face rotation", OFFSET(in_frot), AV_OPT_TYPE_STRING, {.str="000000"}, 0, NB_DIRECTIONS-1, FLAGS, "in_frot"}, { "out_frot", "output cubemap face rotation",OFFSET(out_frot), AV_OPT_TYPE_STRING, {.str="000000"}, 0, NB_DIRECTIONS-1, FLAGS, "out_frot"}, + { "in_pad", "input cubemap pads", OFFSET(in_pad), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 1.f, FLAGS, "in_pad"}, + { "out_pad", "output cubemap pads", OFFSET(out_pad), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 1.f, FLAGS, "out_pad"}, { "yaw", "yaw rotation", OFFSET(yaw), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "yaw"}, { "pitch", "pitch rotation", OFFSET(pitch), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "pitch"}, { "roll", "roll rotation", OFFSET(roll), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "roll"}, @@ -734,6 +738,9 @@ static void cube_to_xyz(const V360Context *s, float norm; float l_x, l_y, l_z; + uf /= (1.f - s->out_pad); + vf /= (1.f - s->out_pad); + rotate_cube_face_inverse(&uf, &vf, s->out_cubemap_face_rotation[face]); switch (direction) { @@ -1091,6 +1098,9 @@ static void xyz_to_cube3x2(const V360Context *s, xyz_to_cube(s, vec, &uf, &vf, &direction); + uf *= (1.f - s->in_pad); + vf *= (1.f - s->in_pad); + face = s->in_cubemap_face_order[direction]; u_face = face % 3; v_face = face / 3; @@ -1108,22 +1118,44 @@ static void xyz_to_cube3x2(const V360Context *s, for (i = -1; i < 3; i++) { for (j = -1; j < 3; j++) { - float u, v; + int new_ui = ui + j; + int new_vi = vi + i; int u_shift, v_shift; int new_ewi, new_ehi; - process_cube_coordinates(s, 2.f * (ui + j) / ewi - 1.f, - 2.f * (vi + i) / ehi - 1.f, - direction, &u, &v, &face); - u_face = face % 3; - v_face = face / 3; - u_shift = ceilf(ew * u_face); - v_shift = ceilf(eh * v_face); - new_ewi = ceilf(ew * (u_face + 1)) - u_shift; - new_ehi = ceilf(eh * (v_face + 1)) - v_shift; - - us[i + 1][j + 1] = u_shift + av_clip(roundf(0.5f * new_ewi * (u + 1.f)), 0, new_ewi - 1); - vs[i + 1][j + 1] = v_shift + av_clip(roundf(0.5f * new_ehi * (v + 1.f)), 0, new_ehi - 1); + if (new_ui >= 0 && new_ui < ewi && new_vi >= 0 && new_vi < ehi) { + face = s->in_cubemap_face_order[direction]; + + u_face = face % 3; + v_face = face / 3; + u_shift = ceilf(ew * u_face); + v_shift = ceilf(eh * v_face); + } else { + uf = 2.f * new_ui / ewi - 1.f; + vf = 2.f * new_vi / ehi - 1.f; + + uf /= (1.f - s->in_pad); + vf /= (1.f - s->in_pad); + + process_cube_coordinates(s, uf, vf, direction, &uf, &vf, &face); + + uf *= (1.f - s->in_pad); + vf *= (1.f - s->in_pad); + + u_face = face % 3; + v_face = face / 3; + u_shift = ceilf(ew * u_face); + v_shift = ceilf(eh * v_face); + new_ewi = ceilf(ew * (u_face + 1)) - u_shift; + new_ehi = ceilf(eh * (v_face + 1)) - v_shift; + + new_ui = av_clip(roundf(0.5f * new_ewi * (uf + 1.f)), 0, new_ewi - 1); + new_vi = av_clip(roundf(0.5f * new_ehi * (vf + 1.f)), 0, new_ehi - 1); + } + + + us[i + 1][j + 1] = u_shift + new_ui; + vs[i + 1][j + 1] = v_shift + new_vi; } } } @@ -1173,7 +1205,7 @@ static void xyz_to_cube6x1(const V360Context *s, uint16_t us[4][4], uint16_t vs[4][4], float *du, float *dv) { const float ew = width / 6.f; - const float eh = height; + const int ehi = height; float uf, vf; int ui, vi; int ewi; @@ -1182,11 +1214,14 @@ static void xyz_to_cube6x1(const V360Context *s, xyz_to_cube(s, vec, &uf, &vf, &direction); + uf *= (1.f - s->in_pad); + vf *= (1.f - s->in_pad); + face = s->in_cubemap_face_order[direction]; ewi = ceilf(ew * (face + 1)) - ceilf(ew * face); uf = 0.5f * ewi * (uf + 1.f); - vf = 0.5f * eh * (vf + 1.f); + vf = 0.5f * ehi * (vf + 1.f); ui = floorf(uf); vi = floorf(vf); @@ -1196,18 +1231,37 @@ static void xyz_to_cube6x1(const V360Context *s, for (i = -1; i < 3; i++) { for (j = -1; j < 3; j++) { - float u, v; + int new_ui = ui + j; + int new_vi = vi + i; int u_shift; int new_ewi; - process_cube_coordinates(s, 2.f * (ui + j) / ewi - 1.f, - 2.f * (vi + i) / eh - 1.f, - direction, &u, &v, &face); - u_shift = ceilf(ew * face); - new_ewi = ceilf(ew * (face + 1)) - u_shift; + if (new_ui >= 0 && new_ui < ewi && new_vi >= 0 && new_vi < ehi) { + face = s->in_cubemap_face_order[direction]; + + u_shift = ceilf(ew * face); + } else { + uf = 2.f * new_ui / ewi - 1.f; + vf = 2.f * new_vi / ehi - 1.f; + + uf /= (1.f - s->in_pad); + vf /= (1.f - s->in_pad); + + process_cube_coordinates(s, uf, vf, direction, &uf, &vf, &face); + + uf *= (1.f - s->in_pad); + vf *= (1.f - s->in_pad); + + u_shift = ceilf(ew * face); + new_ewi = ceilf(ew * (face + 1)) - u_shift; + + new_ui = av_clip(roundf(0.5f * new_ewi * (uf + 1.f)), 0, new_ewi - 1); + new_vi = av_clip(roundf(0.5f * ehi * (vf + 1.f)), 0, ehi - 1); + } + - us[i + 1][j + 1] = u_shift + av_clip(roundf(0.5f * new_ewi * (u + 1.f)), 0, new_ewi - 1); - vs[i + 1][j + 1] = av_clip(roundf(0.5f * eh * (v + 1.f)), 0, eh - 1); + us[i + 1][j + 1] = u_shift + new_ui; + vs[i + 1][j + 1] = new_vi; } } }