[FFmpeg-devel] [PATCH v2 2/3] avfilter/vf_v360: add padding option for cubemap
Eugene Lyapustin
unishifft at gmail.com
Wed Aug 14 04:14:04 EEST 2019
Signed-off-by: Eugene Lyapustin <unishifft at gmail.com>
---
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
+ at item in_pad
+ at item out_pad
+Set padding proprtion for the input/output cubemap. Values in decimals.
+
+Example values:
+ at table @samp
+ at item 0
+No padding.
+ at 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)
+ at 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;
}
}
}
--
2.22.0
More information about the ffmpeg-devel
mailing list