From 0d5ae023b2b7b860cbbfb7763f94da76bc841788 Mon Sep 17 00:00:00 2001 From: Jasper Taylor Date: Sun, 16 Mar 2014 15:29:30 +0000 Subject: [PATCH] avfilter/vf_tinterlace: Fix vf_tinterlace mode 6 (interlacex2) The purpose of this filter mode is to allow interlaced content to display properly in interlaced video modes, as described in http://forum.xbmc.org/showthread.php?tid=81834 and https://github.com/mpv-player/mpv/issues/624#issuecomment-37685195 . The filter doubles the video frame rate, but does not work properly because: (1) it does not set the properties of the output stream to indicate the doubled frame rate, and (2) it does not set an appropriate PTS on the extra frames. The attached patch fixes these problems by settling these values the same way they are set in vf_yadif mode 1 (field) which also doubles the frame rate. Signed-off-by: Michael Niedermayer --- libavfilter/vf_tinterlace.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index db82393117..3ebb971646 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -145,6 +145,12 @@ static int config_out_props(AVFilterLink *outlink) tinterlace->mode); tinterlace->flags &= ~TINTERLACE_FLAG_VLPF; } + if (tinterlace->mode == MODE_INTERLACEX2) { + outlink->time_base.num = inlink->time_base.num; + outlink->time_base.den = inlink->time_base.den * 2; + outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1}); + } + 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); @@ -321,6 +327,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) if (!out) return AVERROR(ENOMEM); out->interlaced_frame = 1; + if (cur->pts != AV_NOPTS_VALUE) + out->pts = cur->pts*2; if ((ret = ff_filter_frame(outlink, out)) < 0) return ret; @@ -333,6 +341,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) av_frame_copy_props(out, next); out->interlaced_frame = 1; + if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE) + out->pts = cur->pts + next->pts; + 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, (const uint8_t **)cur->data, cur->linesize,