From: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[email protected]>
---
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
[email protected]
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
[email protected] with subject "unsubscribe".