diff options
-rw-r--r-- | libmpcodecs/pullup.c | 12 | ||||
-rw-r--r-- | libmpcodecs/pullup.h | 5 | ||||
-rw-r--r-- | libmpcodecs/vf.c | 84 | ||||
-rw-r--r-- | libmpcodecs/vf.h | 16 | ||||
-rw-r--r-- | libmpcodecs/vf_bmovl.c | 12 | ||||
-rw-r--r-- | libmpcodecs/vf_detc.c | 13 | ||||
-rw-r--r-- | libmpcodecs/vf_divtc.c | 7 | ||||
-rw-r--r-- | libmpcodecs/vf_filmdint.c | 5 | ||||
-rw-r--r-- | libmpcodecs/vf_ivtc.c | 15 | ||||
-rw-r--r-- | libmpcodecs/vf_lavc.c | 3 | ||||
-rw-r--r-- | libmpcodecs/vf_phase.c | 2 | ||||
-rw-r--r-- | libmpcodecs/vf_pullup.c | 38 | ||||
-rw-r--r-- | libmpcodecs/vf_softpulldown.c | 31 | ||||
-rw-r--r-- | libmpcodecs/vf_telecine.c | 67 | ||||
-rw-r--r-- | libmpcodecs/vf_tile.c | 5 | ||||
-rw-r--r-- | libmpcodecs/vf_tinterlace.c | 10 |
16 files changed, 269 insertions, 56 deletions
diff --git a/libmpcodecs/pullup.c b/libmpcodecs/pullup.c index 2675be6146..b70aa9b56f 100644 --- a/libmpcodecs/pullup.c +++ b/libmpcodecs/pullup.c @@ -22,6 +22,7 @@ #include "config.h" #include "pullup.h" #include "cpudetect.h" +#include "mpcommon.h" @@ -412,7 +413,8 @@ static void check_field_queue(struct pullup_context *c) } } -void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity) +void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, + int parity, double pts) { struct pullup_field *f; @@ -428,6 +430,7 @@ void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int f->flags = 0; f->breaks = 0; f->affinity = 0; + f->pts = pts; compute_metric(c, f, parity, f->prev->prev, parity, c->diff, f->diffs); compute_metric(c, parity?f->prev:f, 0, parity?f:f->prev, 1, c->comb, f->comb); @@ -663,12 +666,19 @@ struct pullup_frame *pullup_get_frame(struct pullup_context *c) fr->length = n; fr->parity = c->first->parity; fr->buffer = 0; + fr->pts = 0; for (i = 0; i < n; i++) { /* We cheat and steal the buffer without release+relock */ fr->ifields[i] = c->first->buffer; c->first->buffer = 0; + if (c->first->pts == MP_NOPTS_VALUE || fr->pts == MP_NOPTS_VALUE) + fr->pts = MP_NOPTS_VALUE; + else + fr->pts += c->first->pts; c->first = c->first->next; } + if (fr->pts != MP_NOPTS_VALUE) + fr->pts /= n; if (n == 1) { fr->ofields[fr->parity] = fr->ifields[0]; diff --git a/libmpcodecs/pullup.h b/libmpcodecs/pullup.h index eb7b143da6..0db8f6f894 100644 --- a/libmpcodecs/pullup.h +++ b/libmpcodecs/pullup.h @@ -40,6 +40,7 @@ struct pullup_buffer struct pullup_field { int parity; + double pts; struct pullup_buffer *buffer; unsigned int flags; int breaks; @@ -55,6 +56,7 @@ struct pullup_frame int lock; int length; int parity; + double pts; struct pullup_buffer **ifields, *ofields[2]; struct pullup_buffer *buffer; }; @@ -87,7 +89,8 @@ struct pullup_buffer *pullup_lock_buffer(struct pullup_buffer *b, int parity); void pullup_release_buffer(struct pullup_buffer *b, int parity); struct pullup_buffer *pullup_get_buffer(struct pullup_context *c, int parity); -void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, int parity); +void pullup_submit_field(struct pullup_context *c, struct pullup_buffer *b, + int parity, double pts); void pullup_flush_fields(struct pullup_context *c); struct pullup_frame *pullup_get_frame(struct pullup_context *c); 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); +} diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h index 58cfaaf787..ec1a9c23ff 100644 --- a/libmpcodecs/vf.h +++ b/libmpcodecs/vf.h @@ -21,6 +21,7 @@ #include "mp_image.h" #include "mpcommon.h" +#include "stdbool.h" struct MPOpts; struct vf_instance; @@ -169,4 +170,19 @@ static inline int norm_qscale(int qscale, int type) return qscale; } +struct vf_detc_pts_buf { + double inpts_prev, outpts_prev; + double lastdelta; +}; +void vf_detc_init_pts_buf(struct vf_detc_pts_buf *p); +/* Adjust pts when detelecining. + * skip_frame: do not render this frame + * reset_pattern: set to 1 if the telecine pattern has reset due to scene cut + */ +double vf_detc_adjust_pts(struct vf_detc_pts_buf *p, double pts, + bool reset_pattern, bool skip_frame); +double vf_softpulldown_adjust_pts(struct vf_detc_pts_buf *p, double pts, + bool reset_pattern, bool skip_frame, + int last_frame_duration); + #endif /* MPLAYER_VF_H */ diff --git a/libmpcodecs/vf_bmovl.c b/libmpcodecs/vf_bmovl.c index 3b46e1ebcc..b6b9940832 100644 --- a/libmpcodecs/vf_bmovl.c +++ b/libmpcodecs/vf_bmovl.c @@ -261,10 +261,10 @@ put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){ else if( strncmp(cmd,"OPAQUE",6)==0 ) vf->priv->opaque=TRUE; else if( strncmp(cmd,"SHOW", 4)==0 ) vf->priv->hidden=FALSE; else if( strncmp(cmd,"HIDE", 4)==0 ) vf->priv->hidden=TRUE; - else if( strncmp(cmd,"FLUSH" ,5)==0 ) return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + else if( strncmp(cmd,"FLUSH" ,5)==0 ) return vf_next_put_image(vf, dmpi, pts); else { mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: Unknown command: '%s'. Ignoring.\n", cmd); - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, pts); } if(command == CMD_ALPHA) { @@ -283,7 +283,7 @@ put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){ buffer = malloc(imgw*imgh*pxsz); if(!buffer) { mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: Couldn't allocate temporary buffer! Skipping...\n\n"); - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, pts); } /* pipes/sockets might need multiple calls to read(): */ want = (imgw*imgh*pxsz); @@ -344,7 +344,7 @@ put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){ if( (imgx <= vf->priv->x2) && ( (imgx+imgw) >= vf->priv->x2) ) vf->priv->x2 = imgx; } - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, pts); } for( buf_y=0 ; (buf_y < imgh) && (buf_y < (vf->priv->h-imgy)) ; buf_y++ ) { @@ -402,7 +402,7 @@ put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){ } } - if(vf->priv->hidden) return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + if(vf->priv->hidden) return vf_next_put_image(vf, dmpi, pts); if(vf->priv->opaque) { // Just copy buffer memory to screen for( ypos=vf->priv->y1 ; ypos < vf->priv->y2 ; ypos++ ) { @@ -454,7 +454,7 @@ put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){ } // for xpos } // for ypos } // if !opaque - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, pts); } // put_image static int diff --git a/libmpcodecs/vf_detc.c b/libmpcodecs/vf_detc.c index cf294ac7f7..bbc22fca6c 100644 --- a/libmpcodecs/vf_detc.c +++ b/libmpcodecs/vf_detc.c @@ -45,6 +45,7 @@ struct vf_priv_s { int mode; int (*analyze)(struct vf_priv_s *, mp_image_t *, mp_image_t *); int needread; + struct vf_detc_pts_buf ptsbuf; }; #define COMPE(a,b,e) (abs((a)-(b)) < (((a)+(b))>>(e))) @@ -285,7 +286,7 @@ static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field) } } -static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) +static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi, double pts) { struct vf_priv_s *p = vf->priv; int dropflag; @@ -306,11 +307,12 @@ static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n", p->outframes, p->inframes, (float)p->outframes/p->inframes); p->lastdrop = 0; + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); return 0; } p->outframes++; - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); } static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) @@ -335,22 +337,24 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) /* Don't copy anything unless we'll need to read it. */ if (p->needread) copy_image(dmpi, mpi, 2); p->lastdrop = 0; + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); break; case TC_PROG: /* Copy and display the whole frame. */ copy_image(dmpi, mpi, 2); - ret = do_put_image(vf, dmpi); + ret = do_put_image(vf, dmpi, pts); break; case TC_IL1: /* Only copy bottom field unless we need to read. */ if (p->needread) copy_image(dmpi, mpi, 2); else copy_image(dmpi, mpi, 1); p->lastdrop = 0; + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); break; case TC_IL2: /* Copy top field and show frame, then copy bottom if needed. */ copy_image(dmpi, mpi, 0); - ret = do_put_image(vf, dmpi); + ret = do_put_image(vf, dmpi, pts); if (p->needread) copy_image(dmpi, mpi, 1); break; } @@ -440,6 +444,7 @@ static int vf_open(vf_instance_t *vf, char *args) if (args) parse_args(p, args); p->analyze = anal_funcs[p->mode].func; p->needread = anal_funcs[p->mode].needread; + vf_detc_init_pts_buf(&p->ptsbuf); return 1; } diff --git a/libmpcodecs/vf_divtc.c b/libmpcodecs/vf_divtc.c index d632a4c60d..b3d84d200f 100644 --- a/libmpcodecs/vf_divtc.c +++ b/libmpcodecs/vf_divtc.c @@ -45,6 +45,7 @@ struct vf_priv_s char *bdata; unsigned int *csdata; int *history; + struct vf_detc_pts_buf ptsbuf; }; /* @@ -358,6 +359,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) { case 0: imgop(copyop, dmpi, mpi, 0); + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); return 0; case 4: @@ -372,12 +374,12 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) imgop(copyop, tmpi, mpi, 0); imgop(deghost_plane, tmpi, dmpi, p->deghost); imgop(copyop, dmpi, mpi, 0); - return vf_next_put_image(vf, tmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, tmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); } } imgop(copyop, dmpi, mpi, 0); - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); } static int analyze(struct vf_priv_s *p) @@ -706,6 +708,7 @@ static int vf_open(vf_instance_t *vf, char *args) #endif free(args); + vf_detc_init_pts_buf(&p->ptsbuf); return 1; } diff --git a/libmpcodecs/vf_filmdint.c b/libmpcodecs/vf_filmdint.c index c8da011d81..b40a66831a 100644 --- a/libmpcodecs/vf_filmdint.c +++ b/libmpcodecs/vf_filmdint.c @@ -91,6 +91,7 @@ struct vf_priv_s { struct metrics thres; char chflag; double diff_time, merge_time, decode_time, vo_time, filter_time; + struct vf_detc_pts_buf ptsbuf; }; #define PPZ { 2000, 2000, 0, 2000 } @@ -1331,7 +1332,8 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) "" : " @@@@@@@@@@@@@@@@@"); p->merge_time += get_time() - diff_time; - return show_fields ? vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) : 0; + pts = vf_detc_adjust_pts(&p->ptsbuf, pts, 0, !show_fields); + return show_fields ? vf_next_put_image(vf, dmpi, pts) : 0; } static int query_format(struct vf_instance *vf, unsigned int fmt) @@ -1357,6 +1359,7 @@ static int config(struct vf_instance *vf, unsigned long cxm = 0; unsigned long cym = 0; struct vf_priv_s *p = vf->priv; + vf_detc_init_pts_buf(&p->ptsbuf); // rounding: if(!IMGFMT_IS_RGB(outfmt) && !IMGFMT_IS_BGR(outfmt)){ switch(outfmt){ diff --git a/libmpcodecs/vf_ivtc.c b/libmpcodecs/vf_ivtc.c index 5622ee03b8..966292ff14 100644 --- a/libmpcodecs/vf_ivtc.c +++ b/libmpcodecs/vf_ivtc.c @@ -49,6 +49,7 @@ struct vf_priv_s { int first; int drop, lastdrop, dropnext; int inframes, outframes; + struct vf_detc_pts_buf ptsbuf; }; enum { @@ -426,7 +427,7 @@ static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field) } } -static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) +static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi, double pts) { struct vf_priv_s *p = vf->priv; int dropflag=0; @@ -448,11 +449,12 @@ static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) // p->outframes, p->inframes, (float)p->outframes/p->inframes); mp_msg(MSGT_VFILTER, MSGL_V, "!"); p->lastdrop = 0; + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); return 0; } p->outframes++; - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 0)); } static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) @@ -464,6 +466,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) if (p->first) { /* hack */ p->first = 0; + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); return 1; } @@ -482,22 +485,23 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) ret = 0; p->lastdrop = 0; mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n"); + vf_detc_adjust_pts(&p->ptsbuf, pts, 0, 1); break; case F_MERGE: copy_image(p->dmpi, mpi, 0); - ret = do_put_image(vf, p->dmpi); + ret = do_put_image(vf, p->dmpi, pts); copy_image(p->dmpi, mpi, 1); mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n"); p->dmpi = NULL; break; case F_NEXT: copy_image(p->dmpi, mpi, 2); - ret = do_put_image(vf, p->dmpi); + ret = do_put_image(vf, p->dmpi, pts); mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n"); p->dmpi = NULL; break; case F_SHOW: - ret = do_put_image(vf, p->dmpi); + ret = do_put_image(vf, p->dmpi, pts); copy_image(p->dmpi, mpi, 2); mp_msg(MSGT_VFILTER, MSGL_V, "OK\n"); p->dmpi = NULL; @@ -537,6 +541,7 @@ static int vf_open(vf_instance_t *vf, char *args) #if HAVE_MMX && HAVE_EBX_AVAILABLE if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX; #endif + vf_detc_init_pts_buf(&p->ptsbuf); return 1; } diff --git a/libmpcodecs/vf_lavc.c b/libmpcodecs/vf_lavc.c index 63de4ffdf5..c31044ba21 100644 --- a/libmpcodecs/vf_lavc.c +++ b/libmpcodecs/vf_lavc.c @@ -30,7 +30,6 @@ #include "vd_ffmpeg.h" #include "libavcodec/avcodec.h" - struct vf_priv_s { unsigned char* outbuf; int outbuf_size; @@ -114,7 +113,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){ dmpi->planes[0]=(unsigned char*)&vf->priv->pes; - return vf_next_put_image(vf,dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf,dmpi, pts); } //===========================================================================// diff --git a/libmpcodecs/vf_phase.c b/libmpcodecs/vf_phase.c index 5b0eaaa17d..b9ea66c506 100644 --- a/libmpcodecs/vf_phase.c +++ b/libmpcodecs/vf_phase.c @@ -237,7 +237,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) &vf->priv->buf[2], mode); } - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, pts); } static void uninit(struct vf_instance *vf) diff --git a/libmpcodecs/vf_pullup.c b/libmpcodecs/vf_pullup.c index 2dafe20b31..356774b060 100644 --- a/libmpcodecs/vf_pullup.c +++ b/libmpcodecs/vf_pullup.c @@ -40,6 +40,7 @@ struct vf_priv_s { int init; int fakecount; char *qbuf; + double lastpts; }; static void init_pullup(struct vf_instance *vf, mp_image_t *mpi) @@ -145,10 +146,35 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 : (mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0); - pullup_submit_field(c, b, p); - pullup_submit_field(c, b, p^1); - if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) - pullup_submit_field(c, b, p); + + if (pts == MP_NOPTS_VALUE) { + pullup_submit_field(c, b, p, MP_NOPTS_VALUE); + pullup_submit_field(c, b, p^1, MP_NOPTS_VALUE); + if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) + pullup_submit_field(c, b, p, MP_NOPTS_VALUE); + } else { + double delta; + if (vf->priv->lastpts == MP_NOPTS_VALUE) + delta = 1001.0/60000.0; // delta = field time distance + else + delta = (pts - vf->priv->lastpts) / 2; + if (delta <= 0.0 || delta >= 0.5) { + pullup_submit_field(c, b, p, pts); + pullup_submit_field(c, b, p^1, pts); + if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) + pullup_submit_field(c, b, p, pts); + } else { + vf->priv->lastpts = pts; + if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) { + pullup_submit_field(c, b, p, pts - delta); + pullup_submit_field(c, b, p^1, pts); + pullup_submit_field(c, b, p, pts + delta); + } else { + pullup_submit_field(c, b, p, pts - delta * 0.5); + pullup_submit_field(c, b, p^1, pts + delta * 0.5); + } + } + } pullup_release_buffer(b, 2); @@ -230,7 +256,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) dmpi->qstride = mpi->qstride; dmpi->qscale_type = mpi->qscale_type; } - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, f->pts); } dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE, @@ -249,7 +275,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) dmpi->qstride = mpi->qstride; dmpi->qscale_type = mpi->qscale_type; } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, f->pts); pullup_release_frame(f); return ret; } diff --git a/libmpcodecs/vf_softpulldown.c b/libmpcodecs/vf_softpulldown.c index ab45c698ce..5bd5e66bfd 100644 --- a/libmpcodecs/vf_softpulldown.c +++ b/libmpcodecs/vf_softpulldown.c @@ -33,8 +33,22 @@ struct vf_priv_s { int state; long long in; long long out; + struct vf_detc_pts_buf ptsbuf; + int last_frame_duration; + double buffered_pts; + mp_image_t *buffered_mpi; + int buffered_last_frame_duration; }; +static int continue_buffered_image(struct vf_instance *vf) +{ + double pts = vf->priv->buffered_pts; + mp_image_t *mpi = vf->priv->buffered_mpi; + vf->priv->out++; + vf->priv->state=0; + return vf_next_put_image(vf, mpi, vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, pts, 0, 0, vf->priv->buffered_last_frame_duration)); +} + static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) { mp_image_t *dmpi; @@ -61,7 +75,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) } if (state == 0) { - ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, mpi, vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, pts, 0, 0, vf->priv->last_frame_duration)); vf->priv->out++; if (flags & MP_IMGFIELD_REPEAT_FIRST) { my_memcpy_pic(dmpi->planes[0], @@ -97,12 +111,13 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, mpi->stride[2]*2); } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, vf_softpulldown_adjust_pts(&vf->priv->ptsbuf, pts, 0, 0, vf->priv->last_frame_duration)); vf->priv->out++; if (flags & MP_IMGFIELD_REPEAT_FIRST) { - ret |= vf_next_put_image(vf, mpi, MP_NOPTS_VALUE); - vf->priv->out++; - state=0; + vf->priv->buffered_mpi = mpi; + vf->priv->buffered_pts = pts; + vf->priv->buffered_last_frame_duration = vf->priv->last_frame_duration; + vf_queue_frame(vf, continue_buffered_image); } else { my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2, @@ -125,6 +140,10 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) } vf->priv->state = state; + if (flags & MP_IMGFIELD_REPEAT_FIRST) + vf->priv->last_frame_duration = 3; + else + vf->priv->last_frame_duration = 2; return ret; } @@ -151,6 +170,8 @@ static int vf_open(vf_instance_t *vf, char *args) vf->default_reqs = VFCAP_ACCEPT_STRIDE; vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); vf->priv->state = 0; + vf->priv->last_frame_duration = 2; + vf_detc_init_pts_buf(&vf->priv->ptsbuf); return 1; } diff --git a/libmpcodecs/vf_telecine.c b/libmpcodecs/vf_telecine.c index 9071dfab98..4ae96f2434 100644 --- a/libmpcodecs/vf_telecine.c +++ b/libmpcodecs/vf_telecine.c @@ -31,8 +31,31 @@ struct vf_priv_s { int frame; + double pts; + double lastpts; + mp_image_t *buffered_mpi; }; +static int continue_buffered_image_fullframe(struct vf_instance *vf) +{ + mp_image_t *mpi = vf->priv->buffered_mpi; + mp_image_t *dmpi = vf_get_image(vf->next, mpi->imgfmt, + MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | + MP_IMGFLAG_PRESERVE, mpi->width, mpi->height); + + memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, + dmpi->stride[0], mpi->stride[0]); + if (mpi->flags & MP_IMGFLAG_PLANAR) { + memcpy_pic(dmpi->planes[1], mpi->planes[1], + mpi->chroma_width, mpi->chroma_height, + dmpi->stride[1], mpi->stride[1]); + memcpy_pic(dmpi->planes[2], mpi->planes[2], + mpi->chroma_width, mpi->chroma_height, + dmpi->stride[2], mpi->stride[2]); + } + return vf_next_put_image(vf, dmpi, vf->priv->pts); +} + static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) { mp_image_t *dmpi; @@ -40,14 +63,26 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) vf->priv->frame = (vf->priv->frame+1)%4; - dmpi = vf_get_image(vf->next, mpi->imgfmt, - MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | - MP_IMGFLAG_PRESERVE, mpi->width, mpi->height); + if (pts != MP_NOPTS_VALUE) { + if (vf->priv->lastpts == MP_NOPTS_VALUE) { + vf->priv->pts = pts; + vf->priv->lastpts = pts; + } else { + // we only increase by 80% of input pts at each frame; in the case + // in which we render two frames, we jump back + // this turns 23.98fps perfectly into 29.97fps + vf->priv->pts += 0.8 * (pts - vf->priv->lastpts); + vf->priv->lastpts = pts; + } + } ret = 0; // 0/0 1/1 2/2 2/3 3/0 switch (vf->priv->frame) { case 0: + dmpi = vf_get_image(vf->next, mpi->imgfmt, + MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | + MP_IMGFLAG_PRESERVE, mpi->width, mpi->height); my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2, dmpi->stride[0]*2, mpi->stride[0]*2); @@ -61,21 +96,19 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, mpi->stride[2]*2); } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, vf->priv->pts); + vf->priv->pts = pts; + vf->priv->buffered_mpi = mpi; + vf_queue_frame(vf, continue_buffered_image_fullframe); + return ret; case 1: case 2: - memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, - dmpi->stride[0], mpi->stride[0]); - if (mpi->flags & MP_IMGFLAG_PLANAR) { - memcpy_pic(dmpi->planes[1], mpi->planes[1], - mpi->chroma_width, mpi->chroma_height, - dmpi->stride[1], mpi->stride[1]); - memcpy_pic(dmpi->planes[2], mpi->planes[2], - mpi->chroma_width, mpi->chroma_height, - dmpi->stride[2], mpi->stride[2]); - } - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) || ret; + vf->priv->buffered_mpi = mpi; + return continue_buffered_image_fullframe(vf); case 3: + dmpi = vf_get_image(vf->next, mpi->imgfmt, + MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | + MP_IMGFLAG_PRESERVE, mpi->width, mpi->height); my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2, dmpi->stride[0]*2, mpi->stride[0]*2); @@ -89,7 +122,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, mpi->stride[2]*2); } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, vf->priv->pts); my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2, dmpi->stride[0]*2, mpi->stride[0]*2); if (mpi->flags & MP_IMGFLAG_PLANAR) { @@ -142,6 +175,8 @@ static int vf_open(vf_instance_t *vf, char *args) vf->priv->frame = 1; if (args) sscanf(args, "%d", &vf->priv->frame); vf->priv->frame--; + vf->priv->pts = MP_NOPTS_VALUE; + vf->priv->lastpts = MP_NOPTS_VALUE; return 1; } diff --git a/libmpcodecs/vf_tile.c b/libmpcodecs/vf_tile.c index ad3d662875..0b5dac1559 100644 --- a/libmpcodecs/vf_tile.c +++ b/libmpcodecs/vf_tile.c @@ -80,6 +80,7 @@ struct vf_priv_s { /* Work data */ int frame_cur; + double start_pts; }; @@ -147,6 +148,8 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) // /* First frame, delete the background */ // // } + if (t == 0) + priv->start_pts = pts; /* Position of image */ xi = priv->start + (mpi->w + priv->delta) * (t % priv->xtile); @@ -183,7 +186,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) /* Display the composition */ dmpi->width = xw; dmpi->height = yh; - return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + return vf_next_put_image(vf, dmpi, priv->start_pts); } else { /* Skip the frame */ diff --git a/libmpcodecs/vf_tinterlace.c b/libmpcodecs/vf_tinterlace.c index 91ceb6074b..2583d431e9 100644 --- a/libmpcodecs/vf_tinterlace.c +++ b/libmpcodecs/vf_tinterlace.c @@ -76,16 +76,16 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) mpi->chroma_width, mpi->chroma_height, dmpi->stride[2]*2, mpi->stride[2]); } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, pts); } break; case 1: if (vf->priv->frame & 1) - ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, mpi, pts); break; case 2: if ((vf->priv->frame & 1) == 0) - ret = vf_next_put_image(vf, mpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, mpi, pts); break; case 3: dmpi = vf_get_image(vf->next, mpi->imgfmt, @@ -116,7 +116,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) dmpi->stride[2]*2, mpi->stride[2]); } } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, pts); break; case 4: // Interleave even lines (only) from Frame 'i' with odd @@ -166,7 +166,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, mpi->stride[2]*2); } - ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); + ret = vf_next_put_image(vf, dmpi, pt |