summaryrefslogtreecommitdiff
path: root/libavfilter/vf_lut.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavfilter/vf_lut.c')
-rw-r--r--libavfilter/vf_lut.c125
1 files changed, 61 insertions, 64 deletions
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index 3817228960..9c8b4123cf 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -1,20 +1,20 @@
/*
* Copyright (c) 2011 Stefano Sabatini
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -25,7 +25,6 @@
*/
#include "libavutil/eval.h"
-#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "avfilter.h"
@@ -34,9 +33,6 @@
#include "video.h"
static const char *const var_names[] = {
- "E",
- "PHI",
- "PI",
"w", ///< width of the input video
"h", ///< height of the input video
"val", ///< input value for the pixel
@@ -48,9 +44,6 @@ static const char *const var_names[] = {
};
enum var_name {
- VAR_E,
- VAR_PHI,
- VAR_PI,
VAR_W,
VAR_H,
VAR_VAL,
@@ -69,7 +62,6 @@ typedef struct {
int hsub, vsub;
double var_values[VAR_VARS_NB];
int is_rgb, is_yuv;
- int rgba_map[4];
int step;
int negate_alpha; /* only used by negate */
} LutContext;
@@ -85,28 +77,23 @@ typedef struct {
#define OFFSET(x) offsetof(LutContext, x)
static const AVOption lut_options[] = {
- {"c0", "set component #0 expression", OFFSET(comp_expr_str[0]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"c1", "set component #1 expression", OFFSET(comp_expr_str[1]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"c2", "set component #2 expression", OFFSET(comp_expr_str[2]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"c3", "set component #3 expression", OFFSET(comp_expr_str[3]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"y", "set Y expression", OFFSET(comp_expr_str[Y]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"u", "set U expression", OFFSET(comp_expr_str[U]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"v", "set V expression", OFFSET(comp_expr_str[V]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"r", "set R expression", OFFSET(comp_expr_str[R]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"g", "set G expression", OFFSET(comp_expr_str[G]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"b", "set B expression", OFFSET(comp_expr_str[B]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
- {"a", "set A expression", OFFSET(comp_expr_str[A]), FF_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"y", "set Y expression", OFFSET(comp_expr_str[Y]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"u", "set U expression", OFFSET(comp_expr_str[U]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"v", "set V expression", OFFSET(comp_expr_str[V]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"r", "set R expression", OFFSET(comp_expr_str[R]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"g", "set G expression", OFFSET(comp_expr_str[G]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"b", "set B expression", OFFSET(comp_expr_str[B]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
+ {"a", "set A expression", OFFSET(comp_expr_str[A]), AV_OPT_TYPE_STRING, {.str="val"}, CHAR_MIN, CHAR_MAX},
{NULL},
};
-static const char *lut_get_name(void *ctx)
-{
- return "lut";
-}
-
static const AVClass lut_class = {
"LutContext",
- lut_get_name,
+ av_default_item_name,
lut_options
};
@@ -118,10 +105,6 @@ static int init(AVFilterContext *ctx, const char *args, void *opaque)
lut->class = &lut_class;
av_opt_set_defaults(lut);
- lut->var_values[VAR_PHI] = M_PHI;
- lut->var_values[VAR_PI] = M_PI;
- lut->var_values[VAR_E ] = M_E;
-
lut->is_rgb = !strcmp(ctx->filter->name, "lutrgb");
lut->is_yuv = !strcmp(ctx->filter->name, "lutyuv");
if (args && (ret = av_set_options_string(lut, args, "=", ":")) < 0)
@@ -154,16 +137,16 @@ static av_cold void uninit(AVFilterContext *ctx)
PIX_FMT_ABGR, PIX_FMT_BGRA, \
PIX_FMT_RGB24, PIX_FMT_BGR24
-static enum PixelFormat yuv_pix_fmts[] = { YUV_FORMATS, PIX_FMT_NONE };
-static enum PixelFormat rgb_pix_fmts[] = { RGB_FORMATS, PIX_FMT_NONE };
-static enum PixelFormat all_pix_fmts[] = { RGB_FORMATS, YUV_FORMATS, PIX_FMT_NONE };
+static const enum PixelFormat yuv_pix_fmts[] = { YUV_FORMATS, PIX_FMT_NONE };
+static const enum PixelFormat rgb_pix_fmts[] = { RGB_FORMATS, PIX_FMT_NONE };
+static const enum PixelFormat all_pix_fmts[] = { RGB_FORMATS, YUV_FORMATS, PIX_FMT_NONE };
static int query_formats(AVFilterContext *ctx)
{
LutContext *lut = ctx->priv;
- enum PixelFormat *pix_fmts = lut->is_rgb ? rgb_pix_fmts :
- lut->is_yuv ? yuv_pix_fmts : all_pix_fmts;
+ const enum PixelFormat *pix_fmts = lut->is_rgb ? rgb_pix_fmts :
+ lut->is_yuv ? yuv_pix_fmts : all_pix_fmts;
ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
return 0;
@@ -196,8 +179,8 @@ static double compute_gammaval(void *opaque, double gamma)
}
static double (* const funcs1[])(void *, double) = {
- clip,
- compute_gammaval,
+ (void *)clip,
+ (void *)compute_gammaval,
NULL
};
@@ -212,6 +195,7 @@ static int config_props(AVFilterLink *inlink)
AVFilterContext *ctx = inlink->dst;
LutContext *lut = ctx->priv;
const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format];
+ int rgba_map[4]; /* component index -> RGBA color index map */
int min[4], max[4];
int val, comp, ret;
@@ -245,48 +229,49 @@ static int config_props(AVFilterLink *inlink)
if (lut->is_rgb) {
switch (inlink->format) {
- case PIX_FMT_ARGB: lut->rgba_map[A] = 0; lut->rgba_map[R] = 1; lut->rgba_map[G] = 2; lut->rgba_map[B] = 3; break;
- case PIX_FMT_ABGR: lut->rgba_map[A] = 0; lut->rgba_map[B] = 1; lut->rgba_map[G] = 2; lut->rgba_map[R] = 3; break;
+ case PIX_FMT_ARGB: rgba_map[0] = A; rgba_map[1] = R; rgba_map[2] = G; rgba_map[3] = B; break;
+ case PIX_FMT_ABGR: rgba_map[0] = A; rgba_map[1] = B; rgba_map[2] = G; rgba_map[3] = R; break;
case PIX_FMT_RGBA:
- case PIX_FMT_RGB24: lut->rgba_map[R] = 0; lut->rgba_map[G] = 1; lut->rgba_map[B] = 2; lut->rgba_map[A] = 3; break;
+ case PIX_FMT_RGB24: rgba_map[0] = R; rgba_map[1] = G; rgba_map[2] = B; rgba_map[3] = A; break;
case PIX_FMT_BGRA:
- case PIX_FMT_BGR24: lut->rgba_map[B] = 0; lut->rgba_map[G] = 1; lut->rgba_map[R] = 2; lut->rgba_map[A] = 3; break;
+ case PIX_FMT_BGR24: rgba_map[0] = B; rgba_map[1] = G; rgba_map[2] = R; rgba_map[3] = A; break;
}
lut->step = av_get_bits_per_pixel(desc) >> 3;
}
for (comp = 0; comp < desc->nb_components; comp++) {
double res;
+ int color = lut->is_rgb ? rgba_map[comp] : comp;
/* create the parsed expression */
- ret = av_expr_parse(&lut->comp_expr[comp], lut->comp_expr_str[comp],
+ ret = av_expr_parse(&lut->comp_expr[color], lut->comp_expr_str[color],
var_names, funcs1_names, funcs1, NULL, NULL, 0, ctx);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR,
- "Error when parsing the expression '%s' for the component %d.\n",
- lut->comp_expr_str[comp], comp);
+ "Error when parsing the expression '%s' for the component %d and color %d.\n",
+ lut->comp_expr_str[comp], comp, color);
return AVERROR(EINVAL);
}
/* compute the lut */
- lut->var_values[VAR_MAXVAL] = max[comp];
- lut->var_values[VAR_MINVAL] = min[comp];
+ lut->var_values[VAR_MAXVAL] = max[color];
+ lut->var_values[VAR_MINVAL] = min[color];
for (val = 0; val < 256; val++) {
lut->var_values[VAR_VAL] = val;
- lut->var_values[VAR_CLIPVAL] = av_clip(val, min[comp], max[comp]);
+ lut->var_values[VAR_CLIPVAL] = av_clip(val, min[color], max[color]);
lut->var_values[VAR_NEGVAL] =
- av_clip(min[comp] + max[comp] - lut->var_values[VAR_VAL],
- min[comp], max[comp]);
+ av_clip(min[color] + max[color] - lut->var_values[VAR_VAL],
+ min[color], max[color]);
- res = av_expr_eval(lut->comp_expr[comp], lut->var_values, lut);
+ res = av_expr_eval(lut->comp_expr[color], lut->var_values, lut);
if (isnan(res)) {
av_log(ctx, AV_LOG_ERROR,
- "Error when evaluating the expression '%s' for the value %d for the component #%d.\n",
- lut->comp_expr_str[comp], val, comp);
+ "Error when evaluating the expression '%s' for the value %d for the component %d.\n",
+ lut->comp_expr_str[color], val, comp);
return AVERROR(EINVAL);
}
- lut->lut[comp][val] = av_clip((int)res, min[comp], max[comp]);
+ lut->lut[comp][val] = av_clip((int)res, min[color], max[color]);
av_log(ctx, AV_LOG_DEBUG, "val[%d][%d] = %d\n", comp, val, lut->lut[comp][val]);
}
}
@@ -302,7 +287,7 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
AVFilterBufferRef *inpic = inlink ->cur_buf;
AVFilterBufferRef *outpic = outlink->out_buf;
uint8_t *inrow, *outrow, *inrow0, *outrow0;
- int i, j, k, plane;
+ int i, j, plane;
if (lut->is_rgb) {
/* packed */
@@ -310,11 +295,21 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
outrow0 = outpic->data[0] + y * outpic->linesize[0];
for (i = 0; i < h; i ++) {
+ int w = inlink->w;
+ const uint8_t (*tab)[256] = (const uint8_t (*)[256])lut->lut;
inrow = inrow0;
outrow = outrow0;
- for (j = 0; j < inlink->w; j++) {
- for (k = 0; k < lut->step; k++)
- outrow[k] = lut->lut[lut->rgba_map[k]][inrow[k]];
+ for (j = 0; j < w; j++) {
+ outrow[0] = tab[0][inrow[0]];
+ if (lut->step>1) {
+ outrow[1] = tab[1][inrow[1]];
+ if (lut->step>2) {
+ outrow[2] = tab[2][inrow[2]];
+ if (lut->step>3) {
+ outrow[3] = tab[3][inrow[3]];
+ }
+ }
+ }
outrow += lut->step;
inrow += lut->step;
}
@@ -331,8 +326,10 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane];
for (i = 0; i < h>>vsub; i ++) {
- for (j = 0; j < inlink->w>>hsub; j++)
- outrow[j] = lut->lut[plane][inrow[j]];
+ const uint8_t *tab = lut->lut[plane];
+ int w = inlink->w>>hsub;
+ for (j = 0; j < w; j++)
+ outrow[j] = tab[inrow[j]];
inrow += inpic ->linesize[plane];
outrow += outpic->linesize[plane];
}
@@ -352,13 +349,13 @@ static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
.uninit = uninit, \
.query_formats = query_formats, \
\
- .inputs = (AVFilterPad[]) {{ .name = "default", \
+ .inputs = (const AVFilterPad[]) {{ .name = "default", \
.type = AVMEDIA_TYPE_VIDEO, \
.draw_slice = draw_slice, \
.config_props = config_props, \
.min_perms = AV_PERM_READ, }, \
{ .name = NULL}}, \
- .outputs = (AVFilterPad[]) {{ .name = "default", \
+ .outputs = (const AVFilterPad[]) {{ .name = "default", \
.type = AVMEDIA_TYPE_VIDEO, }, \
{ .name = NULL}}, \
}