From b74ebd09c719ad250de6e5cdf8fb5663cb0212c8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 1 Jul 2015 09:39:24 +0000 Subject: [PATCH] avfilter/vf_lut: >8 bit depth planar yuv support Signed-off-by: Paul B Mahol --- libavfilter/vf_lut.c | 92 +++++++++++++++++++++++++++---- tests/ref/fate/filter-pixfmts-lut | 20 +++++++ 2 files changed, 100 insertions(+), 12 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 { - /* 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]; diff --git a/tests/ref/fate/filter-pixfmts-lut b/tests/ref/fate/filter-pixfmts-lut index 1deac4c6c9..150157cb64 100644 --- a/tests/ref/fate/filter-pixfmts-lut +++ b/tests/ref/fate/filter-pixfmts-lut @@ -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