summaryrefslogtreecommitdiffstats
path: root/libmpcodecs/vf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmpcodecs/vf.c')
-rw-r--r--libmpcodecs/vf.c84
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);
+}