summaryrefslogtreecommitdiff
path: root/libavfilter/vf_blackdetect.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2021-01-30 16:04:28 +0100
committerPaul B Mahol <onemda@gmail.com>2021-01-30 16:08:26 +0100
commit0959f95a8ea03e1fba94f19395fd9e525bada113 (patch)
treee1235e532c97550dc5c7388d0c982511a66935a3 /libavfilter/vf_blackdetect.c
parent44e27d937d88f3e7cdc83f4de1b9d3a590bcaa04 (diff)
avfilter/vf_blackdetect: add slice threading support
Diffstat (limited to 'libavfilter/vf_blackdetect.c')
-rw-r--r--libavfilter/vf_blackdetect.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c
index 5caf99af5c..565a7545e0 100644
--- a/libavfilter/vf_blackdetect.c
+++ b/libavfilter/vf_blackdetect.c
@@ -47,6 +47,8 @@ typedef struct BlackDetectContext {
unsigned int nb_black_pixels; ///< number of black pixels counted so far
AVRational time_base;
int depth;
+ int nb_threads;
+ unsigned int *counter;
} BlackDetectContext;
#define OFFSET(x) offsetof(BlackDetectContext, x)
@@ -112,8 +114,12 @@ static int config_input(AVFilterLink *inlink)
const int factor = (1 << (depth - 8));
s->depth = depth;
+ s->nb_threads = ff_filter_get_nb_threads(ctx);
s->time_base = inlink->time_base;
s->black_min_duration = s->black_min_duration_time / av_q2d(s->time_base);
+ s->counter = av_calloc(s->nb_threads, sizeof(*s->counter));
+ if (!s->counter)
+ return AVERROR(ENOMEM);
s->pixel_black_th_i = ff_fmt_is_in(inlink->format, yuvj_formats) ?
// luminance_minimum_value + pixel_black_th * luminance_range_size
@@ -141,30 +147,56 @@ static void check_black_end(AVFilterContext *ctx)
}
}
-static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
+static int black_counter(AVFilterContext *ctx, void *arg,
+ int jobnr, int nb_jobs)
{
- AVFilterContext *ctx = inlink->dst;
BlackDetectContext *s = ctx->priv;
- double picture_black_ratio = 0;
+ const unsigned int threshold = s->pixel_black_th_i;
+ unsigned int *counterp = &s->counter[jobnr];
+ AVFrame *in = arg;
+ const int linesize = in->linesize[0];
+ const int w = in->width;
+ const int h = in->height;
+ const int start = (h * jobnr) / nb_jobs;
+ const int end = (h * (jobnr+1)) / nb_jobs;
+ const int size = end - start;
+ unsigned int counter = 0;
if (s->depth == 8) {
- const uint8_t *p = picref->data[0];
+ const uint8_t *p = in->data[0] + start * linesize;
- for (int i = 0; i < inlink->h; i++) {
- for (int x = 0; x < inlink->w; x++)
- s->nb_black_pixels += p[x] <= s->pixel_black_th_i;
- p += picref->linesize[0];
+ for (int i = 0; i < size; i++) {
+ for (int x = 0; x < w; x++)
+ counter += p[x] <= threshold;
+ p += linesize;
}
} else {
- const uint16_t *p = (const uint16_t *)picref->data[0];
+ const uint16_t *p = (const uint16_t *)(in->data[0] + start * linesize);
- for (int i = 0; i < inlink->h; i++) {
- for (int x = 0; x < inlink->w; x++)
- s->nb_black_pixels += p[x] <= s->pixel_black_th_i;
- p += picref->linesize[0] / 2;
+ for (int i = 0; i < size; i++) {
+ for (int x = 0; x < w; x++)
+ counter += p[x] <= threshold;
+ p += linesize / 2;
}
}
+ *counterp = counter;
+
+ return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
+{
+ AVFilterContext *ctx = inlink->dst;
+ BlackDetectContext *s = ctx->priv;
+ double picture_black_ratio = 0;
+
+ ctx->internal->execute(ctx, black_counter, picref, NULL,
+ FFMIN(inlink->h, s->nb_threads));
+
+ for (int i = 0; i < s->nb_threads; i++)
+ s->nb_black_pixels += s->counter[i];
+
picture_black_ratio = (double)s->nb_black_pixels / (inlink->w * inlink->h);
av_log(ctx, AV_LOG_DEBUG,
@@ -199,6 +231,8 @@ static av_cold void uninit(AVFilterContext *ctx)
{
BlackDetectContext *s = ctx->priv;
+ av_freep(&s->counter);
+
if (s->black_started) {
// FIXME: black_end should be set to last_picref_pts + last_picref_duration
s->black_end = s->last_picref_pts;
@@ -233,4 +267,5 @@ AVFilter ff_vf_blackdetect = {
.outputs = blackdetect_outputs,
.uninit = uninit,
.priv_class = &blackdetect_class,
+ .flags = AVFILTER_FLAG_SLICE_THREADS,
};