diff options
author | Rudolf Polzer <divverent@alientrap.org> | 2011-04-23 18:56:47 +0200 |
---|---|---|
committer | Uoti Urpala <uau@mplayer2.org> | 2011-04-24 03:55:47 +0300 |
commit | 994b21a80a2f37b0d672526739cb742b87f33ad9 (patch) | |
tree | 222e014be69723c4772d5045fee35eb98ffc8a63 /libmpcodecs/vf.c | |
parent | 28b3cc0efe7a575cb8004d1b109ce5ca2f2953bb (diff) | |
download | mpv-994b21a80a2f37b0d672526739cb742b87f33ad9.tar.bz2 mpv-994b21a80a2f37b0d672526739cb742b87f33ad9.tar.xz |
vf_*: fix pts values passed to the next filter
Many video filters failed to calculate or even just pass through pts
values for their output frames. Fix this, and also make the two
remaining filters that called vf_next_put_image() twice for the same
input frame (vf_softpulldown, vf_telecine) use vf_queue_frame() so
that e.g. framestepping properly sees both frames.
Changed filters: vf_bmovl, vf_detc, vf_divtc, vf_filmdint, vf_ivtc,
vf_lavc, vf_phase, vf_pullup, vf_softpulldown, vf_telecine, vf_tile,
vf_tinterlace.
Diffstat (limited to 'libmpcodecs/vf.c')
-rw-r--r-- | libmpcodecs/vf.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index 6355076726..eefdaa3c46 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -751,3 +751,87 @@ void vf_uninit_filter_chain(vf_instance_t* vf){ vf=next; } } + +void vf_detc_init_pts_buf(struct vf_detc_pts_buf *p) +{ + p->inpts_prev = MP_NOPTS_VALUE; + p->outpts_prev = MP_NOPTS_VALUE; + p->lastdelta = 0; +} + +static double vf_detc_adjust_pts_internal(struct vf_detc_pts_buf *p, + double pts, bool reset_pattern, + bool skip_frame, double delta, + double boundfactor_minus, + double increasefactor, + double boundfactor_plus) +{ + double newpts; + + if (pts == MP_NOPTS_VALUE) + return pts; + + if (delta <= 0) { + if (p->inpts_prev == MP_NOPTS_VALUE) + delta = 0; + else if(pts == p->inpts_prev) + delta = p->lastdelta; + else + delta = pts - p->inpts_prev; + } + //mp_msg(MSGT_VFILTER, MSGL_INFO, "filmdint: (1) inpts %f (delta: %f, increase: %f)\n", pts, delta, delta * increasefactor); + p->inpts_prev = pts; + p->lastdelta = delta; + + if (skip_frame) + return MP_NOPTS_VALUE; + + // detect bogus deltas and then passthru pts (possibly caused by seeking, or bad input) + if (p->outpts_prev == MP_NOPTS_VALUE || reset_pattern || delta <= 0.0 || delta >= 0.5) { + newpts = pts; + } else { + // turn 5 frames into 4 + newpts = p->outpts_prev + delta * increasefactor; + + // bound to input pts in a sensible way; these numbers come because we + // map frames the following way when ivtc'ing: + // 0/30 -> 0/24 diff=0 + // 1/30 -> 1/24 diff=1/120 + // 2/30 -> - + // 3/30 -> 2/24 diff=-1/60 + // 4/30 -> 3/24 diff=-1/120 + if (newpts < pts - delta * boundfactor_minus) + newpts = pts - delta * boundfactor_minus; + if (newpts > pts + delta * boundfactor_plus) + newpts = pts + delta * boundfactor_plus; + if (newpts < p->outpts_prev) + newpts = p->outpts_prev; // damage control + } + //mp_msg(MSGT_VFILTER, MSGL_INFO, "filmdint: (2) outpts %f (delta: %f)\n", newpts, newpts - p->outpts_prev); + p->outpts_prev = newpts; + + return newpts; +} + +double vf_detc_adjust_pts(struct vf_detc_pts_buf *p, double pts, + bool reset_pattern, bool skip_frame) +{ + // standard telecine (see above) + return vf_detc_adjust_pts_internal(p, pts, reset_pattern, skip_frame, + 0, 0.5, 1.25, 0.25); +} + +double vf_softpulldown_adjust_pts(struct vf_detc_pts_buf *p, double pts, + bool reset_pattern, bool skip_frame, + int last_frame_duration) +{ + // for the softpulldown filter we get: + // 0/60 -> 0/30 + // 2/60 -> 1/30 + // 5/60 -> 2/30 + // 7/60 -> 3/30, 4/30 + return vf_detc_adjust_pts_internal(p, pts, reset_pattern, skip_frame, + 0, 1.0 / last_frame_duration, + 2.0 / last_frame_duration, + 1.0 / last_frame_duration); +} |