From: Limin Wang <lance.lmw...@gmail.com> Signed-off-by: Limin Wang <lance.lmw...@gmail.com> --- libavfilter/vf_colorlevels.c | 176 +++++++++++++++-------------------- 1 file changed, 77 insertions(+), 99 deletions(-)
diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c index 5385a5e754..f8645a08bd 100644 --- a/libavfilter/vf_colorlevels.c +++ b/libavfilter/vf_colorlevels.c @@ -26,6 +26,7 @@ #include "formats.h" #include "internal.h" #include "video.h" +#include "thread.h" #define R 0 #define G 1 @@ -37,6 +38,11 @@ typedef struct Range { double out_min, out_max; } Range; +typedef struct ThreadData { + AVFrame *in; + AVFrame *out; +} ThreadData; + typedef struct ColorLevelsContext { const AVClass *class; Range range[4]; @@ -45,6 +51,7 @@ typedef struct ColorLevelsContext { int step; uint8_t rgba_map[4]; int linesize; + int (*colorlevels_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ColorLevelsContext; #define OFFSET(x) offsetof(ColorLevelsContext, x) @@ -90,6 +97,68 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_formats(ctx, fmts_list); } +#define DEFINE_COLORLEVELS(type, nbits) \ +static int do_##nbits##bit_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + ColorLevelsContext *s = ctx->priv; \ + AVFilterLink *inlink = ctx->inputs[0]; \ + const int step = s->step; \ + int x, y, i; \ + ThreadData *td = arg; \ + const AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + \ + for (i = 0; i < s->nb_comp; i++) { \ + Range *r = &s->range[i]; \ + const int slice_start = (inlink->h * jobnr) / nb_jobs; \ + const int slice_end = (inlink->h * (jobnr+1)) / nb_jobs; \ + const uint8_t offset = s->rgba_map[i]; \ + const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0]; \ + uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \ + int imin = lrint(r->in_min * UINT##nbits##_MAX); \ + int imax = lrint(r->in_max * UINT##nbits##_MAX); \ + int omin = lrint(r->out_min * UINT##nbits##_MAX); \ + int omax = lrint(r->out_max * UINT##nbits##_MAX); \ + double coeff; \ + \ + if (imin < 0) { \ + imin = UINT##nbits##_MAX; \ + for (y = slice_start; y < slice_end; y++) { \ + const type *src = (const type *)srcrow; \ + \ + for (x = 0; x < s->linesize; x += step) \ + imin = FFMIN(imin, src[x + offset]); \ + srcrow += in->linesize[0]; \ + } \ + } \ + if (imax < 0) { \ + imax = 0; \ + for (y = slice_start; y < slice_end; y++) { \ + const type *src = (const type *)srcrow; \ + \ + for (x = 0; x < s->linesize; x += step) \ + imax = FFMAX(imax, src[x + offset]); \ + srcrow += in->linesize[0]; \ + } \ + } \ + \ + coeff = (omax - omin) / (double)(imax - imin); \ + for (y = slice_start; y < slice_end; y++) { \ + const type *src = (const type*)srcrow; \ + type *dst = (type *)dstrow; \ + \ + for (x = 0; x < s->linesize; x += step) \ + dst[x + offset] = av_clip_uint##nbits( \ + (src[x + offset] - imin) * coeff + omin); \ + dstrow += out->linesize[0]; \ + srcrow += in->linesize[0]; \ + } \ + } \ + return 0; \ +} +DEFINE_COLORLEVELS(uint8_t, 8) +DEFINE_COLORLEVELS(uint16_t, 16) + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -102,17 +171,17 @@ static int config_input(AVFilterLink *inlink) s->linesize = inlink->w * s->step; ff_fill_rgba_map(s->rgba_map, inlink->format); + s->colorlevels_slice = s->bpp <= 1 ? do_8bit_slice : do_16bit_slice; return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; - ColorLevelsContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - const int step = s->step; + ColorLevelsContext *s = ctx->priv; AVFrame *out; - int x, y, i; + ThreadData td; if (av_frame_is_writable(in)) { out = in; @@ -125,101 +194,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - switch (s->bpp) { - case 1: - for (i = 0; i < s->nb_comp; i++) { - Range *r = &s->range[i]; - const uint8_t offset = s->rgba_map[i]; - const uint8_t *srcrow = in->data[0]; - uint8_t *dstrow = out->data[0]; - int imin = lrint(r->in_min * UINT8_MAX); - int imax = lrint(r->in_max * UINT8_MAX); - int omin = lrint(r->out_min * UINT8_MAX); - int omax = lrint(r->out_max * UINT8_MAX); - double coeff; - - if (imin < 0) { - imin = UINT8_MAX; - for (y = 0; y < inlink->h; y++) { - const uint8_t *src = srcrow; - - for (x = 0; x < s->linesize; x += step) - imin = FFMIN(imin, src[x + offset]); - srcrow += in->linesize[0]; - } - } - if (imax < 0) { - srcrow = in->data[0]; - imax = 0; - for (y = 0; y < inlink->h; y++) { - const uint8_t *src = srcrow; - - for (x = 0; x < s->linesize; x += step) - imax = FFMAX(imax, src[x + offset]); - srcrow += in->linesize[0]; - } - } - - srcrow = in->data[0]; - coeff = (omax - omin) / (double)(imax - imin); - for (y = 0; y < inlink->h; y++) { - const uint8_t *src = srcrow; - uint8_t *dst = dstrow; - - for (x = 0; x < s->linesize; x += step) - dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin); - dstrow += out->linesize[0]; - srcrow += in->linesize[0]; - } - } - break; - case 2: - for (i = 0; i < s->nb_comp; i++) { - Range *r = &s->range[i]; - const uint8_t offset = s->rgba_map[i]; - const uint8_t *srcrow = in->data[0]; - uint8_t *dstrow = out->data[0]; - int imin = lrint(r->in_min * UINT16_MAX); - int imax = lrint(r->in_max * UINT16_MAX); - int omin = lrint(r->out_min * UINT16_MAX); - int omax = lrint(r->out_max * UINT16_MAX); - double coeff; - - if (imin < 0) { - imin = UINT16_MAX; - for (y = 0; y < inlink->h; y++) { - const uint16_t *src = (const uint16_t *)srcrow; - - for (x = 0; x < s->linesize; x += step) - imin = FFMIN(imin, src[x + offset]); - srcrow += in->linesize[0]; - } - } - if (imax < 0) { - srcrow = in->data[0]; - imax = 0; - for (y = 0; y < inlink->h; y++) { - const uint16_t *src = (const uint16_t *)srcrow; - - for (x = 0; x < s->linesize; x += step) - imax = FFMAX(imax, src[x + offset]); - srcrow += in->linesize[0]; - } - } - - srcrow = in->data[0]; - coeff = (omax - omin) / (double)(imax - imin); - for (y = 0; y < inlink->h; y++) { - const uint16_t *src = (const uint16_t*)srcrow; - uint16_t *dst = (uint16_t *)dstrow; - - for (x = 0; x < s->linesize; x += step) - dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin); - dstrow += out->linesize[0]; - srcrow += in->linesize[0]; - } - } - } + td.in = in; + td.out = out; + ctx->internal->execute(ctx, s->colorlevels_slice, &td, NULL, + FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); if (in != out) av_frame_free(&in); @@ -252,5 +230,5 @@ AVFilter ff_vf_colorlevels = { .query_formats = query_formats, .inputs = colorlevels_inputs, .outputs = colorlevels_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, }; -- 2.21.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".