]> git.sesse.net Git - ffmpeg/commitdiff
avfilter/vf_v360: add pannini input support
authorPaul B Mahol <onemda@gmail.com>
Sat, 4 Apr 2020 12:12:43 +0000 (14:12 +0200)
committerPaul B Mahol <onemda@gmail.com>
Sat, 4 Apr 2020 12:16:28 +0000 (14:16 +0200)
doc/filters.texi
libavfilter/vf_v360.c

index a8d5fb1b4e2e7e5bed39a57097a540a4cc717efb..dce396e3fd48a73f2c48353b47206e067856b42a 100644 (file)
@@ -19044,12 +19044,15 @@ If diagonal field of view is set it overrides horizontal and vertical field of v
 @end table
 
 @item pannini
-Pannini projection. @i{(output only)}
+Pannini projection.
 
 Format specific options:
 @table @option
 @item h_fov
-Set pannini parameter.
+Set output pannini parameter.
+
+@item ih_fov
+Set input pannini parameter.
 @end table
 
 @item cylindrical
index e33a857f878b118ca36798e2deba7c43fe4bf294..ebc281dfcad3207c0ef8ff4834d1a54e1d0c208c 100644 (file)
@@ -74,6 +74,7 @@ static const AVOption v360_options[] = {
     {    "hammer", "hammer",                                     0, AV_OPT_TYPE_CONST,  {.i64=HAMMER},          0,                   0, FLAGS, "in" },
     {"sinusoidal", "sinusoidal",                                 0, AV_OPT_TYPE_CONST,  {.i64=SINUSOIDAL},      0,                   0, FLAGS, "in" },
     {   "fisheye", "fisheye",                                    0, AV_OPT_TYPE_CONST,  {.i64=FISHEYE},         0,                   0, FLAGS, "in" },
+    {   "pannini", "pannini",                                    0, AV_OPT_TYPE_CONST,  {.i64=PANNINI},         0,                   0, FLAGS, "in" },
     {"cylindrical", "cylindrical",                               0, AV_OPT_TYPE_CONST,  {.i64=CYLINDRICAL},     0,                   0, FLAGS, "in" },
     {"tetrahedron", "tetrahedron",                               0, AV_OPT_TYPE_CONST,  {.i64=TETRAHEDRON},     0,                   0, FLAGS, "in" },
     {"barrelsplit", "barrel split facebook's 360 format",        0, AV_OPT_TYPE_CONST,  {.i64=BARREL_SPLIT},    0,                   0, FLAGS, "in" },
@@ -2690,6 +2691,52 @@ static int pannini_to_xyz(const V360Context *s,
     return 1;
 }
 
+/**
+ * Calculate frame position in pannini 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 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 d = s->ih_fov;
+    const float S = (d + 1.f) / (d + cosf(phi));
+
+    const float x = S * sinf(phi);
+    const float y = S * tanf(theta);
+
+    const float uf = (x + 1.f) * width  / 2.f;
+    const float vf = (y + 1.f) * height / 2.f;
+
+    const int ui = floorf(uf);
+    const int vi = floorf(vf);
+
+    const int visible = vi >= 0 && vi < height && ui >= 0 && ui < width && vec[2] >= 0.f;
+
+    *du = uf - ui;
+    *dv = vf - vi;
+
+    for (int i = 0; i < 4; i++) {
+        for (int j = 0; j < 4; j++) {
+            us[i][j] = visible ? av_clip(ui + j - 1, 0, width  - 1) : 0;
+            vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0;
+        }
+    }
+
+    return visible;
+}
+
 /**
  * Prepare data for processing cylindrical output format.
  *
@@ -3877,7 +3924,6 @@ static int config_output(AVFilterLink *outlink)
         hf = h;
         break;
     case PERSPECTIVE:
-    case PANNINI:
         av_log(ctx, AV_LOG_ERROR, "Supplied format is not accepted as input.\n");
         return AVERROR(EINVAL);
     case DUAL_FISHEYE:
@@ -3928,6 +3974,12 @@ static int config_output(AVFilterLink *outlink)
         wf = w * 2;
         hf = h;
         break;
+    case PANNINI:
+        s->in_transform = xyz_to_pannini;
+        err = 0;
+        wf = w;
+        hf = h;
+        break;
     case CYLINDRICAL:
         s->in_transform = xyz_to_cylindrical;
         err = prepare_cylindrical_in(ctx);