X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_limiter.c;h=bb7f1d37cddd8b534353773e9ace47de9290e844;hb=7ca2ee059e3d3e170a8e119af10649671c524112;hp=9c62b1188492331e3e86a9a64c3d7eab4a23dcb7;hpb=cbd5e737fee5e64109fffbc5c2dc05024a06c2c6;p=ffmpeg diff --git a/libavfilter/vf_limiter.c b/libavfilter/vf_limiter.c index 9c62b118849..bb7f1d37cdd 100644 --- a/libavfilter/vf_limiter.c +++ b/libavfilter/vf_limiter.c @@ -28,6 +28,11 @@ #include "limiter.h" #include "video.h" +typedef struct ThreadData { + AVFrame *in; + AVFrame *out; +} ThreadData; + typedef struct LimiterContext { const AVClass *class; int min; @@ -81,7 +86,7 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, - AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE }; @@ -161,13 +166,46 @@ static int config_props(AVFilterLink *inlink) return 0; } +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + LimiterContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + int p; + + for (p = 0; p < s->nb_planes; p++) { + const int h = s->height[p]; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + + if (!((1 << p) & s->planes)) { + if (out != in) + av_image_copy_plane(out->data[p] + slice_start * out->linesize[p], + out->linesize[p], + in->data[p] + slice_start * in->linesize[p], + in->linesize[p], + s->linesize[p], slice_end - slice_start); + continue; + } + + s->dsp.limiter(in->data[p] + slice_start * in->linesize[p], + out->data[p] + slice_start * out->linesize[p], + in->linesize[p], out->linesize[p], + s->width[p], slice_end - slice_start, + s->min, s->max); + } + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; LimiterContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; - int p; if (av_frame_is_writable(in)) { out = in; @@ -180,20 +218,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - for (p = 0; p < s->nb_planes; p++) { - if (!((1 << p) & s->planes)) { - if (out != in) - av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], - s->linesize[p], s->height[p]); - continue; - } - - s->dsp.limiter(in->data[p], out->data[p], - in->linesize[p], out->linesize[p], - s->width[p], s->height[p], - s->min, s->max); - } - + td.out = out; + td.in = in; + ctx->internal->execute(ctx, filter_slice, &td, NULL, + FFMIN(s->height[2], ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); @@ -227,5 +255,5 @@ AVFilter ff_vf_limiter = { .query_formats = query_formats, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, };