diff --git a/libavfilter/colorchannelmixer_template.c b/libavfilter/colorchannelmixer_template.c index 0f15f8fd07..bef57476aa 100644 --- a/libavfilter/colorchannelmixer_template.c +++ b/libavfilter/colorchannelmixer_template.c @@ -21,10 +21,21 @@ #include #undef pixel +#undef cpixel +#undef ROUND #if DEPTH == 8 #define pixel uint8_t +#define cpixel int +#define ROUND lrintf #elif DEPTH == 16 #define pixel uint16_t +#define cpixel int +#define ROUND lrintf +#else +#define NOP(x) (x) +#define pixel float +#define cpixel float +#define ROUND NOP #endif #undef fn @@ -60,8 +71,22 @@ static av_always_inline int fn(filter_slice_rgba_planar)(AVFilterContext *ctx, v const pixel gin = srcg[j]; const pixel bin = srcb[j]; const pixel ain = have_alpha ? srca[j] : 0; - int rout, gout, bout; + cpixel rout, gout, bout; +#if DEPTH == 32 + rout = s->rr * rin + + s->rg * gin + + s->rb * bin + + (have_alpha == 1 ? s->ra * ain : 0); + gout = s->gr * rin + + s->gg * gin + + s->gb * bin + + (have_alpha == 1 ? s->ga * ain : 0); + bout = s->br * rin + + s->bg * gin + + s->bb * bin + + (have_alpha == 1 ? s->ba * ain : 0); +#else rout = s->lut[R][R][rin] + s->lut[R][G][gin] + s->lut[R][B][bin] + @@ -74,31 +99,52 @@ static av_always_inline int fn(filter_slice_rgba_planar)(AVFilterContext *ctx, v s->lut[B][G][gin] + s->lut[B][B][bin] + (have_alpha == 1 ? s->lut[B][A][ain] : 0); +#endif if (pc) { - float frout = av_clipf(rout, 0.f, max); - float fgout = av_clipf(gout, 0.f, max); - float fbout = av_clipf(bout, 0.f, max); - float lin, lout; + float frout, fgout, fbout, lin, lout; + +#if DEPTH < 32 + frout = av_clipf(rout, 0.f, max); + fgout = av_clipf(gout, 0.f, max); + fbout = av_clipf(bout, 0.f, max); +#else + frout = rout; + fgout = gout; + fbout = bout; +#endif preserve_color(s->preserve_color, rin, gin, bin, rout, gout, bout, max, &lin, &lout); preservel(&frout, &fgout, &fbout, lin, lout, max); - rout = lrintf(lerpf(rout, frout, pa)); - gout = lrintf(lerpf(gout, fgout, pa)); - bout = lrintf(lerpf(bout, fbout, pa)); + rout = ROUND(lerpf(rout, frout, pa)); + gout = ROUND(lerpf(gout, fgout, pa)); + bout = ROUND(lerpf(bout, fbout, pa)); } +#if DEPTH < 32 dstr[j] = av_clip_uintp2(rout, depth); dstg[j] = av_clip_uintp2(gout, depth); dstb[j] = av_clip_uintp2(bout, depth); +#else + dstr[j] = rout; + dstg[j] = gout; + dstb[j] = bout; +#endif if (have_alpha == 1) { +#if DEPTH < 32 dsta[j] = av_clip_uintp2(s->lut[A][R][rin] + s->lut[A][G][gin] + s->lut[A][B][bin] + s->lut[A][A][ain], depth); +#else + dsta[j] = s->ar * rin + + s->ag * gin + + s->ab * bin + + s->aa * ain; +#endif } } @@ -115,6 +161,8 @@ static av_always_inline int fn(filter_slice_rgba_planar)(AVFilterContext *ctx, v return 0; } +#if DEPTH < 32 + static av_always_inline int fn(filter_slice_rgba_packed)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step, int pc, int depth) { @@ -191,3 +239,5 @@ static av_always_inline int fn(filter_slice_rgba_packed)(AVFilterContext *ctx, v return 0; } + +#endif diff --git a/libavfilter/vf_colorchannelmixer.c b/libavfilter/vf_colorchannelmixer.c index b32e0a9d0e..88dd7451dc 100644 --- a/libavfilter/vf_colorchannelmixer.c +++ b/libavfilter/vf_colorchannelmixer.c @@ -77,6 +77,10 @@ static void preservel(float *r, float *g, float *b, float lin, float lout, float #define DEPTH 16 #include "colorchannelmixer_template.c" +#undef DEPTH +#define DEPTH 32 +#include "colorchannelmixer_template.c" + #define OFFSET(x) offsetof(ColorChannelMixerContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM @@ -125,6 +129,7 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; @@ -278,6 +283,26 @@ static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, -1, 4, 1, 8); } +static int filter_slice_gbrp32(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 0, 1, 0); +} + +static int filter_slice_gbrap32(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 1, 1, 0); +} + +static int filter_slice_gbrp32_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 0, 1, 1); +} + +static int filter_slice_gbrap32_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 1, 1, 1); +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -391,6 +416,14 @@ static int config_output(AVFilterLink *outlink) s->filter_slice[0] = filter_slice_gbrap16; s->filter_slice[1] = filter_slice_gbrap16_pl; break; + case AV_PIX_FMT_GBRPF32: + s->filter_slice[0] = filter_slice_gbrp32; + s->filter_slice[1] = filter_slice_gbrp32_pl; + break; + case AV_PIX_FMT_GBRAPF32: + s->filter_slice[0] = filter_slice_gbrap32; + s->filter_slice[1] = filter_slice_gbrap32_pl; + break; } return 0;