avfilter/vf_lut: >8 bit depth planar yuv support

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol 2015-07-01 09:39:24 +00:00
parent daff49ccf3
commit b74ebd09c7
2 changed files with 100 additions and 12 deletions

View File

@ -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 {
/* planar */
} 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 uint8_t *tab = s->lut[plane];
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 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 uint16_t *tab = s->lut[plane];
const int in_linesize = in->linesize[plane];
const int out_linesize = out->linesize[plane];

View File

@ -7,12 +7,32 @@ rgba 7bc854c2698b78af3e9159a19c2d9d21
yuv410p 51b39a0e33f108e652457a26667319ea
yuv411p 9204c5af92aef4922a05f58c1f6c095e
yuv420p 7c43bb0cae8dee633375c89295598508
yuv420p10le 1352712dd31cce78bd5441294004cf85
yuv420p12le c66f82da9fda458ba3abda057c58e591
yuv420p14le e45cb5e2a75bf6143da0b55004767f78
yuv420p16le eff54782c51770edfd6b84c958ac7120
yuv420p9le 62bf40b1cb97660238c991efa6ef2962
yuv422p 67df35da0c35e54882492b2365438254
yuv422p10le 0158371a800294015def7f0ef66c78ea
yuv422p12le bc49d3863ffb89658a17bf8c4fe773b0
yuv422p14le b55cb791d286b0b3391fe7481785e5b3
yuv422p16le fc3b2ba889ffaf1633000fc774307c33
yuv422p9le bb6d5a46073ff4aabfcd2f97416ccb59
yuv440p 5e41adcfc27be4369afd217b61b2ffe3
yuv440p10le 8b49714bba268fb4a79b5a84223ad17a
yuv440p12le 15ab4f453238bd9c13b18af81e22f060
yuv444p a2b58590aef88db2c1f14a1a3a3b0359
yuv444p10le c076c20fc808f95b34adb88aca442f48
yuv444p12le af8d4dd88169d5cffc2f3fce6333a94c
yuv444p14le 93367133e25d088d4535199ed1f1ed58
yuv444p16le 800940feec14365ccd9b4863e38f6991
yuv444p9le 08cab94dfa6d2a688f9a8cbac8c4b61b
yuva420p 518a380bf1af60ef2ecf4754eec088e9
yuva420p16le 72ad4fa535b007d122666ce103ef9c8b
yuva422p 7110ac2e37377b05b6fc5ad967dfabb5
yuva422p16le e2867210660ada5784a60b4339ac52c0
yuva444p 642f3958f141dece9e99407945e2ef43
yuva444p16le ab04ba8acbe38085b0df650d82065eb0
yuvj420p 65bc88887c7f06a6221155ca7f9cfca4
yuvj422p ff5baffefc8ffe4547653092fd7da200
yuvj440p ef3f27270e60ac06582e3ac7c2f3e6fa