diff options
author | Paul B Mahol <onemda@gmail.com> | 2020-10-04 14:36:30 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2020-10-04 19:23:52 +0200 |
commit | eaba6cecfb5e83ad7b37da5eda236aa5fc6f5f4c (patch) | |
tree | 218c5afcbed01398c5112d8f114f1c5ac58ffe1b | |
parent | acd735efaf0ceba95c3f07751182af485af993d2 (diff) | |
download | ffmpeg-eaba6cecfb5e83ad7b37da5eda236aa5fc6f5f4c.tar.gz |
avfilter/vf_v360: add mitchell interpolation
-rw-r--r-- | doc/filters.texi | 2 | ||||
-rw-r--r-- | libavfilter/v360.h | 1 | ||||
-rw-r--r-- | libavfilter/vf_v360.c | 74 | ||||
-rw-r--r-- | libavfilter/x86/vf_v360_init.c | 3 |
4 files changed, 79 insertions, 1 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index f072a84424..8404f4fb9a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -19543,6 +19543,8 @@ Spline16 interpolation. @item gauss @item gaussian Gaussian interpolation. +@item mitchell +Mitchell interpolation. @end table Default value is @b{@samp{line}}. diff --git a/libavfilter/v360.h b/libavfilter/v360.h index 9b52827bd1..b64d4827f8 100644 --- a/libavfilter/v360.h +++ b/libavfilter/v360.h @@ -65,6 +65,7 @@ enum InterpMethod { LANCZOS, SPLINE16, GAUSSIAN, + MITCHELL, NB_INTERP_METHODS, }; diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index 1266ddc3b6..853a26da03 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -128,6 +128,7 @@ static const AVOption v360_options[] = { { "spline16", "spline16 interpolation", 0, AV_OPT_TYPE_CONST, {.i64=SPLINE16}, 0, 0, FLAGS, "interp" }, { "gauss", "gaussian interpolation", 0, AV_OPT_TYPE_CONST, {.i64=GAUSSIAN}, 0, 0, FLAGS, "interp" }, { "gaussian", "gaussian interpolation", 0, AV_OPT_TYPE_CONST, {.i64=GAUSSIAN}, 0, 0, FLAGS, "interp" }, + { "mitchell", "mitchell interpolation", 0, AV_OPT_TYPE_CONST, {.i64=MITCHELL}, 0, 0, FLAGS, "interp" }, { "w", "output width", OFFSET(width), AV_OPT_TYPE_INT, {.i64=0}, 0, INT16_MAX, FLAGS, "w"}, { "h", "output height", OFFSET(height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT16_MAX, FLAGS, "h"}, { "in_stereo", "input stereo format", OFFSET(in_stereo), AV_OPT_TYPE_INT, {.i64=STEREO_2D}, 0, NB_STEREO_FMTS-1, FLAGS, "stereo" }, @@ -381,6 +382,7 @@ void ff_v360_init(V360Context *s, int depth) case LANCZOS: case SPLINE16: case GAUSSIAN: + case MITCHELL: s->remap_line = depth <= 8 ? remap4_8bit_line_c : remap4_16bit_line_c; break; } @@ -670,6 +672,71 @@ static void gaussian_kernel(float du, float dv, const XYRemap *rmap, } /** + * Calculate 1-dimensional cubic_bc_spline coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static void calculate_cubic_bc_coeffs(float t, float *coeffs, + float b, float c) +{ + float sum = 0.f; + float p0 = (6.f - 2.f * b) / 6.f, + p2 = (-18.f + 12.f * b + 6.f * c) / 6.f, + p3 = (12.f - 9.f * b - 6.f * c) / 6.f, + q0 = (8.f * b + 24.f * c) / 6.f, + q1 = (-12.f * b - 48.f * c) / 6.f, + q2 = (6.f * b + 30.f * c) / 6.f, + q3 = (-b - 6.f * c) / 6.f; + + for (int i = 0; i < 4; i++) { + const float x = fabsf(t - i + 1.f); + if (x < 1.f) { + coeffs[i] = (p0 + x * x * (p2 + x * p3)) * + (p0 + x * x * (p2 + x * p3 / 2.f) / 4.f); + } else if (x < 2.f) { + coeffs[i] = (q0 + x * (q1 + x * (q2 + x * q3))) * + (q0 + x * (q1 + x * (q2 + x / 2.f * q3) / 2.f) / 2.f); + } else { + coeffs[i] = 0.f; + } + sum += coeffs[i]; + } + + for (int i = 0; i < 4; i++) { + coeffs[i] /= sum; + } +} + +/** + * Calculate kernel for mitchell 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 mitchell_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[4]; + float dv_coeffs[4]; + + calculate_cubic_bc_coeffs(du, du_coeffs, 1.f / 3.f, 1.f / 3.f); + calculate_cubic_bc_coeffs(dv, dv_coeffs, 1.f / 3.f, 1.f / 3.f); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + u[i * 4 + j] = rmap->u[i][j]; + v[i * 4 + j] = rmap->v[i][j]; + ker[i * 4 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** * Modulo operation with only positive remainders. * * @param a dividend @@ -4138,6 +4205,13 @@ static int config_output(AVFilterLink *outlink) sizeof_uv = sizeof(int16_t) * s->elements; sizeof_ker = sizeof(int16_t) * s->elements; break; + case MITCHELL: + s->calculate_kernel = mitchell_kernel; + s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice; + s->elements = 4 * 4; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; default: av_assert0(0); } diff --git a/libavfilter/x86/vf_v360_init.c b/libavfilter/x86/vf_v360_init.c index 7d001a6948..2b2b06dd40 100644 --- a/libavfilter/x86/vf_v360_init.c +++ b/libavfilter/x86/vf_v360_init.c @@ -64,7 +64,8 @@ av_cold void ff_v360_init_x86(V360Context *s, int depth) if (EXTERNAL_AVX2_FAST(cpu_flags) && (s->interp == BICUBIC || s->interp == LANCZOS || s->interp == SPLINE16 || - s->interp == GAUSSIAN) && depth <= 8) + s->interp == GAUSSIAN || + s->interp == MITCHELL) && depth <= 8) s->remap_line = ff_remap4_8bit_line_avx2; #endif } |