avfilter/vf_v360: simplify input flipping

This commit is contained in:
Paul B Mahol 2020-09-29 14:16:32 +02:00
parent 86b29c0cd0
commit 12585c87e6
2 changed files with 69 additions and 95 deletions

View File

@ -151,7 +151,6 @@ typedef struct V360Context {
float rot_mat[3][3];
float input_mirror_modifier[2];
float output_mirror_modifier[3];
int in_width, in_height;

View File

@ -1111,9 +1111,6 @@ static void xyz_to_cube(const V360Context *s,
face = s->in_cubemap_face_order[*direction];
rotate_cube_face(uf, vf, s->in_cubemap_face_rotation[face]);
(*uf) *= s->input_mirror_modifier[0];
(*vf) *= s->input_mirror_modifier[1];
}
/**
@ -1804,8 +1801,8 @@ static int xyz_to_stereographic(const V360Context *s,
const float theta = acosf(vec[2]);
const float r = tanf(theta * 0.5f);
const float c = r / hypotf(vec[0], vec[1]);
const float x = vec[0] * c / s->iflat_range[0] * s->input_mirror_modifier[0];
const float y = vec[1] * c / s->iflat_range[1] * s->input_mirror_modifier[1];
const float x = vec[0] * c / s->iflat_range[0];
const float y = vec[1] * c / s->iflat_range[1];
const float uf = (x + 1.f) * width / 2.f;
const float vf = (y + 1.f) * height / 2.f;
@ -1910,8 +1907,8 @@ static int xyz_to_equisolid(const V360Context *s,
const float theta = acosf(vec[2]);
const float r = sinf(theta * 0.5f);
const float c = r / hypotf(vec[0], vec[1]);
const float x = vec[0] * c / s->iflat_range[0] * s->input_mirror_modifier[0];
const float y = vec[1] * c / s->iflat_range[1] * s->input_mirror_modifier[1];
const float x = vec[0] * c / s->iflat_range[0];
const float y = vec[1] * c / s->iflat_range[1];
const float uf = (x + 1.f) * width / 2.f;
const float vf = (y + 1.f) * height / 2.f;
@ -2015,8 +2012,8 @@ static int xyz_to_orthographic(const V360Context *s,
const float theta = acosf(vec[2]);
const float r = sinf(theta);
const float c = r / hypotf(vec[0], vec[1]);
const float x = vec[0] * c / s->iflat_range[0] * s->input_mirror_modifier[0];
const float y = vec[1] * c / s->iflat_range[1] * s->input_mirror_modifier[1];
const float x = vec[0] * c / s->iflat_range[0];
const float y = vec[1] * c / s->iflat_range[1];
const float uf = (x + 1.f) * width / 2.f;
const float vf = (y + 1.f) * height / 2.f;
@ -2055,8 +2052,8 @@ static int xyz_to_equirect(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]);
const float theta = asinf(vec[1]);
const float uf = (phi / M_PI + 1.f) * width / 2.f;
const float vf = (theta / M_PI_2 + 1.f) * height / 2.f;
@ -2093,8 +2090,8 @@ static int xyz_to_hequirect(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]);
const float theta = asinf(vec[1]);
const float uf = (phi / M_PI_2 + 1.f) * width / 2.f;
const float vf = (theta / M_PI_2 + 1.f) * height / 2.f;
@ -2156,8 +2153,8 @@ static int xyz_to_flat(const V360Context *s,
const float zf = vec[2];
const float h = hypotf(vec[0], vec[1]);
const float c = h <= 1e-6f ? 1.f : rr / h;
float uf = vec[0] * c / s->iflat_range[0] * s->input_mirror_modifier[0];
float vf = vec[1] * c / s->iflat_range[1] * s->input_mirror_modifier[1];
float uf = vec[0] * c / s->iflat_range[0];
float vf = vec[1] * c / s->iflat_range[1];
int visible, ui, vi;
uf = zf >= 0.f ? (uf + 1.f) * width / 2.f : 0.f;
@ -2197,8 +2194,8 @@ static int xyz_to_mercator(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = vec[1] * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]);
const float theta = vec[1];
const float uf = (phi / M_PI + 1.f) * width / 2.f;
const float vf = (av_clipf(logf((1.f + theta) / (1.f - theta)) / (2.f * M_PI), -1.f, 1.f) + 1.f) * height / 2.f;
@ -2268,8 +2265,8 @@ static int xyz_to_ball(const V360Context *s,
const float l = hypotf(vec[0], vec[1]);
const float r = sqrtf(1.f - vec[2]) / M_SQRT2;
const float uf = (1.f + r * vec[0] * s->input_mirror_modifier[0] / (l > 0.f ? l : 1.f)) * width * 0.5f;
const float vf = (1.f + r * vec[1] * s->input_mirror_modifier[1] / (l > 0.f ? l : 1.f)) * height * 0.5f;
const float uf = (1.f + r * vec[0] / (l > 0.f ? l : 1.f)) * width * 0.5f;
const float vf = (1.f + r * vec[1] / (l > 0.f ? l : 1.f)) * height * 0.5f;
const int ui = floorf(uf);
const int vi = floorf(vf);
@ -2376,11 +2373,11 @@ static int xyz_to_hammer(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float theta = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = atan2f(vec[0], vec[2]);
const float z = sqrtf(1.f + sqrtf(1.f - vec[1] * vec[1]) * cosf(theta * 0.5f));
const float x = sqrtf(1.f - vec[1] * vec[1]) * sinf(theta * 0.5f) / z;
const float y = vec[1] / z * s->input_mirror_modifier[1];
const float y = vec[1] / z;
const float uf = (x + 1.f) * width / 2.f;
const float vf = (y + 1.f) * height / 2.f;
@ -2448,8 +2445,8 @@ static int xyz_to_sinusoidal(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0] * cosf(theta);
const float theta = asinf(vec[1]);
const float phi = atan2f(vec[0], vec[2]) * cosf(theta);
const float uf = (phi / M_PI + 1.f) * width / 2.f;
const float vf = (theta / M_PI_2 + 1.f) * height / 2.f;
@ -2481,51 +2478,19 @@ static int prepare_eac_in(AVFilterContext *ctx)
{
V360Context *s = ctx->priv;
if (s->ih_flip && s->iv_flip) {
s->in_cubemap_face_order[RIGHT] = BOTTOM_LEFT;
s->in_cubemap_face_order[LEFT] = BOTTOM_RIGHT;
s->in_cubemap_face_order[UP] = TOP_LEFT;
s->in_cubemap_face_order[DOWN] = TOP_RIGHT;
s->in_cubemap_face_order[FRONT] = BOTTOM_MIDDLE;
s->in_cubemap_face_order[BACK] = TOP_MIDDLE;
} else if (s->ih_flip) {
s->in_cubemap_face_order[RIGHT] = TOP_LEFT;
s->in_cubemap_face_order[LEFT] = TOP_RIGHT;
s->in_cubemap_face_order[UP] = BOTTOM_LEFT;
s->in_cubemap_face_order[DOWN] = BOTTOM_RIGHT;
s->in_cubemap_face_order[FRONT] = TOP_MIDDLE;
s->in_cubemap_face_order[BACK] = BOTTOM_MIDDLE;
} else if (s->iv_flip) {
s->in_cubemap_face_order[RIGHT] = BOTTOM_RIGHT;
s->in_cubemap_face_order[LEFT] = BOTTOM_LEFT;
s->in_cubemap_face_order[UP] = TOP_RIGHT;
s->in_cubemap_face_order[DOWN] = TOP_LEFT;
s->in_cubemap_face_order[FRONT] = BOTTOM_MIDDLE;
s->in_cubemap_face_order[BACK] = TOP_MIDDLE;
} else {
s->in_cubemap_face_order[RIGHT] = TOP_RIGHT;
s->in_cubemap_face_order[LEFT] = TOP_LEFT;
s->in_cubemap_face_order[UP] = BOTTOM_RIGHT;
s->in_cubemap_face_order[DOWN] = BOTTOM_LEFT;
s->in_cubemap_face_order[FRONT] = TOP_MIDDLE;
s->in_cubemap_face_order[BACK] = BOTTOM_MIDDLE;
}
s->in_cubemap_face_order[RIGHT] = TOP_RIGHT;
s->in_cubemap_face_order[LEFT] = TOP_LEFT;
s->in_cubemap_face_order[UP] = BOTTOM_RIGHT;
s->in_cubemap_face_order[DOWN] = BOTTOM_LEFT;
s->in_cubemap_face_order[FRONT] = TOP_MIDDLE;
s->in_cubemap_face_order[BACK] = BOTTOM_MIDDLE;
if (s->iv_flip) {
s->in_cubemap_face_rotation[TOP_LEFT] = ROT_270;
s->in_cubemap_face_rotation[TOP_MIDDLE] = ROT_90;
s->in_cubemap_face_rotation[TOP_RIGHT] = ROT_270;
s->in_cubemap_face_rotation[BOTTOM_LEFT] = ROT_0;
s->in_cubemap_face_rotation[BOTTOM_MIDDLE] = ROT_0;
s->in_cubemap_face_rotation[BOTTOM_RIGHT] = ROT_0;
} else {
s->in_cubemap_face_rotation[TOP_LEFT] = ROT_0;
s->in_cubemap_face_rotation[TOP_MIDDLE] = ROT_0;
s->in_cubemap_face_rotation[TOP_RIGHT] = ROT_0;
s->in_cubemap_face_rotation[BOTTOM_LEFT] = ROT_270;
s->in_cubemap_face_rotation[BOTTOM_MIDDLE] = ROT_90;
s->in_cubemap_face_rotation[BOTTOM_RIGHT] = ROT_270;
}
s->in_cubemap_face_rotation[TOP_LEFT] = ROT_0;
s->in_cubemap_face_rotation[TOP_MIDDLE] = ROT_0;
s->in_cubemap_face_rotation[TOP_RIGHT] = ROT_0;
s->in_cubemap_face_rotation[BOTTOM_LEFT] = ROT_270;
s->in_cubemap_face_rotation[BOTTOM_MIDDLE] = ROT_90;
s->in_cubemap_face_rotation[BOTTOM_RIGHT] = ROT_270;
return 0;
}
@ -2852,8 +2817,8 @@ static int xyz_to_fisheye(const V360Context *s,
const float lh = h > 0.f ? h : 1.f;
const float phi = atan2f(h, vec[2]) / M_PI;
float uf = vec[0] / lh * phi * s->input_mirror_modifier[0] / s->iflat_range[0];
float vf = vec[1] / lh * phi * s->input_mirror_modifier[1] / s->iflat_range[1];
float uf = vec[0] / lh * phi / s->iflat_range[0];
float vf = vec[1] / lh * phi / s->iflat_range[1];
const int visible = hypotf(uf, vf) <= 0.5f;
int ui, vi;
@ -2927,8 +2892,8 @@ static int xyz_to_pannini(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]);
const float theta = asinf(vec[1]);
const float d = s->ih_fov;
const float S = (d + 1.f) / (d + cosf(phi));
@ -3041,8 +3006,8 @@ static int xyz_to_cylindrical(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0] / s->iflat_range[0];
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]) / s->iflat_range[0];
const float theta = asinf(vec[1]);
const float uf = (phi + 1.f) * (width - 1) / 2.f;
const float vf = (tanf(theta) / s->iflat_range[1] + 1.f) * height / 2.f;
@ -3169,13 +3134,13 @@ static int xyz_to_tetrahedron(const V360Context *s,
y = vec[1] / d;
z = -vec[2] / d;
vf = 0.5f - y * 0.5f * s->input_mirror_modifier[1];
vf = 0.5f - y * 0.5f;
if ((x + y >= 0.f && y + z >= 0.f && -z - x <= 0.f) ||
(x + y <= 0.f && -y + z >= 0.f && z - x >= 0.f)) {
uf = 0.25f * x * s->input_mirror_modifier[0] + 0.25f;
uf = 0.25f * x + 0.25f;
} else {
uf = 0.75f - 0.25f * x * s->input_mirror_modifier[0];
uf = 0.75f - 0.25f * x;
}
uf *= width;
@ -3259,8 +3224,8 @@ static int xyz_to_dfisheye(const V360Context *s,
const float lh = h > 0.f ? h : 1.f;
const float theta = acosf(fabsf(vec[2])) / M_PI;
float uf = (theta * (vec[0] / lh) * s->input_mirror_modifier[0] / s->iflat_range[0] + 0.5f) * ew;
float vf = (theta * (vec[1] / lh) * s->input_mirror_modifier[1] / s->iflat_range[1] + 0.5f) * eh;
float uf = (theta * (vec[0] / lh) / s->iflat_range[0] + 0.5f) * ew;
float vf = (theta * (vec[1] / lh) / s->iflat_range[1] + 0.5f) * eh;
int ui, vi;
int u_shift;
@ -3378,8 +3343,8 @@ static int xyz_to_barrel(const V360Context *s,
{
const float scale = 0.99f;
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]);
const float theta = asinf(vec[1]);
const float theta_range = M_PI_4;
int ew, eh;
@ -3391,7 +3356,7 @@ static int xyz_to_barrel(const V360Context *s,
ew = 4 * width / 5;
eh = height;
u_shift = s->ih_flip ? width / 5 : 0;
u_shift = 0;
v_shift = 0;
uf = (phi / M_PI * scale + 1.f) * ew / 2.f;
@ -3400,7 +3365,7 @@ static int xyz_to_barrel(const V360Context *s,
ew = width / 5;
eh = height / 2;
u_shift = s->ih_flip ? 0 : 4 * ew;
u_shift = 4 * ew;
if (theta < 0.f) { // UP
uf = -vec[0] / vec[1];
@ -3412,9 +3377,6 @@ static int xyz_to_barrel(const V360Context *s,
v_shift = eh;
}
uf *= s->input_mirror_modifier[0] * s->input_mirror_modifier[1];
vf *= s->input_mirror_modifier[1];
uf = 0.5f * ew * (uf * scale + 1.f);
vf = 0.5f * eh * (vf * scale + 1.f);
}
@ -3451,8 +3413,8 @@ static int xyz_to_barrelsplit(const V360Context *s,
const float *vec, int width, int height,
int16_t us[4][4], int16_t vs[4][4], float *du, float *dv)
{
const float phi = atan2f(vec[0], vec[2]) * s->input_mirror_modifier[0];
const float theta = asinf(vec[1]) * s->input_mirror_modifier[1];
const float phi = atan2f(vec[0], vec[2]);
const float theta = asinf(vec[1]);
const float theta_range = M_PI_4;
@ -3468,7 +3430,7 @@ static int xyz_to_barrelsplit(const V360Context *s,
ew = width / 3 * 2;
eh = height / 2;
u_shift = s->ih_flip ? width / 3 : 0;
u_shift = 0;
v_shift = phi >= M_PI_2 || phi < -M_PI_2 ? eh : 0;
uf = fmodf(phi, M_PI_2) / M_PI_2;
@ -3487,7 +3449,7 @@ static int xyz_to_barrelsplit(const V360Context *s,
ew = width / 3;
eh = height / 4;
u_shift = s->ih_flip ? 0 : 2 * ew;
u_shift = 2 * ew;
if (theta <= 0.f && theta >= -M_PI_2 &&
phi <= M_PI_2 && phi >= -M_PI_2) {
@ -3511,9 +3473,6 @@ static int xyz_to_barrelsplit(const V360Context *s,
v_shift = height * 0.75f;
}
uf *= s->input_mirror_modifier[0] * s->input_mirror_modifier[1];
vf *= s->input_mirror_modifier[1];
uf = 0.5f * width / 3.f * (uf * scalew + 1.f);
vf = height * 0.25f * (vf * scaleh + 1.f) + v_offset;
}
@ -3921,6 +3880,23 @@ static inline void mirror(const float *modifier, float *vec)
vec[2] *= modifier[2];
}
static inline void input_flip(int16_t u[4][4], int16_t v[4][4], int w, int h, int hflip, int vflip)
{
if (hflip) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
u[i][j] = w - 1 - u[i][j];
}
}
if (vflip) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
v[i][j] = h - 1 - v[i][j];
}
}
}
static int allocate_plane(V360Context *s, int sizeof_uv, int sizeof_ker, int sizeof_mask, int p)
{
const int pr_height = s->pr_height[p];
@ -4074,6 +4050,7 @@ static av_always_inline int v360_slice(AVFilterContext *ctx, void *arg, int jobn
in_mask = s->in_transform(s, vec, in_height, in_width, rmap.v, rmap.u, &du, &dv);
else
in_mask = s->in_transform(s, vec, in_width, in_height, rmap.u, rmap.v, &du, &dv);
input_flip(rmap.u, rmap.v, in_width, in_height, s->ih_flip, s->iv_flip);
av_assert1(!isnan(du) && !isnan(dv));
s->calculate_kernel(du, dv, &rmap, u, v, ker);
@ -4110,8 +4087,6 @@ static int config_output(AVFilterLink *outlink)
int have_alpha;
s->max_value = (1 << depth) - 1;
s->input_mirror_modifier[0] = s->ih_flip ? -1.f : 1.f;
s->input_mirror_modifier[1] = s->iv_flip ? -1.f : 1.f;
switch (s->interp) {
case NEAREST: