|
|
|
@@ -59,12 +59,13 @@ enum var_name { |
|
|
|
|
|
|
|
typedef struct LutContext { |
|
|
|
const AVClass *class; |
|
|
|
uint8_t lut[4][256]; ///< lookup table for each component |
|
|
|
uint16_t lut[4][256 * 256]; ///< lookup table for each component |
|
|
|
char *comp_expr_str[4]; |
|
|
|
AVExpr *comp_expr[4]; |
|
|
|
int hsub, vsub; |
|
|
|
double var_values[VAR_VARS_NB]; |
|
|
|
int is_rgb, is_yuv; |
|
|
|
int is_16bit; |
|
|
|
int step; |
|
|
|
int negate_alpha; /* only used by negate */ |
|
|
|
} LutContext; |
|
|
|
@@ -112,7 +113,13 @@ static av_cold void uninit(AVFilterContext *ctx) |
|
|
|
AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, \ |
|
|
|
AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, \ |
|
|
|
AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, \ |
|
|
|
AV_PIX_FMT_YUVJ440P |
|
|
|
AV_PIX_FMT_YUVJ440P, \ |
|
|
|
AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUV422P9LE, AV_PIX_FMT_YUV420P9, \ |
|
|
|
AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUV440P10LE, \ |
|
|
|
AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV422P12LE, AV_PIX_FMT_YUV420P12LE, AV_PIX_FMT_YUV440P12LE, \ |
|
|
|
AV_PIX_FMT_YUV444P14LE, AV_PIX_FMT_YUV422P14LE, AV_PIX_FMT_YUV420P14LE, \ |
|
|
|
AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUV422P16LE, AV_PIX_FMT_YUV420P16LE, \ |
|
|
|
AV_PIX_FMT_YUVA444P16LE, AV_PIX_FMT_YUVA422P16LE, AV_PIX_FMT_YUVA420P16LE |
|
|
|
|
|
|
|
#define RGB_FORMATS \ |
|
|
|
AV_PIX_FMT_ARGB, AV_PIX_FMT_RGBA, \ |
|
|
|
@@ -205,6 +212,7 @@ static int config_props(AVFilterLink *inlink) |
|
|
|
|
|
|
|
s->var_values[VAR_W] = inlink->w; |
|
|
|
s->var_values[VAR_H] = inlink->h; |
|
|
|
s->is_16bit = desc->comp[0].depth_minus1 > 7; |
|
|
|
|
|
|
|
switch (inlink->format) { |
|
|
|
case AV_PIX_FMT_YUV410P: |
|
|
|
@@ -216,10 +224,40 @@ static int config_props(AVFilterLink *inlink) |
|
|
|
case AV_PIX_FMT_YUVA420P: |
|
|
|
case AV_PIX_FMT_YUVA422P: |
|
|
|
case AV_PIX_FMT_YUVA444P: |
|
|
|
min[Y] = min[U] = min[V] = 16; |
|
|
|
max[Y] = 235; |
|
|
|
max[U] = max[V] = 240; |
|
|
|
min[A] = 0; max[A] = 255; |
|
|
|
case AV_PIX_FMT_YUV420P9LE: |
|
|
|
case AV_PIX_FMT_YUV422P9LE: |
|
|
|
case AV_PIX_FMT_YUV444P9LE: |
|
|
|
case AV_PIX_FMT_YUVA420P9LE: |
|
|
|
case AV_PIX_FMT_YUVA422P9LE: |
|
|
|
case AV_PIX_FMT_YUVA444P9LE: |
|
|
|
case AV_PIX_FMT_YUV420P10LE: |
|
|
|
case AV_PIX_FMT_YUV422P10LE: |
|
|
|
case AV_PIX_FMT_YUV440P10LE: |
|
|
|
case AV_PIX_FMT_YUV444P10LE: |
|
|
|
case AV_PIX_FMT_YUVA420P10LE: |
|
|
|
case AV_PIX_FMT_YUVA422P10LE: |
|
|
|
case AV_PIX_FMT_YUVA444P10LE: |
|
|
|
case AV_PIX_FMT_YUV420P12LE: |
|
|
|
case AV_PIX_FMT_YUV422P12LE: |
|
|
|
case AV_PIX_FMT_YUV440P12LE: |
|
|
|
case AV_PIX_FMT_YUV444P12LE: |
|
|
|
case AV_PIX_FMT_YUV420P14LE: |
|
|
|
case AV_PIX_FMT_YUV422P14LE: |
|
|
|
case AV_PIX_FMT_YUV444P14LE: |
|
|
|
case AV_PIX_FMT_YUV420P16LE: |
|
|
|
case AV_PIX_FMT_YUV422P16LE: |
|
|
|
case AV_PIX_FMT_YUV444P16LE: |
|
|
|
case AV_PIX_FMT_YUVA420P16LE: |
|
|
|
case AV_PIX_FMT_YUVA422P16LE: |
|
|
|
case AV_PIX_FMT_YUVA444P16LE: |
|
|
|
min[Y] = 16 * (1 << (desc->comp[0].depth_minus1 - 7)); |
|
|
|
min[U] = 16 * (1 << (desc->comp[1].depth_minus1 - 7)); |
|
|
|
min[V] = 16 * (1 << (desc->comp[2].depth_minus1 - 7)); |
|
|
|
min[A] = 0; |
|
|
|
max[Y] = 235 * (1 << (desc->comp[0].depth_minus1 - 7)); |
|
|
|
max[U] = 240 * (1 << (desc->comp[1].depth_minus1 - 7)); |
|
|
|
max[V] = 240 * (1 << (desc->comp[2].depth_minus1 - 7)); |
|
|
|
max[A] = (1 << (desc->comp[3].depth_minus1 + 1)) - 1; |
|
|
|
break; |
|
|
|
default: |
|
|
|
min[0] = min[1] = min[2] = min[3] = 0; |
|
|
|
@@ -255,7 +293,7 @@ static int config_props(AVFilterLink *inlink) |
|
|
|
s->var_values[VAR_MAXVAL] = max[color]; |
|
|
|
s->var_values[VAR_MINVAL] = min[color]; |
|
|
|
|
|
|
|
for (val = 0; val < 256; val++) { |
|
|
|
for (val = 0; val < (1 << (desc->comp[0].depth_minus1 + 1)); val++) { |
|
|
|
s->var_values[VAR_VAL] = val; |
|
|
|
s->var_values[VAR_CLIPVAL] = av_clip(val, min[color], max[color]); |
|
|
|
s->var_values[VAR_NEGVAL] = |
|
|
|
@@ -283,7 +321,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
|
|
LutContext *s = ctx->priv; |
|
|
|
AVFilterLink *outlink = ctx->outputs[0]; |
|
|
|
AVFrame *out; |
|
|
|
uint8_t *inrow, *outrow, *inrow0, *outrow0; |
|
|
|
int i, j, plane, direct = 0; |
|
|
|
|
|
|
|
if (av_frame_is_writable(in)) { |
|
|
|
@@ -300,9 +337,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
|
|
|
|
|
|
if (s->is_rgb) { |
|
|
|
/* packed */ |
|
|
|
uint8_t *inrow, *outrow, *inrow0, *outrow0; |
|
|
|
const int w = inlink->w; |
|
|
|
const int h = in->height; |
|
|
|
const uint8_t (*tab)[256] = (const uint8_t (*)[256])s->lut; |
|
|
|
const uint16_t (*tab)[256*256] = (const uint16_t (*)[256*256])s->lut; |
|
|
|
const int in_linesize = in->linesize[0]; |
|
|
|
const int out_linesize = out->linesize[0]; |
|
|
|
const int step = s->step; |
|
|
|
@@ -326,14 +364,44 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
|
|
inrow0 += in_linesize; |
|
|
|
outrow0 += out_linesize; |
|
|
|
} |
|
|
|
} else if (s->is_16bit) { |
|
|
|
// planar yuv >8 bit depth |
|
|
|
uint16_t *inrow, *outrow; |
|
|
|
|
|
|
|
for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { |
|
|
|
int vsub = plane == 1 || plane == 2 ? s->vsub : 0; |
|
|
|
int hsub = plane == 1 || plane == 2 ? s->hsub : 0; |
|
|
|
int h = FF_CEIL_RSHIFT(inlink->h, vsub); |
|
|
|
int w = FF_CEIL_RSHIFT(inlink->w, hsub); |
|
|
|
const uint16_t *tab = s->lut[plane]; |
|
|
|
const int in_linesize = in->linesize[plane] / 2; |
|
|
|
const int out_linesize = out->linesize[plane] / 2; |
|
|
|
|
|
|
|
inrow = (uint16_t *)in ->data[plane]; |
|
|
|
outrow = (uint16_t *)out->data[plane]; |
|
|
|
|
|
|
|
for (i = 0; i < h; i++) { |
|
|
|
for (j = 0; j < w; j++) { |
|
|
|
#if HAVE_BIGENDIAN |
|
|
|
outrow[j] = av_bswap16(tab[av_bswap16(inrow[j])]); |
|
|
|
#else |
|
|
|
outrow[j] = tab[inrow[j]]; |
|
|
|
#endif |
|
|
|
} |
|
|
|
inrow += in_linesize; |
|
|
|
outrow += out_linesize; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
/* planar */ |
|
|
|
/* planar 8bit depth */ |
|
|
|
uint8_t *inrow, *outrow; |
|
|
|
|
|
|
|
for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { |
|
|
|
int vsub = plane == 1 || plane == 2 ? s->vsub : 0; |
|
|
|
int hsub = plane == 1 || plane == 2 ? s->hsub : 0; |
|
|
|
int h = FF_CEIL_RSHIFT(inlink->h, vsub); |
|
|
|
int w = FF_CEIL_RSHIFT(inlink->w, hsub); |
|
|
|
const uint8_t *tab = s->lut[plane]; |
|
|
|
const uint16_t *tab = s->lut[plane]; |
|
|
|
const int in_linesize = in->linesize[plane]; |
|
|
|
const int out_linesize = out->linesize[plane]; |
|
|
|
|
|
|
|
|