diff mbox series

[FFmpeg-devel,1/2] avfilter/vf_v360: add lagrange interpolation

Message ID 20200331135106.32490-1-onemda@gmail.com
State New
Headers show
Series [FFmpeg-devel,1/2] avfilter/vf_v360: add lagrange interpolation
Related show

Checks

Context Check Description
andriy/ffmpeg-patchwork pending
andriy/ffmpeg-patchwork success Applied patch
andriy/ffmpeg-patchwork success Configure finished
andriy/ffmpeg-patchwork success Make finished
andriy/ffmpeg-patchwork success Make fate finished

Commit Message

Paul B Mahol March 31, 2020, 1:51 p.m. UTC
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 doc/filters.texi      |  2 ++
 libavfilter/v360.h    |  1 +
 libavfilter/vf_v360.c | 56 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+)
diff mbox series

Patch

diff --git a/doc/filters.texi b/doc/filters.texi
index 44d41a87cf..8827aac316 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -19105,6 +19105,8 @@  Nearest neighbour.
 @item line
 @item linear
 Bilinear interpolation.
+@item lagrange
+Lagrange interpolation.
 @item cube
 @item cubic
 Bicubic interpolation.
diff --git a/libavfilter/v360.h b/libavfilter/v360.h
index f2f1a47144..1d4098e5c1 100644
--- a/libavfilter/v360.h
+++ b/libavfilter/v360.h
@@ -57,6 +57,7 @@  enum Projections {
 enum InterpMethod {
     NEAREST,
     BILINEAR,
+    LAGRANGE,
     BICUBIC,
     LANCZOS,
     SPLINE16,
diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c
index 54d4d23825..ca8e55e32c 100644
--- a/libavfilter/vf_v360.c
+++ b/libavfilter/vf_v360.c
@@ -112,6 +112,7 @@  static const AVOption v360_options[] = {
     {   "nearest", "nearest neighbour",                          0, AV_OPT_TYPE_CONST,  {.i64=NEAREST},         0,                   0, FLAGS, "interp" },
     {      "line", "bilinear interpolation",                     0, AV_OPT_TYPE_CONST,  {.i64=BILINEAR},        0,                   0, FLAGS, "interp" },
     {    "linear", "bilinear interpolation",                     0, AV_OPT_TYPE_CONST,  {.i64=BILINEAR},        0,                   0, FLAGS, "interp" },
+    {  "lagrange", "lagrange interpolation",                     0, AV_OPT_TYPE_CONST,  {.i64=LAGRANGE},        0,                   0, FLAGS, "interp" },
     {      "cube", "bicubic interpolation",                      0, AV_OPT_TYPE_CONST,  {.i64=BICUBIC},         0,                   0, FLAGS, "interp" },
     {     "cubic", "bicubic interpolation",                      0, AV_OPT_TYPE_CONST,  {.i64=BICUBIC},         0,                   0, FLAGS, "interp" },
     {      "lanc", "lanczos interpolation",                      0, AV_OPT_TYPE_CONST,  {.i64=LANCZOS},         0,                   0, FLAGS, "interp" },
@@ -313,9 +314,11 @@  static int remap##ws##_##bits##bit_slice(AVFilterContext *ctx, void *arg, int jo
 
 DEFINE_REMAP(1,  8)
 DEFINE_REMAP(2,  8)
+DEFINE_REMAP(3,  8)
 DEFINE_REMAP(4,  8)
 DEFINE_REMAP(1, 16)
 DEFINE_REMAP(2, 16)
+DEFINE_REMAP(3, 16)
 DEFINE_REMAP(4, 16)
 
 #define DEFINE_REMAP_LINE(ws, bits, div)                                                      \
@@ -346,8 +349,10 @@  static void remap##ws##_##bits##bit_line_c(uint8_t *dst, int width, const uint8_
 }
 
 DEFINE_REMAP_LINE(2,  8, 1)
+DEFINE_REMAP_LINE(3,  8, 1)
 DEFINE_REMAP_LINE(4,  8, 1)
 DEFINE_REMAP_LINE(2, 16, 2)
+DEFINE_REMAP_LINE(3, 16, 2)
 DEFINE_REMAP_LINE(4, 16, 2)
 
 void ff_v360_init(V360Context *s, int depth)
@@ -359,6 +364,9 @@  void ff_v360_init(V360Context *s, int depth)
     case BILINEAR:
         s->remap_line = depth <= 8 ? remap2_8bit_line_c : remap2_16bit_line_c;
         break;
+    case LAGRANGE:
+        s->remap_line = depth <= 8 ? remap3_8bit_line_c : remap3_16bit_line_c;
+        break;
     case BICUBIC:
     case LANCZOS:
     case SPLINE16:
@@ -417,6 +425,47 @@  static void bilinear_kernel(float du, float dv, const XYRemap *rmap,
     ker[3] = lrintf(       du  *        dv  * 16385.f);
 }
 
+/**
+ * Calculate 1-dimensional lagrange coefficients.
+ *
+ * @param t relative coordinate
+ * @param coeffs coefficients
+ */
+static inline void calculate_lagrange_coeffs(float t, float *coeffs)
+{
+    coeffs[0] = (t - 1.f) * (t - 2.f) * 0.5f;
+    coeffs[1] = -t * (t - 2.f);
+    coeffs[2] =  t * (t - 1.f) * 0.5f;
+}
+
+/**
+ * Calculate kernel for lagrange interpolation.
+ *
+ * @param du horizontal relative coordinate
+ * @param dv vertical relative coordinate
+ * @param rmap calculated 4x4 window
+ * @param u u remap data
+ * @param v v remap data
+ * @param ker ker remap data
+ */
+static void lagrange_kernel(float du, float dv, const XYRemap *rmap,
+                            int16_t *u, int16_t *v, int16_t *ker)
+{
+    float du_coeffs[3];
+    float dv_coeffs[3];
+
+    calculate_lagrange_coeffs(du, du_coeffs);
+    calculate_lagrange_coeffs(dv, dv_coeffs);
+
+    for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 3; j++) {
+            u[i * 3 + j] = rmap->u[i+1][j+1];
+            v[i * 3 + j] = rmap->v[i+1][j+1];
+            ker[i * 3 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f);
+        }
+    }
+}
+
 /**
  * Calculate 1-dimensional cubic coefficients.
  *
@@ -3689,6 +3738,13 @@  static int config_output(AVFilterLink *outlink)
         sizeof_uv = sizeof(int16_t) * s->elements;
         sizeof_ker = sizeof(int16_t) * s->elements;
         break;
+    case LAGRANGE:
+        s->calculate_kernel = lagrange_kernel;
+        s->remap_slice = depth <= 8 ? remap3_8bit_slice : remap3_16bit_slice;
+        s->elements = 3 * 3;
+        sizeof_uv = sizeof(int16_t) * s->elements;
+        sizeof_ker = sizeof(int16_t) * s->elements;
+        break;
     case BICUBIC:
         s->calculate_kernel = bicubic_kernel;
         s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice;