mirror of https://git.ffmpeg.org/ffmpeg.git
avfilter/vf_v360: implement diagonal field of view
This commit is contained in:
parent
8efc9fcc56
commit
cb8d6a4e3e
|
@ -18006,7 +18006,10 @@ Format specific options:
|
||||||
@table @option
|
@table @option
|
||||||
@item h_fov
|
@item h_fov
|
||||||
@item v_fov
|
@item v_fov
|
||||||
Set horizontal/vertical field of view. Values in degrees.
|
@item d_fov
|
||||||
|
Set horizontal/vertical/diagonal field of view. Values in degrees.
|
||||||
|
|
||||||
|
If diagonal field of view is set it overrides horizontal and vertical field of view.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item dfisheye
|
@item dfisheye
|
||||||
|
@ -18040,7 +18043,10 @@ Format specific options:
|
||||||
@table @option
|
@table @option
|
||||||
@item h_fov
|
@item h_fov
|
||||||
@item v_fov
|
@item v_fov
|
||||||
Set horizontal/vertical field of view. Values in degrees.
|
@item d_fov
|
||||||
|
Set horizontal/vertical/diagonal field of view. Values in degrees.
|
||||||
|
|
||||||
|
If diagonal field of view is set it overrides horizontal and vertical field of view.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
|
@ -103,7 +103,7 @@ typedef struct V360Context {
|
||||||
int h_flip, v_flip, d_flip;
|
int h_flip, v_flip, d_flip;
|
||||||
int in_transpose, out_transpose;
|
int in_transpose, out_transpose;
|
||||||
|
|
||||||
float h_fov, v_fov;
|
float h_fov, v_fov, d_fov;
|
||||||
float flat_range[3];
|
float flat_range[3];
|
||||||
|
|
||||||
float input_mirror_modifier[2];
|
float input_mirror_modifier[2];
|
||||||
|
|
|
@ -102,6 +102,7 @@ static const AVOption v360_options[] = {
|
||||||
{ "rorder", "rotation order", OFFSET(rorder), AV_OPT_TYPE_STRING, {.str="ypr"}, 0, 0, FLAGS, "rorder"},
|
{ "rorder", "rotation order", OFFSET(rorder), AV_OPT_TYPE_STRING, {.str="ypr"}, 0, 0, FLAGS, "rorder"},
|
||||||
{ "h_fov", "horizontal field of view", OFFSET(h_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.00001f, 360.f, FLAGS, "h_fov"},
|
{ "h_fov", "horizontal field of view", OFFSET(h_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.00001f, 360.f, FLAGS, "h_fov"},
|
||||||
{ "v_fov", "vertical field of view", OFFSET(v_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.00001f, 360.f, FLAGS, "v_fov"},
|
{ "v_fov", "vertical field of view", OFFSET(v_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.00001f, 360.f, FLAGS, "v_fov"},
|
||||||
|
{ "d_fov", "diagonal field of view", OFFSET(d_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f, FLAGS, "d_fov"},
|
||||||
{ "h_flip", "flip out video horizontally", OFFSET(h_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "h_flip"},
|
{ "h_flip", "flip out video horizontally", OFFSET(h_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "h_flip"},
|
||||||
{ "v_flip", "flip out video vertically", OFFSET(v_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "v_flip"},
|
{ "v_flip", "flip out video vertically", OFFSET(v_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "v_flip"},
|
||||||
{ "d_flip", "flip out video indepth", OFFSET(d_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "d_flip"},
|
{ "d_flip", "flip out video indepth", OFFSET(d_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "d_flip"},
|
||||||
|
@ -2139,6 +2140,20 @@ static int allocate_plane(V360Context *s, int sizeof_uv, int sizeof_ker, int p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fov_from_dfov(V360Context *s, float w, float h)
|
||||||
|
{
|
||||||
|
const float d_angle = 0.5 * FFMIN(s->d_fov, 359.f) * M_PI / 180.f;
|
||||||
|
const float d = hypotf(w, h);
|
||||||
|
|
||||||
|
s->h_fov = atan2f(tanf(d_angle) * w, d) * 360.f / M_PI;
|
||||||
|
s->v_fov = atan2f(tanf(d_angle) * h, d) * 360.f / M_PI;
|
||||||
|
|
||||||
|
if (s->h_fov < 0.f)
|
||||||
|
s->h_fov += 360.f;
|
||||||
|
if (s->v_fov < 0.f)
|
||||||
|
s->v_fov += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
static int config_output(AVFilterLink *outlink)
|
static int config_output(AVFilterLink *outlink)
|
||||||
{
|
{
|
||||||
AVFilterContext *ctx = outlink->src;
|
AVFilterContext *ctx = outlink->src;
|
||||||
|
@ -2161,6 +2176,7 @@ static int config_output(AVFilterLink *outlink)
|
||||||
float *vec);
|
float *vec);
|
||||||
void (*calculate_kernel)(float du, float dv, const XYRemap *r_tmp,
|
void (*calculate_kernel)(float du, float dv, const XYRemap *r_tmp,
|
||||||
uint16_t *u, uint16_t *v, int16_t *ker);
|
uint16_t *u, uint16_t *v, int16_t *ker);
|
||||||
|
int (*prepare_out)(AVFilterContext *ctx);
|
||||||
float rot_mat[3][3];
|
float rot_mat[3][3];
|
||||||
|
|
||||||
s->input_mirror_modifier[0] = s->ih_flip ? -1.f : 1.f;
|
s->input_mirror_modifier[0] = s->ih_flip ? -1.f : 1.f;
|
||||||
|
@ -2285,55 +2301,55 @@ static int config_output(AVFilterLink *outlink)
|
||||||
switch (s->out) {
|
switch (s->out) {
|
||||||
case EQUIRECTANGULAR:
|
case EQUIRECTANGULAR:
|
||||||
out_transform = equirect_to_xyz;
|
out_transform = equirect_to_xyz;
|
||||||
err = 0;
|
prepare_out = NULL;
|
||||||
w = roundf(wf);
|
w = roundf(wf);
|
||||||
h = roundf(hf);
|
h = roundf(hf);
|
||||||
break;
|
break;
|
||||||
case CUBEMAP_3_2:
|
case CUBEMAP_3_2:
|
||||||
out_transform = cube3x2_to_xyz;
|
out_transform = cube3x2_to_xyz;
|
||||||
err = prepare_cube_out(ctx);
|
prepare_out = prepare_cube_out;
|
||||||
w = roundf(wf / 4.f * 3.f);
|
w = roundf(wf / 4.f * 3.f);
|
||||||
h = roundf(hf);
|
h = roundf(hf);
|
||||||
break;
|
break;
|
||||||
case CUBEMAP_1_6:
|
case CUBEMAP_1_6:
|
||||||
out_transform = cube1x6_to_xyz;
|
out_transform = cube1x6_to_xyz;
|
||||||
err = prepare_cube_out(ctx);
|
prepare_out = prepare_cube_out;
|
||||||
w = roundf(wf / 4.f);
|
w = roundf(wf / 4.f);
|
||||||
h = roundf(hf * 3.f);
|
h = roundf(hf * 3.f);
|
||||||
break;
|
break;
|
||||||
case CUBEMAP_6_1:
|
case CUBEMAP_6_1:
|
||||||
out_transform = cube6x1_to_xyz;
|
out_transform = cube6x1_to_xyz;
|
||||||
err = prepare_cube_out(ctx);
|
prepare_out = prepare_cube_out;
|
||||||
w = roundf(wf / 2.f * 3.f);
|
w = roundf(wf / 2.f * 3.f);
|
||||||
h = roundf(hf / 2.f);
|
h = roundf(hf / 2.f);
|
||||||
break;
|
break;
|
||||||
case EQUIANGULAR:
|
case EQUIANGULAR:
|
||||||
out_transform = eac_to_xyz;
|
out_transform = eac_to_xyz;
|
||||||
err = prepare_eac_out(ctx);
|
prepare_out = prepare_eac_out;
|
||||||
w = roundf(wf);
|
w = roundf(wf);
|
||||||
h = roundf(hf / 8.f * 9.f);
|
h = roundf(hf / 8.f * 9.f);
|
||||||
break;
|
break;
|
||||||
case FLAT:
|
case FLAT:
|
||||||
out_transform = flat_to_xyz;
|
out_transform = flat_to_xyz;
|
||||||
err = prepare_flat_out(ctx);
|
prepare_out = prepare_flat_out;
|
||||||
w = roundf(wf);
|
w = roundf(wf);
|
||||||
h = roundf(hf);
|
h = roundf(hf);
|
||||||
break;
|
break;
|
||||||
case DUAL_FISHEYE:
|
case DUAL_FISHEYE:
|
||||||
out_transform = dfisheye_to_xyz;
|
out_transform = dfisheye_to_xyz;
|
||||||
err = 0;
|
prepare_out = NULL;
|
||||||
w = roundf(wf);
|
w = roundf(wf);
|
||||||
h = roundf(hf);
|
h = roundf(hf);
|
||||||
break;
|
break;
|
||||||
case BARREL:
|
case BARREL:
|
||||||
out_transform = barrel_to_xyz;
|
out_transform = barrel_to_xyz;
|
||||||
err = 0;
|
prepare_out = NULL;
|
||||||
w = roundf(wf / 4.f * 5.f);
|
w = roundf(wf / 4.f * 5.f);
|
||||||
h = roundf(hf);
|
h = roundf(hf);
|
||||||
break;
|
break;
|
||||||
case STEREOGRAPHIC:
|
case STEREOGRAPHIC:
|
||||||
out_transform = stereographic_to_xyz;
|
out_transform = stereographic_to_xyz;
|
||||||
err = prepare_stereographic_out(ctx);
|
prepare_out = prepare_stereographic_out;
|
||||||
w = roundf(wf);
|
w = roundf(wf);
|
||||||
h = roundf(hf * 2.f);
|
h = roundf(hf * 2.f);
|
||||||
break;
|
break;
|
||||||
|
@ -2342,10 +2358,6 @@ static int config_output(AVFilterLink *outlink)
|
||||||
return AVERROR_BUG;
|
return AVERROR_BUG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != 0) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override resolution with user values if specified
|
// Override resolution with user values if specified
|
||||||
if (s->width > 0 && s->height > 0) {
|
if (s->width > 0 && s->height > 0) {
|
||||||
w = s->width;
|
w = s->width;
|
||||||
|
@ -2361,6 +2373,15 @@ static int config_output(AVFilterLink *outlink)
|
||||||
FFSWAP(int, w, h);
|
FFSWAP(int, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->d_fov > 0.f)
|
||||||
|
fov_from_dfov(s, w, h);
|
||||||
|
|
||||||
|
if (prepare_out) {
|
||||||
|
err = prepare_out(ctx);
|
||||||
|
if (err != 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(h, desc->log2_chroma_h);
|
s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(h, desc->log2_chroma_h);
|
||||||
s->planeheight[0] = s->planeheight[3] = h;
|
s->planeheight[0] = s->planeheight[3] = h;
|
||||||
s->planewidth[1] = s->planewidth[2] = FF_CEIL_RSHIFT(w, desc->log2_chroma_w);
|
s->planewidth[1] = s->planewidth[2] = FF_CEIL_RSHIFT(w, desc->log2_chroma_w);
|
||||||
|
|
Loading…
Reference in New Issue