[FFmpeg-cvslog] avfilter/vf_colorlevels: call execute once per frame
Paul B Mahol
git at videolan.org
Tue Feb 2 18:55:27 EET 2021
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Tue Feb 2 16:44:29 2021 +0100| [68b5236eaea24da7bcbabd7daf25d6148429e43e] | committer: Paul B Mahol
avfilter/vf_colorlevels: call execute once per frame
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=68b5236eaea24da7bcbabd7daf25d6148429e43e
---
libavfilter/vf_colorlevels.c | 163 +++++++++++++++++++++----------------------
1 file changed, 81 insertions(+), 82 deletions(-)
diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c
index f1eeb68c54..9085e40974 100644
--- a/libavfilter/vf_colorlevels.c
+++ b/libavfilter/vf_colorlevels.c
@@ -40,11 +40,14 @@ typedef struct Range {
typedef struct ColorLevelsContext {
const AVClass *class;
Range range[4];
+
int nb_comp;
int bpp;
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,91 +93,101 @@ static int query_formats(AVFilterContext *ctx)
return ff_set_common_formats(ctx, fmts_list);
}
-static int config_input(AVFilterLink *inlink)
-{
- AVFilterContext *ctx = inlink->dst;
- ColorLevelsContext *s = ctx->priv;
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
-
- s->nb_comp = desc->nb_components;
- s->bpp = desc->comp[0].depth >> 3;
- s->step = (av_get_padded_bits_per_pixel(desc) >> 3) / s->bpp;
- s->linesize = inlink->w * s->step;
- ff_fill_rgba_map(s->rgba_map, inlink->format);
-
- return 0;
-}
-
typedef struct ThreadData {
const uint8_t *srcrow;
uint8_t *dstrow;
int dst_linesize;
int src_linesize;
- float coeff;
- uint8_t offset;
+ float coeff[4];
int h;
- int imin;
- int omin;
+ int imin[4];
+ int omin[4];
} ThreadData;
#define LOAD_COMMON \
ColorLevelsContext *s = ctx->priv; \
const ThreadData *td = arg; \
- \
- int process_h = td->h; \
+ const int process_h = td->h; \
const int slice_start = (process_h * jobnr ) / nb_jobs; \
const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \
- int x, y; \
const uint8_t *srcrow = td->srcrow; \
uint8_t *dstrow = td->dstrow; \
- const int step = s->step; \
- const uint8_t offset = td->offset; \
- \
- int imin = td->imin; \
- int omin = td->omin; \
- float coeff = td->coeff;
-
-static int colorlevel_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+ const int step = s->step;
+
+static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
LOAD_COMMON
- for (y = slice_start; y < slice_end; y++) {
- const uint8_t *src = srcrow + y * td->src_linesize;
- uint8_t *dst = dstrow + y * td->dst_linesize;
+ for (int comp = 0; comp < s->nb_comp; comp++) {
+ const uint8_t offset = s->rgba_map[comp];
+ const int imin = td->imin[comp];
+ const int omin = td->omin[comp];
+ const float coeff = td->coeff[comp];
- for (x = 0; x < s->linesize; x += step)
- dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin);
+ for (int y = slice_start; y < slice_end; y++) {
+ const uint8_t *src = srcrow + y * td->src_linesize;
+ uint8_t *dst = dstrow + y * td->dst_linesize;
+
+ for (int x = 0; x < s->linesize; x += step)
+ dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin);
+ }
}
return 0;
}
-static int colorlevel_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
LOAD_COMMON
- for (y = slice_start; y < slice_end; y++) {
- const uint16_t *src = (const uint16_t *)(srcrow + y * td->src_linesize);
- uint16_t *dst = (uint16_t *)(dstrow + y * td->dst_linesize);
+ for (int comp = 0; comp < s->nb_comp; comp++) {
+ const uint8_t offset = s->rgba_map[comp];
+ const int imin = td->imin[comp];
+ const int omin = td->omin[comp];
+ const float coeff = td->coeff[comp];
- for (x = 0; x < s->linesize; x += step)
- dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin);
+ for (int y = slice_start; y < slice_end; y++) {
+ const uint16_t *src = (const uint16_t *)(srcrow + y * td->src_linesize);
+ uint16_t *dst = (uint16_t *)(dstrow + y * td->dst_linesize);
+
+ for (int x = 0; x < s->linesize; x += step)
+ dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin);
+ }
}
return 0;
}
+static int config_input(AVFilterLink *inlink)
+{
+ AVFilterContext *ctx = inlink->dst;
+ ColorLevelsContext *s = ctx->priv;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+
+ s->nb_comp = desc->nb_components;
+ s->bpp = desc->comp[0].depth >> 3;
+ s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2));
+ s->linesize = inlink->w * s->step;
+ ff_fill_rgba_map(s->rgba_map, inlink->format);
+
+ s->colorlevels_slice = colorlevels_slice_8;
+ if (s->bpp == 2)
+ s->colorlevels_slice = colorlevels_slice_16;
+
+ 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;
+ ThreadData td;
AVFrame *out;
- int x, y, i;
if (av_frame_is_writable(in)) {
out = in;
@@ -187,26 +200,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
av_frame_copy_props(out, in);
}
+ td.h = inlink->h;
+ td.dst_linesize = out->linesize[0];
+ td.src_linesize = in->linesize[0];
+ td.srcrow = in->data[0];
+ td.dstrow = out->data[0];
+
switch (s->bpp) {
case 1:
- for (i = 0; i < s->nb_comp; i++) {
+ for (int 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);
float coeff;
- ThreadData td;
if (imin < 0) {
imin = UINT8_MAX;
- for (y = 0; y < inlink->h; y++) {
+ for (int y = 0; y < inlink->h; y++) {
const uint8_t *src = srcrow;
- for (x = 0; x < s->linesize; x += step)
+ for (int x = 0; x < s->linesize; x += step)
imin = FFMIN(imin, src[x + offset]);
srcrow += in->linesize[0];
}
@@ -214,51 +231,39 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
if (imax < 0) {
srcrow = in->data[0];
imax = 0;
- for (y = 0; y < inlink->h; y++) {
+ for (int y = 0; y < inlink->h; y++) {
const uint8_t *src = srcrow;
- for (x = 0; x < s->linesize; x += step)
+ for (int 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);
- td.srcrow = srcrow;
- td.dstrow = dstrow;
- td.dst_linesize = out->linesize[0];
- td.src_linesize = in->linesize[0];
- td.coeff = coeff;
- td.offset = offset;
- td.h = inlink->h;
- td.imin = imin;
- td.omin = omin;
-
- ctx->internal->execute(ctx, colorlevel_slice_8, &td, NULL,
- FFMIN(inlink->h, ff_filter_get_nb_threads(ctx)));
+ td.coeff[i] = coeff;
+ td.imin[i] = imin;
+ td.omin[i] = omin;
}
break;
case 2:
- for (i = 0; i < s->nb_comp; i++) {
+ for (int 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);
float coeff;
- ThreadData td;
if (imin < 0) {
imin = UINT16_MAX;
- for (y = 0; y < inlink->h; y++) {
+ for (int y = 0; y < inlink->h; y++) {
const uint16_t *src = (const uint16_t *)srcrow;
- for (x = 0; x < s->linesize; x += step)
+ for (int x = 0; x < s->linesize; x += step)
imin = FFMIN(imin, src[x + offset]);
srcrow += in->linesize[0];
}
@@ -266,33 +271,27 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
if (imax < 0) {
srcrow = in->data[0];
imax = 0;
- for (y = 0; y < inlink->h; y++) {
+ for (int y = 0; y < inlink->h; y++) {
const uint16_t *src = (const uint16_t *)srcrow;
- for (x = 0; x < s->linesize; x += step)
+ for (int 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);
- td.srcrow = srcrow;
- td.dstrow = dstrow;
- td.dst_linesize = out->linesize[0];
- td.src_linesize = in->linesize[0];
- td.coeff = coeff;
- td.offset = offset;
- td.h = inlink->h;
- td.imin = imin;
- td.omin = omin;
-
- ctx->internal->execute(ctx, colorlevel_slice_16, &td, NULL,
- FFMIN(inlink->h, ff_filter_get_nb_threads(ctx)));
+ td.coeff[i] = coeff;
+ td.imin[i] = imin;
+ td.omin[i] = omin;
}
+ break;
}
+ 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);
return ff_filter_frame(outlink, out);
More information about the ffmpeg-cvslog
mailing list