ping. On Wed, Oct 23, 2019 at 06:27:43PM +0800, lance.lmw...@gmail.com wrote: > 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".