mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-29 19:02:21 +00:00
avfilter/vf_v360: add padding option for cubemap
Signed-off-by: Eugene Lyapustin <unishifft@gmail.com>
This commit is contained in:
parent
b26094e217
commit
d044252aac
@ -17917,6 +17917,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.
|
||||
@ -18017,9 +18031,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:
|
||||
|
@ -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;
|
||||
if (new_ui >= 0 && new_ui < ewi && new_vi >= 0 && new_vi < ehi) {
|
||||
face = s->in_cubemap_face_order[direction];
|
||||
|
||||
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);
|
||||
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];
|
||||
|
||||
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);
|
||||
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 + new_ui;
|
||||
vs[i + 1][j + 1] = new_vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user