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:
parent
9d548fce24
commit
18b46ecc93
@ -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 */
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user