[FFmpeg-cvslog] avfilter/vf_v360: add truncated square pyramid output format

Paul B Mahol git at videolan.org
Mon Mar 2 20:18:17 EET 2020


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Mar  2 17:40:21 2020 +0100| [3dd81be866bf7d1ad4f8dce642616a100245f94b] | committer: Paul B Mahol

avfilter/vf_v360: add truncated square pyramid output format

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=3dd81be866bf7d1ad4f8dce642616a100245f94b
---

 doc/filters.texi      |  4 +++
 libavfilter/v360.h    |  1 +
 libavfilter/vf_v360.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 1453ecd8b1..10fac14eff 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -19027,6 +19027,10 @@ Set perspective parameter.
 
 @item tetrahedron
 Tetrahedron projection.
+
+ at item tsp
+Truncated square pyramid projection. @i{(output only)}
+
 @end table
 
 @item interp
diff --git a/libavfilter/v360.h b/libavfilter/v360.h
index e1f131c9a8..4b2351f177 100644
--- a/libavfilter/v360.h
+++ b/libavfilter/v360.h
@@ -49,6 +49,7 @@ enum Projections {
     PERSPECTIVE,
     TETRAHEDRON,
     BARREL_SPLIT,
+    TSPYRAMID,
     NB_PROJECTIONS,
 };
 
diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c
index e6984e703a..a522582c70 100644
--- a/libavfilter/vf_v360.c
+++ b/libavfilter/vf_v360.c
@@ -101,6 +101,7 @@ static const AVOption v360_options[] = {
     {"perspective", "perspective",                               0, AV_OPT_TYPE_CONST,  {.i64=PERSPECTIVE},     0,                   0, FLAGS, "out" },
     {"tetrahedron", "tetrahedron",                               0, AV_OPT_TYPE_CONST,  {.i64=TETRAHEDRON},     0,                   0, FLAGS, "out" },
     {"barrelsplit", "barrel split facebook's 360 format",        0, AV_OPT_TYPE_CONST,  {.i64=BARREL_SPLIT},    0,                   0, FLAGS, "out" },
+    {       "tsp", "truncated square pyramid",                   0, AV_OPT_TYPE_CONST,  {.i64=TSPYRAMID},       0,                   0, FLAGS, "out" },
     {    "interp", "set interpolation method",      OFFSET(interp), AV_OPT_TYPE_INT,    {.i64=BILINEAR},        0, NB_INTERP_METHODS-1, FLAGS, "interp" },
     {      "near", "nearest neighbour",                          0, AV_OPT_TYPE_CONST,  {.i64=NEAREST},         0,                   0, FLAGS, "interp" },
     {   "nearest", "nearest neighbour",                          0, AV_OPT_TYPE_CONST,  {.i64=NEAREST},         0,                   0, FLAGS, "interp" },
@@ -3227,6 +3228,64 @@ static int barrelsplit_to_xyz(const V360Context *s,
     return 1;
 }
 
+/**
+ * Calculate 3D coordinates on sphere for corresponding frame position in tspyramid format.
+ *
+ * @param s filter private context
+ * @param i horizontal position on frame [0, width)
+ * @param j vertical position on frame [0, height)
+ * @param width frame width
+ * @param height frame height
+ * @param vec coordinates on sphere
+ */
+static int tspyramid_to_xyz(const V360Context *s,
+                            int i, int j, int width, int height,
+                            float *vec)
+{
+    const float x = (i + 0.5f) / width;
+    const float y = (j + 0.5f) / height;
+
+    if (x < 0.5f) {
+        vec[0] =   x * 4.f - 1.f;
+        vec[1] = -(y * 2.f - 1.f);
+        vec[2] = -1.f;
+    } else if (x >= 0.6875f && x < 0.8125f &&
+               y >= 0.375f  && y < 0.625f) {
+        vec[0] = -(x - 0.6875f) * 16.f + 1.f;
+        vec[1] = -(y - 0.375f) * 8.f + 1.f;
+        vec[2] = 1.f;
+    } else if (0.5f <= x && x < 0.6875f &&
+               ((0.f <= y && y < 0.375f && y >= 2.f * (x - 0.5f)) ||
+                (0.375f <= y && y < 0.625f) ||
+                (0.625f <= y && y < 1.f && y <= 2.f * (1.f - x)))) {
+        vec[0] =  1.f;
+        vec[1] = -2.f * (y - 2.f * x + 1.f) / (3.f - 4.f * x) + 1.f;
+        vec[2] =  2.f * (x - 0.5f) / 0.1875f - 1.f;
+    } else if (0.8125f <= x && x < 1.f &&
+               ((0.f <= y && y < 0.375f && x >= (1.f - y / 2.f)) ||
+                (0.375f <= y && y < 0.625f) ||
+                (0.625f <= y && y < 1.f && y <= (2.f * x - 1.f)))) {
+        vec[0] = -1.f;
+        vec[1] = -2.f * (y + 2.f * x - 2.f) / (4.f * x - 3.f) + 1.f;
+        vec[2] = -2.f * (x - 0.8125f) / 0.1875f + 1.f;
+    } else if (0.f <= y && y < 0.375f &&
+               ((0.5f <= x && x < 0.8125f && y < 2.f * (x - 0.5f)) ||
+                (0.6875f <= x && x < 0.8125f) ||
+                (0.8125f <= x && x < 1.f && x < (1.f - y / 2.f)))) {
+        vec[0] =  2.f * (1.f - x - 0.5f * y) / (0.5f - y) - 1.f;
+        vec[1] =  1.f;
+        vec[2] = -2.f * (0.375f - y) / 0.375f + 1.f;
+    } else {
+        vec[0] =  2.f * (0.5f - x + 0.5f * y) / (y - 0.5f) - 1.f;
+        vec[1] = -1.f;
+        vec[2] =  2.f * (1.f - y) / 0.375f - 1.f;
+    }
+
+    normalize_vector(vec);
+
+    return 1;
+}
+
 static void multiply_matrix(float c[3][3], const float a[3][3], const float b[3][3])
 {
     for (int i = 0; i < 3; i++) {
@@ -3350,7 +3409,7 @@ static void fov_from_dfov(int format, float d_fov, float w, float h, float *h_fo
     case FLAT:
     default:
         {
-            const float da = tanf(0.5 * FFMIN(d_fov, 359.f) * M_PI / 180.f);
+            const float da = tanf(0.5f * FFMIN(d_fov, 359.f) * M_PI / 180.f);
             const float d = hypotf(w, h);
 
             *h_fov = atan2f(da * w, d) * 360.f / M_PI;
@@ -3792,6 +3851,12 @@ static int config_output(AVFilterLink *outlink)
         w = lrintf(wf / 4.f * 3.f);
         h = lrintf(hf);
         break;
+    case TSPYRAMID:
+        s->out_transform = tspyramid_to_xyz;
+        prepare_out = NULL;
+        w = lrintf(wf);
+        h = lrintf(hf);
+        break;
     default:
         av_log(ctx, AV_LOG_ERROR, "Specified output format is not handled.\n");
         return AVERROR_BUG;



More information about the ffmpeg-cvslog mailing list