[FFmpeg-devel] [PATCH v1 3/3] avfilter/colorlevels: add slice threading support with less code
Limin Wang
lance.lmwang at gmail.com
Fri Nov 8 12:29:56 EET 2019
ping.
On Wed, Oct 23, 2019 at 06:27:43PM +0800, lance.lmwang at gmail.com wrote:
> From: Limin Wang <lance.lmwang at gmail.com>
>
> Signed-off-by: Limin Wang <lance.lmwang at 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
>
More information about the ffmpeg-devel
mailing list