aboutsummaryrefslogtreecommitdiffstats
path: root/libavfilter/vf_lut.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2015-07-01 09:39:24 +0000
committerPaul B Mahol <onemda@gmail.com>2015-07-03 09:29:06 +0000
commitb74ebd09c719ad250de6e5cdf8fb5663cb0212c8 (patch)
treee12c250c273c57c9ceae613cfd6ecc1fd33a26e2 /libavfilter/vf_lut.c
parentdaff49ccf3e5d9e90851595c4ea3199140f40f50 (diff)
downloadffmpeg-b74ebd09c719ad250de6e5cdf8fb5663cb0212c8.tar.gz
avfilter/vf_lut: >8 bit depth planar yuv support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavfilter/vf_lut.c')
-rw-r--r--libavfilter/vf_lut.c90
1 files changed, 79 insertions, 11 deletions
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index 93b18a82cb..fafa67f70a 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -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];