---
Turning off the lowpass filter while interlacing is a terrible idea
as it can easily gernerate terrible results; the effect would be
similar to decimating vertically by dropping the odd lines.
So I propose to remove this option from the filter and keep the lowpass
filter always applied, like by default.
I'm not sure if/which version bump should be made or if I have to wrap
the code-to-be-removed in FF_API_ clauses.
Cheers,
Vittorio
doc/filters.texi | 7 ++----
libavfilter/vf_interlace.c | 57 +++++++++++++++++++++++-----------------------
2 files changed, 30 insertions(+), 34 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 8c83b4e..51f208a 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1426,7 +1426,8 @@ a float number which specifies chroma temporal strength,
defaults to
Simple interlacing filter from progressive contents. This interleaves upper (or
lower) lines from odd frames with lower (or upper) lines from even frames,
-halving the frame rate and preserving image height.
+halving the frame rate and preserving image height. A vertical lowpass filter
+is always applied in order to avoid twitter effect and reduce moire patterns.
@example
Original Original New Frame
@@ -1446,10 +1447,6 @@ It accepts the following optional parameters:
@item scan
determines whether the interlaced frame is taken from the even (tff - default)
or odd (bff) lines of the progressive frame.
-
-@item lowpass
-Enable (default) or disable the vertical lowpass filter to avoid twitter
-interlacing and reduce moire patterns.
@end table
@section lut, lutrgb, lutyuv
diff --git a/libavfilter/vf_interlace.c b/libavfilter/vf_interlace.c
index a05ab03..51aded5 100644
--- a/libavfilter/vf_interlace.c
+++ b/libavfilter/vf_interlace.c
@@ -58,7 +58,7 @@ static const AVOption options[] = {
AV_OPT_TYPE_CONST, {.i64 = MODE_TFF }, INT_MIN, INT_MAX, .flags = V,
.unit = "scan" },
{ "bff", "bottom field first", 0,
AV_OPT_TYPE_CONST, {.i64 = MODE_BFF }, INT_MIN, INT_MAX, .flags = V,
.unit = "scan" },
- { "lowpass", "enable vertical low-pass filter", OFFSET(lowpass),
+ { "lowpass", "(deprecated, the filter is always set)", OFFSET(lowpass),
AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 1, .flags = V },
{ NULL }
};
@@ -100,6 +100,9 @@ static int config_out_props(AVFilterLink *outlink)
AVFilterLink *inlink = outlink->src->inputs[0];
InterlaceContext *s = ctx->priv;
+ if (!s->lowpass)
+ av_log(ctx, AV_LOG_WARNING, "this is not the lowpass you were looking
for\n");
+
if (inlink->h < 2) {
av_log(ctx, AV_LOG_ERROR, "input video height is too small\n");
return AVERROR_INVALIDDATA;
@@ -111,15 +114,14 @@ static int config_out_props(AVFilterLink *outlink)
// half framerate
outlink->time_base.num *= 2;
- av_log(ctx, AV_LOG_VERBOSE, "%s interlacing %s lowpass filter\n",
- s->scan == MODE_TFF ? "tff" : "bff", (s->lowpass) ? "with" :
"without");
+ av_log(ctx, AV_LOG_VERBOSE, "%s interlacing\n",
+ s->scan == MODE_TFF ? "tff" : "bff");
return 0;
}
static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame,
- AVFilterLink *inlink, enum FieldType field_type,
- int lowpass)
+ AVFilterLink *inlink, enum FieldType field_type)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
int vsub = desc->log2_chroma_h;
@@ -130,6 +132,8 @@ static void copy_picture_field(AVFrame *src_frame, AVFrame
*dst_frame,
int linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
uint8_t *dstp = dst_frame->data[plane];
const uint8_t *srcp = src_frame->data[plane];
+ int srcp_linesize;
+ int dstp_linesize;
av_assert0(linesize >= 0);
@@ -138,29 +142,24 @@ static void copy_picture_field(AVFrame *src_frame,
AVFrame *dst_frame,
srcp += src_frame->linesize[plane];
if (field_type == FIELD_LOWER)
dstp += dst_frame->linesize[plane];
- if (lowpass) {
- int srcp_linesize = src_frame->linesize[plane] * 2;
- int dstp_linesize = dst_frame->linesize[plane] * 2;
- for (j = lines; j > 0; j--) {
- const uint8_t *srcp_above = srcp - src_frame->linesize[plane];
- const uint8_t *srcp_below = srcp + src_frame->linesize[plane];
- if (j == lines)
- srcp_above = srcp; // there is no line above
- if (j == 1)
- srcp_below = srcp; // there is no line below
- for (i = 0; i < linesize; 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;
- }
- dstp += dstp_linesize;
- srcp += srcp_linesize;
+
+ srcp_linesize = src_frame->linesize[plane] * 2;
+ dstp_linesize = dst_frame->linesize[plane] * 2;
+ for (j = lines; j > 0; j--) {
+ const uint8_t *srcp_above = srcp - src_frame->linesize[plane];
+ const uint8_t *srcp_below = srcp + src_frame->linesize[plane];
+ if (j == lines)
+ srcp_above = srcp; // there is no line above
+ if (j == 1)
+ srcp_below = srcp; // there is no line below
+ for (i = 0; i < linesize; 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;
}
- } else {
- av_image_copy_plane(dstp, dst_frame->linesize[plane] * 2,
- srcp, src_frame->linesize[plane] * 2,
- linesize, lines);
+ dstp += dstp_linesize;
+ srcp += srcp_linesize;
}
}
}
@@ -204,11 +203,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
*buf)
out->pts /= 2; // adjust pts to new framerate
/* copy upper/lower field from cur */
- copy_picture_field(s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER,
s->lowpass);
+ copy_picture_field(s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER);
av_frame_free(&s->cur);
/* copy lower/upper field from next */
- copy_picture_field(s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER,
s->lowpass);
+ copy_picture_field(s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER);
av_frame_free(&s->next);
ret = ff_filter_frame(outlink, out);
--
1.8.4
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel