This patch adds slice threading support to the blackframe filter, improving performance on multi-core systems.
Changes in v5: - Removed meta-comments regarding C90 compliance as requested. - Removed redundant null checks for ThreadData pointers. - Renamed the thread results array to 'nb_black_pixels_per_slice' for clarity. Signed-off-by: Raja Rathour <[email protected]> --- libavfilter/vf_blackframe.c | 73 ++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index cb566d103d..fb531b8a4c 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -39,19 +39,20 @@ typedef struct BlackFrameContext { const AVClass *class; - int bamount; ///< black amount - int bthresh; ///< black threshold - unsigned int frame; ///< frame number - unsigned int nblack; ///< number of black pixels counted so far - unsigned int last_keyframe; ///< frame number of the last received key-frame + int bamount; + int bthresh; + unsigned int frame; + unsigned int nblack; + unsigned int last_keyframe; } BlackFrameContext; typedef struct ThreadData { - const uint8_t *data; // Pointer to the image data - int linesize; // How wide is the memory line - int bthresh; // The black threshold - int width; // Image width - unsigned int *counts; // POINTER to the array where threads write results + const uint8_t *data; + int linesize; + int bthresh; + int width; + int height; // Added height for cleaner slice math + unsigned int *counts; } ThreadData; static const enum AVPixelFormat pix_fmts[] = { @@ -67,25 +68,21 @@ static const enum AVPixelFormat pix_fmts[] = { static int blackframe_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ThreadData *td = arg; - // Calculate vertical slice - int slice_start = (ctx->inputs[0]->h * jobnr) / nb_jobs; - int slice_end = (ctx->inputs[0]->h * (jobnr+1)) / nb_jobs; - - // Safety check for pointers - if (!td || !td->data || !td->counts) return 0; - - const uint8_t *p = td->data + slice_start * td->linesize; - unsigned int local_nblack = 0; + int slice_start = (td->height * jobnr) / nb_jobs; + int slice_end = (td->height * (jobnr+1)) / nb_jobs; int x, y; + const uint8_t *p; + unsigned int black_pixels_count = 0; + + p = td->data + slice_start * td->linesize; for (y = slice_start; y < slice_end; y++) { for (x = 0; x < td->width; x++) - local_nblack += p[x] < td->bthresh; + black_pixels_count += p[x] < td->bthresh; p += td->linesize; } - // Save my private count - td->counts[jobnr] = local_nblack; + td->counts[jobnr] = black_pixels_count; return 0; } @@ -97,39 +94,31 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) AVDictionary **metadata; char buf[32]; ThreadData td; + int nb_threads, nb_jobs, i; + unsigned int *nb_black_pixels_per_slice; + + nb_threads = ff_filter_get_nb_threads(ctx); - // 1. Get thread count - int nb_threads = ff_filter_get_nb_threads(ctx); - - // Allocate memory for thread results - unsigned int *thread_counts = av_calloc(nb_threads, sizeof(*thread_counts)); - if (!thread_counts) { - av_log(ctx, AV_LOG_ERROR, "Failed to allocate thread_counts\n"); + nb_black_pixels_per_slice = av_calloc(nb_threads, sizeof(*nb_black_pixels_per_slice)); + if (!nb_black_pixels_per_slice) return AVERROR(ENOMEM); - } - // 3. Prepare the data package td.data = frame->data[0]; td.linesize = frame->linesize[0]; td.width = inlink->w; + td.height = inlink->h; td.bthresh = s->bthresh; - td.counts = thread_counts; + td.counts = nb_black_pixels_per_slice; - // 4. Run the threads! - // We calculate the exact number of jobs we are about to run - int nb_jobs = FFMIN(frame->height, nb_threads); + nb_jobs = FFMIN(td.height, nb_threads); ff_filter_execute(ctx, blackframe_slice, &td, NULL, nb_jobs); - // 5. THE REDUCE STEP: Sum up the results s->nblack = 0; - // Only sum up the jobs that actually ran - for (int i = 0; i < nb_jobs; i++) { - s->nblack += thread_counts[i]; + for (i = 0; i < nb_jobs; i++) { + s->nblack += nb_black_pixels_per_slice[i]; } - // --- FROM HERE DOWN, THE CODE IS THE SAME AS THE ORIGINAL --- - if (frame->flags & AV_FRAME_FLAG_KEY) s->last_keyframe = s->frame; @@ -149,7 +138,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->frame++; s->nblack = 0; - av_free(thread_counts); + av_free(nb_black_pixels_per_slice); return ff_filter_frame(inlink->dst->outputs[0], frame); } -- 2.48.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
