From e57b9aa8b191349c79c105f283a4e0a680d55e89 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 20 Jan 2020 14:50:54 +0100 Subject: avfilter/vf_v360: add support for flat input format --- doc/filters.texi | 11 ++++++-- libavfilter/v360.h | 2 ++ libavfilter/vf_v360.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d69987c9f4..1154638f95 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18910,14 +18910,21 @@ Equi-Angular Cubemap. @item flat @item gnomonic @item rectilinear -Regular video. @i{(output only)} +Regular video. Format specific options: @table @option @item h_fov @item v_fov @item d_fov -Set horizontal/vertical/diagonal field of view. Values in degrees. +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input 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 diff --git a/libavfilter/v360.h b/libavfilter/v360.h index 6f51396d86..ba3d0da60f 100644 --- a/libavfilter/v360.h +++ b/libavfilter/v360.h @@ -130,7 +130,9 @@ typedef struct V360Context { int in_transpose, out_transpose; float h_fov, v_fov, d_fov; + float ih_fov, iv_fov, id_fov; float flat_range[2]; + float iflat_range[2]; float rot_mat[3][3]; diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index f00c7c448c..48090e8cb6 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -61,6 +61,9 @@ static const AVOption v360_options[] = { { "c6x1", "cubemap 6x1", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_6_1}, 0, 0, FLAGS, "in" }, { "eac", "equi-angular cubemap", 0, AV_OPT_TYPE_CONST, {.i64=EQUIANGULAR}, 0, 0, FLAGS, "in" }, { "dfisheye", "dual fisheye", 0, AV_OPT_TYPE_CONST, {.i64=DUAL_FISHEYE}, 0, 0, FLAGS, "in" }, + { "flat", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "in" }, + {"rectilinear", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "in" }, + { "gnomonic", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "in" }, { "barrel", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL}, 0, 0, FLAGS, "in" }, { "fb", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL}, 0, 0, FLAGS, "in" }, { "c1x6", "cubemap 1x6", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_1_6}, 0, 0, FLAGS, "in" }, @@ -133,6 +136,9 @@ 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"}, + { "ih_fov", "input horizontal field of view",OFFSET(ih_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.00001f, 360.f, FLAGS, "ih_fov"}, + { "iv_fov", "input vertical field of view", OFFSET(iv_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.00001f, 360.f, FLAGS, "iv_fov"}, + { "id_fov", "input diagonal field of view", OFFSET(id_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f, FLAGS, "id_fov"}, { NULL } }; @@ -1648,6 +1654,68 @@ static void xyz_to_equirect(const V360Context *s, } } +/** + * Prepare data for processing flat input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_flat_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = tanf(0.5f * s->ih_fov * M_PI / 180.f); + s->iflat_range[1] = tanf(0.5f * s->iv_fov * M_PI / 180.f); + + return 0; +} + +/** + * Calculate frame position in flat format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static void xyz_to_flat(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 = acosf(vec[2]); + const float r = tanf(theta); + const float rr = fabsf(r) < 1e+6f ? r : hypotf(width, height); + 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]; + int visible, ui, vi; + + uf = zf >= 0.f ? (uf + 1.f) * width / 2.f : 0.f; + vf = zf >= 0.f ? (vf + 1.f) * height / 2.f : 0.f; + + ui = floorf(uf); + vi = floorf(vf); + + visible = vi >= 0 && vi < height && ui >= 0 && ui < width; + + *du = uf - ui; + *dv = vf - vi; + + for (int i = -1; i < 3; i++) { + for (int j = -1; j < 3; j++) { + us[i + 1][j + 1] = visible ? av_clip(ui + j, 0, width - 1) : 0; + vs[i + 1][j + 1] = visible ? av_clip(vi + i, 0, height - 1) : 0; + } + } +} + /** * Calculate frame position in mercator format for corresponding 3D coordinates on sphere. * @@ -2899,6 +2967,9 @@ static int config_output(AVFilterLink *outlink) s->in_width = s->inplanewidth[0]; s->in_height = s->inplaneheight[0]; + if (s->id_fov > 0.f) + fov_from_dfov(s->id_fov, w, h, &s->ih_fov, &s->iv_fov); + if (s->in_transpose) FFSWAP(int, s->in_width, s->in_height); @@ -2933,11 +3004,16 @@ static int config_output(AVFilterLink *outlink) wf = w; hf = h / 9.f * 8.f; break; + case FLAT: + s->in_transform = xyz_to_flat; + err = prepare_flat_in(ctx); + wf = w; + hf = h; + break; case PERSPECTIVE: case CYLINDRICAL: case PANNINI: case FISHEYE: - case FLAT: av_log(ctx, AV_LOG_ERROR, "Supplied format is not accepted as input.\n"); return AVERROR(EINVAL); case DUAL_FISHEYE: -- cgit v1.2.3