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: 2e1704059a by Kieran Kunhya

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2014-11-15 03:20:02 +01:00
parent 9d548fce24
commit 18b46ecc93
2 changed files with 30 additions and 15 deletions

View File

@ -51,6 +51,8 @@ typedef struct {
AVFrame *next; AVFrame *next;
uint8_t *black_data[4]; ///< buffer used to fill padded lines uint8_t *black_data[4]; ///< buffer used to fill padded lines
int black_linesize[4]; 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; } TInterlaceContext;
#endif /* AVFILTER_TINTERLACE_H */ #endif /* AVFILTER_TINTERLACE_H */

View File

@ -77,6 +77,18 @@ static int query_formats(AVFilterContext *ctx)
return 0; 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) static av_cold void uninit(AVFilterContext *ctx)
{ {
TInterlaceContext *tinterlace = ctx->priv; 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}); 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", av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n",
tinterlace->mode, (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "on" : "off", tinterlace->mode, (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "on" : "off",
inlink->h, outlink->h); inlink->h, outlink->h);
@ -152,7 +168,8 @@ static int config_out_props(AVFilterLink *outlink)
* @param flags context flags * @param flags context flags
*/ */
static inline 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], const uint8_t *src[4], int src_linesize[4],
enum AVPixelFormat format, int w, int src_h, enum AVPixelFormat format, int w, int src_h,
int src_field, int interleave, int dst_field, 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]; const uint8_t *srcp_below = srcp + src_linesize[plane];
if (h == lines) srcp_above = srcp; // there is no line above if (h == lines) srcp_above = srcp; // there is no line above
if (h == 1) srcp_below = srcp; // there is no line below if (h == 1) srcp_below = srcp; // there is no line below
for (i = 0; i < cols; i++) {
// this calculation is an integer representation of tinterlace->lowpass_line(dstp, cols, srcp, srcp_above, srcp_below);
// '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;
}
dstp += dstp_linesize; dstp += dstp_linesize;
srcp += srcp_linesize; srcp += srcp_linesize;
} }
@ -235,12 +248,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
out->top_field_first = 1; out->top_field_first = 1;
/* write odd frame lines into the upper field of the new frame */ /* 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, (const uint8_t **)cur->data, cur->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags); FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags);
/* write even frame lines into the lower field of the new frame */ /* 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, (const uint8_t **)next->data, next->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
FIELD_UPPER_AND_LOWER, 1, FIELD_LOWER, tinterlace->flags); 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; field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER;
/* copy upper and lower fields */ /* 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, (const uint8_t **)cur->data, cur->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags); FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags);
/* pad with black the other field */ /* 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, (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags); 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; out->top_field_first = tff;
/* copy upper/lower field from cur */ /* 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, (const uint8_t **)cur->data, cur->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
tinterlace->flags); tinterlace->flags);
/* copy lower/upper field from next */ /* 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, (const uint8_t **)next->data, next->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
@ -328,13 +341,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
else else
out->pts = AV_NOPTS_VALUE; out->pts = AV_NOPTS_VALUE;
/* write current frame second field lines into the second field of the new frame */ /* 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, (const uint8_t **)cur->data, cur->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
tinterlace->flags); tinterlace->flags);
/* write next frame first field lines into the first field of the new frame */ /* 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, (const uint8_t **)next->data, next->linesize,
inlink->format, inlink->w, inlink->h, inlink->format, inlink->w, inlink->h,
tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,