Re: [FFmpeg-devel] [PATCH] avfilter: add lut1d filter
On 8/23/18, Paul B Mahol wrote: > Signed-off-by: Paul B Mahol > --- > doc/filters.texi | 31 +++ > libavfilter/Makefile | 1 + > libavfilter/allfilters.c | 1 + > libavfilter/vf_lut3d.c | 438 +++ > 4 files changed, 471 insertions(+) > Will apply. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] avfilter: add lut1d filter
Signed-off-by: Paul B Mahol --- doc/filters.texi | 31 +++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_lut3d.c | 438 +++ 4 files changed, 471 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 32c95b591c..37e79d34e1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10962,6 +10962,37 @@ Set maximal size in number of frames. Default is 0. Set first frame of loop. Default is 0. @end table +@section lut1d + +Apply a 1D LUT to an input video. + +The filter accepts the following options: + +@table @option +@item file +Set the 1D LUT file name. + +Currently supported formats: +@table @samp +@item cube +Iridas +@end table + +@item interp +Select interpolation mode. + +Available values are: + +@table @samp +@item nearest +Use values from the nearest defined point. +@item linear +Interpolate values using the linear interpolation. +@item cubic +Interpolate values using the cubic interpolation. +@end table +@end table + @anchor{lut3d} @section lut3d diff --git a/libavfilter/Makefile b/libavfilter/Makefile index e5d3a57af7..e412000c8f 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -258,6 +258,7 @@ OBJS-$(CONFIG_LIBVMAF_FILTER)+= vf_libvmaf.o framesync.o OBJS-$(CONFIG_LIMITER_FILTER)+= vf_limiter.o OBJS-$(CONFIG_LOOP_FILTER) += f_loop.o OBJS-$(CONFIG_LUMAKEY_FILTER)+= vf_lumakey.o +OBJS-$(CONFIG_LUT1D_FILTER) += vf_lut3d.o OBJS-$(CONFIG_LUT_FILTER)+= vf_lut.o OBJS-$(CONFIG_LUT2_FILTER) += vf_lut2.o framesync.o OBJS-$(CONFIG_LUT3D_FILTER) += vf_lut3d.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9732ae5345..2fa9460335 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -246,6 +246,7 @@ extern AVFilter ff_vf_limiter; extern AVFilter ff_vf_loop; extern AVFilter ff_vf_lumakey; extern AVFilter ff_vf_lut; +extern AVFilter ff_vf_lut1d; extern AVFilter ff_vf_lut2; extern AVFilter ff_vf_lut3d; extern AVFilter ff_vf_lutrgb; diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c index 27b79b860b..6ec0cad650 100644 --- a/libavfilter/vf_lut3d.c +++ b/libavfilter/vf_lut3d.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013 Clément Bœsch + * Copyright (c) 2018 Paul B Mahol * * This file is part of FFmpeg. * @@ -975,3 +976,440 @@ AVFilter ff_vf_haldclut = { .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; #endif + +#if CONFIG_LUT1D_FILTER + +enum interp_1d_mode { +INTERPOLATE_1D_NEAREST, +INTERPOLATE_1D_LINEAR, +INTERPOLATE_1D_CUBIC, +NB_INTERP_1D_MODE +}; + +#define MAX_1D_LEVEL 65536 + +typedef struct LUT1DContext { +const AVClass *class; +char *file; +int interpolation; ///lutsize = size; +for (i = 0; i < size; i++) { +lut1d->lut[0][i] = i * c; +lut1d->lut[1][i] = i * c; +lut1d->lut[2][i] = i * c; +} +} + +static int parse_cube_1d(AVFilterContext *ctx, FILE *f) +{ +LUT1DContext *lut1d = ctx->priv; +char line[MAX_LINE_SIZE]; +float min[3] = {0.0, 0.0, 0.0}; +float max[3] = {1.0, 1.0, 1.0}; + +while (fgets(line, sizeof(line), f)) { +if (!strncmp(line, "LUT_1D_SIZE ", 12)) { +const int size = strtol(line + 12, NULL, 0); +int i; + +if (size < 2 || size > MAX_1D_LEVEL) { +av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n"); +return AVERROR(EINVAL); +} +lut1d->lutsize = size; +for (i = 0; i < size; i++) { +do { +try_again: +NEXT_LINE(0); +if (!strncmp(line, "DOMAIN_", 7)) { +float *vals = NULL; +if (!strncmp(line + 7, "MIN ", 4)) vals = min; +else if (!strncmp(line + 7, "MAX ", 4)) vals = max; +if (!vals) +return AVERROR_INVALIDDATA; +sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2); +av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n", + min[0], min[1], min[2], max[0], max[1], max[2]); +goto try_again; +} +} while (skip_line(line)); +if (sscanf(line, "%f %f %f", >lut[0][i], >lut[1][i], >lut[2][i]) != 3) +return AVERROR_INVALIDDATA; +lut1d->lut[0][i] *= max[0] - min[0]; +lut1d->lut[1][i] *= max[1] - min[1]; +lut1d->lut[2][i] *= max[2] - min[2]; +} +break; +} +} +return 0; +} + +static const AVOption lut1d_options[] = { +{ "file", "set 1D LUT file name", OFFSET(file),
[FFmpeg-devel] [PATCH] avfilter: add lut1d filter
Signed-off-by: Paul B Mahol --- doc/filters.texi | 29 +++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_lut3d.c | 404 +++ 4 files changed, 435 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 32c95b591c..72ce95f94a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -10962,6 +10962,35 @@ Set maximal size in number of frames. Default is 0. Set first frame of loop. Default is 0. @end table +@section lut1d + +Apply a 1D LUT to an input video. + +The filter accepts the following options: + +@table @option +@item file +Set the 1D LUT file name. + +Currently supported formats: +@table @samp +@item cube +Iridas +@end table + +@item interp +Select interpolation mode. + +Available values are: + +@table @samp +@item nearest +Use values from the nearest defined point. +@item linear +Interpolate values using the linear interpolation. +@end table +@end table + @anchor{lut3d} @section lut3d diff --git a/libavfilter/Makefile b/libavfilter/Makefile index e5d3a57af7..e412000c8f 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -258,6 +258,7 @@ OBJS-$(CONFIG_LIBVMAF_FILTER)+= vf_libvmaf.o framesync.o OBJS-$(CONFIG_LIMITER_FILTER)+= vf_limiter.o OBJS-$(CONFIG_LOOP_FILTER) += f_loop.o OBJS-$(CONFIG_LUMAKEY_FILTER)+= vf_lumakey.o +OBJS-$(CONFIG_LUT1D_FILTER) += vf_lut3d.o OBJS-$(CONFIG_LUT_FILTER)+= vf_lut.o OBJS-$(CONFIG_LUT2_FILTER) += vf_lut2.o framesync.o OBJS-$(CONFIG_LUT3D_FILTER) += vf_lut3d.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 9732ae5345..2fa9460335 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -246,6 +246,7 @@ extern AVFilter ff_vf_limiter; extern AVFilter ff_vf_loop; extern AVFilter ff_vf_lumakey; extern AVFilter ff_vf_lut; +extern AVFilter ff_vf_lut1d; extern AVFilter ff_vf_lut2; extern AVFilter ff_vf_lut3d; extern AVFilter ff_vf_lutrgb; diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c index 27b79b860b..b5673b82bf 100644 --- a/libavfilter/vf_lut3d.c +++ b/libavfilter/vf_lut3d.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013 Clément Bœsch + * Copyright (c) 2018 Paul B Mahol * * This file is part of FFmpeg. * @@ -975,3 +976,406 @@ AVFilter ff_vf_haldclut = { .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; #endif + +#if CONFIG_LUT1D_FILTER + +enum interp_1d_mode { +INTERPOLATE_1D_NEAREST, +INTERPOLATE_1D_LINEAR, +NB_INTERP_1D_MODE +}; + +#define MAX_1D_LEVEL 65536 + +typedef struct LUT1DContext { +const AVClass *class; +char *file; +int interpolation; ///lutsize = size; +for (i = 0; i < size; i++) { +lut1d->lut[0][i] = i * c; +lut1d->lut[1][i] = i * c; +lut1d->lut[2][i] = i * c; +} +} + +static int parse_cube_1d(AVFilterContext *ctx, FILE *f) +{ +LUT1DContext *lut1d = ctx->priv; +char line[MAX_LINE_SIZE]; +float min[3] = {0.0, 0.0, 0.0}; +float max[3] = {1.0, 1.0, 1.0}; + +while (fgets(line, sizeof(line), f)) { +if (!strncmp(line, "LUT_1D_SIZE ", 12)) { +const int size = strtol(line + 12, NULL, 0); +int i; + +if (size < 2 || size > MAX_1D_LEVEL) { +av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n"); +return AVERROR(EINVAL); +} +lut1d->lutsize = size; +for (i = 0; i < size; i++) { +do { +try_again: +NEXT_LINE(0); +if (!strncmp(line, "DOMAIN_", 7)) { +float *vals = NULL; +if (!strncmp(line + 7, "MIN ", 4)) vals = min; +else if (!strncmp(line + 7, "MAX ", 4)) vals = max; +if (!vals) +return AVERROR_INVALIDDATA; +sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2); +av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n", + min[0], min[1], min[2], max[0], max[1], max[2]); +goto try_again; +} +} while (skip_line(line)); +if (sscanf(line, "%f %f %f", >lut[0][i], >lut[1][i], >lut[2][i]) != 3) +return AVERROR_INVALIDDATA; +lut1d->lut[0][i] *= max[0] - min[0]; +lut1d->lut[1][i] *= max[1] - min[1]; +lut1d->lut[2][i] *= max[2] - min[2]; +} +break; +} +} +return 0; +} + +static const AVOption lut1d_options[] = { +{ "file", "set 1D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, +{ "interp", "select interpolation mode",