From: Mark Reid
---
libavfilter/vf_lut3d.c | 207 +++--
1 file changed, 201 insertions(+), 6 deletions(-)
diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c
index fda85b16b4..482e2394a7 100644
--- a/libavfilter/vf_lut3d.c
+++ b/libavfilter/vf_lut3d.c
@@ -24,9 +24,12 @@
* 3D Lookup table filter
*/
+#include "float.h"
+
#include "libavutil/opt.h"
#include "libavutil/file.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/intfloat.h"
#include "libavutil/avassert.h"
#include "libavutil/pixdesc.h"
#include "libavutil/avstring.h"
@@ -73,6 +76,7 @@ typedef struct LUT3DContext {
int clut_step;
int clut_bits;
int clut_planar;
+int clut_float;
int clut_width;
FFFrameSync fs;
#endif
@@ -91,6 +95,30 @@ typedef struct ThreadData {
{ "tetrahedral", "interpolate values using a tetrahedron",
0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX,
FLAGS, "interp_mode" }, \
{ NULL }
+#define EXPONENT_MASK 0x7F80
+#define MANTISSA_MASK 0x007F
+#define SIGN_MASK 0x7FFF
+
+static inline float sanitizef(float f)
+{
+union av_intfloat32 t;
+t.f = f;
+
+if ((t.i & EXPONENT_MASK) == EXPONENT_MASK) {
+if ((t.i & MANTISSA_MASK) != 0) {
+// NAN
+return 0.0f;
+} else if (t.i & SIGN_MASK) {
+// -INF
+return FLT_MIN;
+} else {
+// +INF
+return FLT_MAX;
+}
+}
+return f;
+}
+
static inline float lerpf(float v0, float v1, float f)
{
return v0 + (v1 - v0) * f;
@@ -285,6 +313,66 @@ DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 16)
DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 16)
DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 16)
+#define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth)
\
+static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int
jobnr, int nb_jobs) \
+{
\
+int x, y;
\
+const LUT3DContext *lut3d = ctx->priv;
\
+const ThreadData *td = arg;
\
+const AVFrame *in = td->in;
\
+const AVFrame *out = td->out;
\
+const int direct = out == in;
\
+const int slice_start = (in->height * jobnr ) / nb_jobs;
\
+const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
\
+uint8_t *grow = out->data[0] + slice_start * out->linesize[0];
\
+uint8_t *brow = out->data[1] + slice_start * out->linesize[1];
\
+uint8_t *rrow = out->data[2] + slice_start * out->linesize[2];
\
+uint8_t *arow = out->data[3] + slice_start * out->linesize[3];
\
+const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0];
\
+const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1];
\
+const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2];
\
+const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3];
\
+const float lutsize = lut3d->lutsize - 1;
\
+const float scale_r = lut3d->scale.r * lutsize;
\
+const float scale_g = lut3d->scale.g * lutsize;
\
+const float scale_b = lut3d->scale.b * lutsize;
\
+
\
+for (y = slice_start; y < slice_end; y++) {
\
+float *dstg = (float *)grow;
\
+float *dstb = (float *)brow;
\
+float *dstr = (float *)rrow;
\
+float *dsta = (float *)arow;
\
+const float *srcg = (const float *)srcgrow;