diff options
author | Paul B Mahol <onemda@gmail.com> | 2019-09-09 14:01:23 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2019-09-09 14:17:22 +0200 |
commit | 976617c7d21e4b525d6edde2fb280994fc5c567c (patch) | |
tree | 0c14dde299145fcfba63033e5fbd19deb33e5f9b | |
parent | 7985430c70910fe4aa2a10a3a852fba2c6396d0c (diff) | |
download | ffmpeg-976617c7d21e4b525d6edde2fb280994fc5c567c.tar.gz |
avfilter/vf_v360: extend stereographic projection
Add option to change central point projection.
-rw-r--r-- | doc/filters.texi | 7 | ||||
-rw-r--r-- | libavfilter/v360.h | 1 | ||||
-rw-r--r-- | libavfilter/vf_v360.c | 32 |
3 files changed, 31 insertions, 9 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index 114ce6fd97..d1d47be415 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18038,7 +18038,12 @@ Stereographic format. @i{(output only)} Format specific options: @table @option @item h_fov -Set field of view. Values in degrees. +@item v_fov +Set horizontal/vertical field of view. Values in degrees. + +@item p_lon +@item p_lat +Set central point of projection longitude/latitude. Values in degrees. @end table @end table diff --git a/libavfilter/v360.h b/libavfilter/v360.h index 93ac8034ef..b769218c04 100644 --- a/libavfilter/v360.h +++ b/libavfilter/v360.h @@ -105,6 +105,7 @@ typedef struct V360Context { float h_fov, v_fov; float flat_range[3]; + float p_lon, p_lat; float input_mirror_modifier[2]; diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index bf94727400..0ea7a460ea 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -33,6 +33,8 @@ * 5) Remap input frame to output frame using precalculated data */ +#include <float.h> + #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" @@ -105,6 +107,8 @@ static const AVOption v360_options[] = { { "iv_flip", "flip in video vertically", OFFSET(iv_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "iv_flip"}, { "in_trans", "transpose video input", OFFSET(in_transpose), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "in_transpose"}, { "out_trans", "transpose video output", OFFSET(out_transpose), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "out_transpose"}, + { "p_lon", "central projection longitude", OFFSET(p_lon), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "p_lon"}, + { "p_lat", "central projection latitude", OFFSET(p_lat), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, -90.f, 90.f, FLAGS, "p_lat"}, { NULL } }; @@ -1406,14 +1410,26 @@ static void stereographic_to_xyz(const V360Context *s, int i, int j, int width, int height, float *vec) { - const float z = 0.5f * s->h_fov * M_PI / 180.f; - const float x = z * (2.f * i / width - 1.f); - const float y = z * (2.f * j / height - 1.f); - const float xy = x * x + y * y; - - vec[0] = 2.f * x / (1.f + xy); - vec[1] = (-1.f + xy) / (1.f + xy); - vec[2] = 2.f * y / (1.f + xy); + const float x = ((2.f * i) / width - 1.f) * (s->h_fov / 180.f) * M_PI; + const float y = ((2.f * j) / height - 1.f) * (s->v_fov / 90.f) * M_PI_2; + const float rho = hypotf(x, y) + FLT_EPSILON; + const float c = 2.f * atan2f(rho, 0.15f / 2.f); + const float cos_c = cosf(c); + const float sin_c = sinf(c); + const float cp_x = s->p_lon / 180.f * M_PI; + const float cp_y = s->p_lat / 90.f * M_PI_2; + + const float phi = cp_x + atan2f(x * sin_c, rho * cosf(cp_y) * cos_c - y * sinf(cp_y) * sin_c); + const float theta = asinf(cos_c * sinf(cp_y) + (y * sin_c * cosf(cp_y)) / rho); + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * sin_phi; + vec[1] = -sin_theta; + vec[2] = -cos_theta * cos_phi; normalize_vector(vec); } |