From 18b46ecc93bf07663431ae561118990b525bc103 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 15 Nov 2014 03:20:02 +0100 Subject: [PATCH] avfilter/tinterlace: Move lowpass_line to a separate function and call it through a function pointer This permits replacing it by a optimized implementation Based-on / Idea-from: 2e1704059ae8625beda2ffde847ad22c5ba416dc by Kieran Kunhya Signed-off-by: Michael Niedermayer --- libavfilter/tinterlace.h | 2 ++ libavfilter/vf_tinterlace.c | 43 ++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/libavfilter/tinterlace.h b/libavfilter/tinterlace.h index 8fc95cbc92..8d33452b0d 100644 --- a/libavfilter/tinterlace.h +++ b/libavfilter/tinterlace.h @@ -51,6 +51,8 @@ typedef struct { AVFrame *next; uint8_t *black_data[4]; ///< buffer used to fill padded lines int black_linesize[4]; + void (*lowpass_line)(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, + const uint8_t *srcp_above, const uint8_t *srcp_below); } TInterlaceContext; #endif /* AVFILTER_TINTERLACE_H */ diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index 6ef2a92c88..1d34d21436 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -77,6 +77,18 @@ static int query_formats(AVFilterContext *ctx) return 0; } +static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp, + const uint8_t *srcp_above, const uint8_t *srcp_below) +{ + int i; + for (i = 0; i < width; i++) { + // this calculation is an integer representation of + // '0.5 * current + 0.25 * above + 0.25 * below' + // '1 +' is for rounding. + dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2; + } +} + static av_cold void uninit(AVFilterContext *ctx) { TInterlaceContext *tinterlace = ctx->priv; @@ -131,6 +143,10 @@ static int config_out_props(AVFilterLink *outlink) outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2}); } + if (tinterlace->flags & TINTERLACE_FLAG_VLPF) { + tinterlace->lowpass_line = lowpass_line_c; + } + av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode, (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "on" : "off", inlink->h, outlink->h); @@ -152,7 +168,8 @@ static int config_out_props(AVFilterLink *outlink) * @param flags context flags */ static inline -void copy_picture_field(uint8_t *dst[4], int dst_linesize[4], +void copy_picture_field(TInterlaceContext *tinterlace, + uint8_t *dst[4], int dst_linesize[4], const uint8_t *src[4], int src_linesize[4], enum AVPixelFormat format, int w, int src_h, int src_field, int interleave, int dst_field, @@ -189,12 +206,8 @@ void copy_picture_field(uint8_t *dst[4], int dst_linesize[4], const uint8_t *srcp_below = srcp + src_linesize[plane]; if (h == lines) srcp_above = srcp; // there is no line above if (h == 1) srcp_below = srcp; // there is no line below - for (i = 0; i < cols; i++) { - // this calculation is an integer representation of - // '0.5 * current + 0.25 * above + 0.25 * below' - // '1 +' is for rounding. */ - dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2; - } + + tinterlace->lowpass_line(dstp, cols, srcp, srcp_above, srcp_below); dstp += dstp_linesize; srcp += srcp_linesize; } @@ -235,12 +248,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) out->top_field_first = 1; /* write odd frame lines into the upper field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags); /* write even frame lines into the lower field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, FIELD_LOWER, tinterlace->flags); @@ -265,12 +278,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER; /* copy upper and lower fields */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags); /* pad with black the other field */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags); @@ -289,13 +302,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) out->top_field_first = tff; /* copy upper/lower field from cur */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, tinterlace->flags); /* copy lower/upper field from next */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, @@ -328,13 +341,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) else out->pts = AV_NOPTS_VALUE; /* write current frame second field lines into the second field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, tinterlace->flags); /* write next frame first field lines into the first field of the new frame */ - copy_picture_field(out->data, out->linesize, + copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,