Web lists-archives.com

[MPlayer-dev-eng] [PATCH 2/2] timing: pass through endpts and time last frame correctly.




endpts is the only way we can get correct timing
for the last frame.
It should also be useful to implement e.g. correctly
interpolated pts for frame-doubling deinterlacing and
to fix timing for -nodouble rendering (which draws
the frame a decode time, so we need to know the approximately
right time to decode the next frame before it was decoded/filtered).

Fixes trac issue #2315.
---
 libmenu/vf_menu.c             | 10 +++++-----
 libmpcodecs/dec_video.c       | 13 +++++++++----
 libmpcodecs/dec_video.h       |  4 ++--
 libmpcodecs/vf.c              |  4 ++--
 libmpcodecs/vf.h              |  9 +++++----
 libmpcodecs/vf_1bpp.c         |  4 ++--
 libmpcodecs/vf_2xsai.c        |  4 ++--
 libmpcodecs/vf_ass.c          |  4 ++--
 libmpcodecs/vf_blackframe.c   |  4 ++--
 libmpcodecs/vf_bmovl.c        | 14 +++++++-------
 libmpcodecs/vf_boxblur.c      |  4 ++--
 libmpcodecs/vf_crop.c         |  6 +++---
 libmpcodecs/vf_cropdetect.c   |  4 ++--
 libmpcodecs/vf_decimate.c     |  4 ++--
 libmpcodecs/vf_delogo.c       |  4 ++--
 libmpcodecs/vf_denoise3d.c    |  4 ++--
 libmpcodecs/vf_detc.c         |  4 ++--
 libmpcodecs/vf_dint.c         |  4 ++--
 libmpcodecs/vf_divtc.c        |  6 +++---
 libmpcodecs/vf_down3dright.c  |  4 ++--
 libmpcodecs/vf_eq.c           |  4 ++--
 libmpcodecs/vf_eq2.c          |  4 ++--
 libmpcodecs/vf_expand.c       |  8 ++++----
 libmpcodecs/vf_field.c        |  4 ++--
 libmpcodecs/vf_fil.c          |  6 +++---
 libmpcodecs/vf_filmdint.c     |  4 ++--
 libmpcodecs/vf_fixpts.c       |  4 ++--
 libmpcodecs/vf_flip.c         |  6 +++---
 libmpcodecs/vf_framestep.c    |  4 ++--
 libmpcodecs/vf_fspp.c         |  4 ++--
 libmpcodecs/vf_geq.c          |  4 ++--
 libmpcodecs/vf_gradfun.c      |  4 ++--
 libmpcodecs/vf_halfpack.c     |  4 ++--
 libmpcodecs/vf_harddup.c      |  6 +++---
 libmpcodecs/vf_hqdn3d.c       |  4 ++--
 libmpcodecs/vf_hue.c          |  4 ++--
 libmpcodecs/vf_il.c           |  4 ++--
 libmpcodecs/vf_ilpack.c       |  4 ++--
 libmpcodecs/vf_ivtc.c         |  4 ++--
 libmpcodecs/vf_kerndeint.c    |  6 +++---
 libmpcodecs/vf_lavc.c         |  4 ++--
 libmpcodecs/vf_lavfi.c        |  2 +-
 libmpcodecs/vf_mcdeint.c      |  4 ++--
 libmpcodecs/vf_mirror.c       |  4 ++--
 libmpcodecs/vf_noise.c        |  4 ++--
 libmpcodecs/vf_ow.c           |  4 ++--
 libmpcodecs/vf_palette.c      |  4 ++--
 libmpcodecs/vf_perspective.c  |  4 ++--
 libmpcodecs/vf_phase.c        |  4 ++--
 libmpcodecs/vf_pp.c           |  4 ++--
 libmpcodecs/vf_pp7.c          |  4 ++--
 libmpcodecs/vf_pullup.c       |  6 +++---
 libmpcodecs/vf_qp.c           |  4 ++--
 libmpcodecs/vf_rectangle.c    |  4 ++--
 libmpcodecs/vf_remove_logo.c  |  4 ++--
 libmpcodecs/vf_rgbtest.c      |  4 ++--
 libmpcodecs/vf_rotate.c       |  4 ++--
 libmpcodecs/vf_sab.c          |  4 ++--
 libmpcodecs/vf_scale.c        |  4 ++--
 libmpcodecs/vf_screenshot.c   |  4 ++--
 libmpcodecs/vf_smartblur.c    |  4 ++--
 libmpcodecs/vf_softpulldown.c |  8 ++++----
 libmpcodecs/vf_softskip.c     |  4 ++--
 libmpcodecs/vf_spp.c          |  4 ++--
 libmpcodecs/vf_stereo3d.c     |  4 ++--
 libmpcodecs/vf_swapuv.c       |  4 ++--
 libmpcodecs/vf_telecine.c     |  8 ++++----
 libmpcodecs/vf_test.c         |  4 ++--
 libmpcodecs/vf_tfields.c      |  8 ++++----
 libmpcodecs/vf_tile.c         |  4 ++--
 libmpcodecs/vf_tinterlace.c   | 12 ++++++------
 libmpcodecs/vf_unsharp.c      |  4 ++--
 libmpcodecs/vf_uspp.c         |  4 ++--
 libmpcodecs/vf_vo.c           |  9 ++++++++-
 libmpcodecs/vf_yadif.c        |  6 +++---
 libmpcodecs/vf_yuvcsp.c       |  4 ++--
 libmpcodecs/vf_yvu9.c         |  4 ++--
 libmpcodecs/vf_zrmjpeg.c      |  4 ++--
 libmpdemux/demuxer.c          |  9 +++++++++
 libmpdemux/demuxer.h          |  1 +
 libmpdemux/stheader.h         |  2 ++
 mencoder.c                    |  8 ++++----
 mplayer.c                     | 29 ++++++++++++++++++++++-------
 83 files changed, 237 insertions(+), 197 deletions(-)

diff --git a/libmenu/vf_menu.c b/libmenu/vf_menu.c
index cac1c040d..2e601e0dc 100644
--- a/libmenu/vf_menu.c
+++ b/libmenu/vf_menu.c
@@ -54,12 +54,12 @@ struct vf_priv_s {
   int passthrough;
 };
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts);
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts);
 
 void vf_menu_pause_update(struct vf_instance *vf) {
   const vo_functions_t *video_out = mpctx_get_video_out(vf->priv->current->ctx);
   if(pause_mpi) {
-    put_image(vf,pause_mpi, MP_NOPTS_VALUE);
+    put_image(vf,pause_mpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     // Don't draw the osd atm
     //vf->control(vf,VFCTRL_DRAW_OSD,NULL);
     video_out->flip_page();
@@ -137,14 +137,14 @@ static int key_cb(int code) {
   return menu_read_key(st_priv->current,code);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
   mp_image_t *dmpi = NULL;
 
   if (vf->priv->passthrough) {
     dmpi=vf_get_image(vf->next, IMGFMT_MPEGPES, MP_IMGTYPE_EXPORT,
                       0, mpi->w, mpi->h);
     dmpi->planes[0]=mpi->planes[0];
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf,dmpi, pts, endpts);
   }
 
   // Close all menu who requested it
@@ -202,7 +202,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
       dmpi->priv      = mpi->priv;
     }
   }
-  return vf_next_put_image(vf,dmpi, pts);
+  return vf_next_put_image(vf,dmpi, pts, endpts);
 }
 
 static void uninit(vf_instance_t *vf) {
diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c
index 97a9ac29c..dd9380fff 100644
--- a/libmpcodecs/dec_video.c
+++ b/libmpcodecs/dec_video.c
@@ -388,7 +388,7 @@ int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list,
 }
 
 void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
-                   int drop_frame, double pts, int *full_frame)
+                   int drop_frame, double pts, double endpts, int *full_frame)
 {
     mp_image_t *mpi = NULL;
     unsigned int t = GetTimer();
@@ -420,9 +420,12 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
             for (i = 0; i < sh_video->num_buffered_pts; i++)
                 if (sh_video->buffered_pts[i] < pts)
                     break;
-            for (j = sh_video->num_buffered_pts; j > i; j--)
+            for (j = sh_video->num_buffered_pts; j > i; j--) {
                 sh_video->buffered_pts[j] = sh_video->buffered_pts[j - 1];
+                sh_video->buffered_endpts[j] = sh_video->buffered_endpts[j - 1];
+            }
             sh_video->buffered_pts[i] = pts;
+            sh_video->buffered_endpts[i] = endpts;
             sh_video->num_buffered_pts++;
         }
     }
@@ -454,10 +457,12 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
         if (sh_video->num_buffered_pts) {
             sh_video->num_buffered_pts--;
             sh_video->pts = sh_video->buffered_pts[sh_video->num_buffered_pts];
+            sh_video->endpts = sh_video->buffered_endpts[sh_video->num_buffered_pts];
         } else {
             mp_msg(MSGT_CPLAYER, MSGL_ERR,
                    "No pts value from demuxer to use for frame!\n");
             sh_video->pts = MP_NOPTS_VALUE;
+            sh_video->endpts = MP_NOPTS_VALUE;
         }
         if (delay >= 0) {
             // limit buffered pts only afterwards so we do not get confused
@@ -479,13 +484,13 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
     return mpi;
 }
 
-int filter_video(sh_video_t *sh_video, void *frame, double pts)
+int filter_video(sh_video_t *sh_video, void *frame, double pts, double endpts)
 {
     mp_image_t *mpi = frame;
     unsigned int t2 = GetTimer();
     vf_instance_t *vf = sh_video->vfilter;
     // apply video filters and call the leaf vo/ve
-    int ret = vf->put_image(vf, mpi, pts);
+    int ret = vf->put_image(vf, mpi, pts, endpts);
     if (ret > 0) {
         // draw EOSD first so it ends up below the OSD.
         // Note that changing this is will not work right with vf_ass and the
diff --git a/libmpcodecs/dec_video.h b/libmpcodecs/dec_video.h
index 4be420592..2a53a70e5 100644
--- a/libmpcodecs/dec_video.h
+++ b/libmpcodecs/dec_video.h
@@ -29,8 +29,8 @@ void vfm_help(void);
 int init_best_video_codec(sh_video_t *sh_video, char** video_codec_list, char** video_fm_list);
 void uninit_video(sh_video_t *sh_video);
 
-void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size, int drop_frame, double pts, int *full_frame);
-int filter_video(sh_video_t *sh_video, void *frame, double pts);
+void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size, int drop_frame, double pts, double endpts, int *full_frame);
+int filter_video(sh_video_t *sh_video, void *frame, double pts, double endpts);
 
 int get_video_quality_max(sh_video_t *sh_video);
 void set_video_quality(sh_video_t *sh_video, int quality);
diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c
index d7d0e5f78..046579151 100644
--- a/libmpcodecs/vf.c
+++ b/libmpcodecs/vf.c
@@ -716,14 +716,14 @@ int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
     return flags;
 }
 
-int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
+int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts, double endpts){
     mpi->usage_count--;
     if (mpi->usage_count < 0) {
         mp_msg(MSGT_VFILTER, MSGL_V, "Bad mp_image usage count %i in vf_%s (type %i)\n",
                mpi->usage_count, vf->info->name, mpi->type);
         mpi->usage_count = 0;
     }
-    return vf->next->put_image(vf->next,mpi, pts);
+    return vf->next->put_image(vf->next,mpi, pts, endpts);
 }
 
 void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h
index 8fad5f2e8..0276e5a2d 100644
--- a/libmpcodecs/vf.h
+++ b/libmpcodecs/vf.h
@@ -66,7 +66,7 @@ typedef struct vf_instance {
     void (*get_image)(struct vf_instance *vf,
         mp_image_t *mpi);
     int (*put_image)(struct vf_instance *vf,
-        mp_image_t *mpi, double pts);
+        mp_image_t *mpi, double pts, double endpts);
     void (*start_slice)(struct vf_instance *vf,
         mp_image_t *mpi);
     void (*draw_slice)(struct vf_instance *vf,
@@ -109,8 +109,9 @@ typedef struct vf_seteq_s
 #define VFCTRL_INIT_EOSD       15 /* Select EOSD renderer */
 #define VFCTRL_DRAW_EOSD       16 /* Render EOSD */
 #define VFCTRL_GET_PTS         17 /* Return last pts value that reached vf_vo*/
-#define VFCTRL_SET_DEINTERLACE 18 /* Set deinterlacing status */
-#define VFCTRL_GET_DEINTERLACE 19 /* Get deinterlacing status */
+#define VFCTRL_GET_ENDPTS      18 /* Return last endpts value that reached vf_vo*/
+#define VFCTRL_SET_DEINTERLACE 19 /* Set deinterlacing status */
+#define VFCTRL_GET_DEINTERLACE 20 /* Get deinterlacing status */
 
 #include "vfcap.h"
 
@@ -138,7 +139,7 @@ int vf_next_config(struct vf_instance *vf,
 int vf_next_control(struct vf_instance *vf, int request, void* data);
 void vf_extra_flip(struct vf_instance *vf);
 int vf_next_query_format(struct vf_instance *vf, unsigned int fmt);
-int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts);
+int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts, double endpts);
 void vf_next_draw_slice (struct vf_instance *vf, unsigned char** src, int* stride, int w,int h, int x, int y);
 
 vf_instance_t* append_filters(vf_instance_t* last);
diff --git a/libmpcodecs/vf_1bpp.c b/libmpcodecs/vf_1bpp.c
index 8d1373594..5d09935b3 100644
--- a/libmpcodecs/vf_1bpp.c
+++ b/libmpcodecs/vf_1bpp.c
@@ -123,7 +123,7 @@ static void convert(mp_image_t *mpi, mp_image_t *dmpi, int value0, int value1,in
     }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     // hope we'll get DR buffer:
@@ -173,7 +173,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 	return 0;
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf,dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_2xsai.c b/libmpcodecs/vf_2xsai.c
index a19420ff9..90eb76ee4 100644
--- a/libmpcodecs/vf_2xsai.c
+++ b/libmpcodecs/vf_2xsai.c
@@ -290,7 +290,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,2*width,2*height,2*d_width,2*d_height,flags,outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     // hope we'll get DR buffer:
@@ -302,7 +302,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
                   dmpi->planes[0], dmpi->stride[0],
                   mpi->w, mpi->h, mpi->bpp/8);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf,dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c
index a5b50d97e..cc4b8289c 100644
--- a/libmpcodecs/vf_ass.c
+++ b/libmpcodecs/vf_ass.c
@@ -836,7 +836,7 @@ static void prepare_eosd(vf_instance_t *vf, struct mp_eosd_image_list *imgs)
     vf->priv->prepare_buffer(vf);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     struct mp_eosd_image_list images;
     eosd_render_frame(pts, &images);
@@ -844,7 +844,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
     if (images.changed)
         prepare_eosd(vf, &images);
     vf->priv->render_frame(vf);
-    return vf_next_put_image(vf, vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 static int query_format(struct vf_instance *vf, unsigned int fmt)
diff --git a/libmpcodecs/vf_blackframe.c b/libmpcodecs/vf_blackframe.c
index c72552c99..4d745344a 100644
--- a/libmpcodecs/vf_blackframe.c
+++ b/libmpcodecs/vf_blackframe.c
@@ -66,7 +66,7 @@ static int query_format(struct vf_instance *vf, unsigned fmt) {
     return 0;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     int x, y;
     int nblack=0, pblack=0;
@@ -107,7 +107,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     vf_clone_mpi_attributes(dmpi, mpi);
 
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control(struct vf_instance *vf, int request, void* data){
diff --git a/libmpcodecs/vf_bmovl.c b/libmpcodecs/vf_bmovl.c
index bfbbe0be7..a40dee4d5 100644
--- a/libmpcodecs/vf_bmovl.c
+++ b/libmpcodecs/vf_bmovl.c
@@ -217,7 +217,7 @@ _read_cmd(int fd, char *cmd, char *args) {
 
 
 static int
-put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){
+put_image(struct vf_instance *vf, mp_image_t* mpi, double pts, double endpts){
 	int buf_x=0, buf_y=0, buf_pos=0;
 	int have, got, want;
 	int xpos=0, ypos=0, pos=0;
@@ -264,10 +264,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 			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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 			}
 
 			if(command == CMD_ALPHA) {
@@ -286,7 +286,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 			    }
   				/* pipes/sockets might need multiple calls to read(): */
 			    want = (imgw*imgh*pxsz);
@@ -347,7 +347,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 			}
 
 			for( buf_y=0 ; (buf_y < imgh) && (buf_y < (vf->priv->h-imgy)) ; buf_y++ ) {
@@ -405,7 +405,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 
 	if(vf->priv->opaque) {	// Just copy buffer memory to screen
 		for( ypos=vf->priv->y1 ; ypos < vf->priv->y2 ; ypos++ ) {
@@ -460,7 +460,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 } // put_image
 
 static int
diff --git a/libmpcodecs/vf_boxblur.c b/libmpcodecs/vf_boxblur.c
index bc1ec8028..004dbea80 100644
--- a/libmpcodecs/vf_boxblur.c
+++ b/libmpcodecs/vf_boxblur.c
@@ -127,7 +127,7 @@ static void vBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int s
         }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
         int cw= mpi->w >> mpi->chroma_x_shift;
         int ch= mpi->h >> mpi->chroma_y_shift;
 
@@ -151,7 +151,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         vBlur(dmpi->planes[2], dmpi->planes[2], cw,ch,
                 dmpi->stride[2], dmpi->stride[2], vf->priv->chromaParam.radius, vf->priv->chromaParam.power);
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf,dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_crop.c b/libmpcodecs/vf_crop.c
index 20b0228d8..784ce0e3b 100644
--- a/libmpcodecs/vf_crop.c
+++ b/libmpcodecs/vf_crop.c
@@ -84,10 +84,10 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,vf->priv->crop_w,vf->priv->crop_h,d_width,d_height,flags,outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     if (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
-	return vf_next_put_image(vf,vf->dmpi, pts);
+	return vf_next_put_image(vf,vf->dmpi, pts, endpts);
     dmpi=vf_get_image(vf->next,mpi->imgfmt,
 	MP_IMGTYPE_EXPORT, 0,
 	vf->priv->crop_w, vf->priv->crop_h);
@@ -108,7 +108,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     }
     dmpi->stride[0]=mpi->stride[0];
     dmpi->width=mpi->width;
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf,dmpi, pts, endpts);
 }
 
 static void start_slice(struct vf_instance *vf, mp_image_t *mpi){
diff --git a/libmpcodecs/vf_cropdetect.c b/libmpcodecs/vf_cropdetect.c
index c3de24793..0750418ce 100644
--- a/libmpcodecs/vf_cropdetect.c
+++ b/libmpcodecs/vf_cropdetect.c
@@ -72,7 +72,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     int bpp=mpi->bpp/8;
     int w,h,x,y,shrink_by;
@@ -161,7 +161,7 @@ if(++vf->priv->fno>0){        // ignore first 2 frames - they may be empty
 
 }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf,dmpi, pts, endpts);
 }
 
 static int query_format(struct vf_instance *vf, unsigned int fmt) {
diff --git a/libmpcodecs/vf_decimate.c b/libmpcodecs/vf_decimate.c
index 902c29204..5d4c93734 100644
--- a/libmpcodecs/vf_decimate.c
+++ b/libmpcodecs/vf_decimate.c
@@ -128,7 +128,7 @@ static int diff_to_drop(int hi, int lo, float frac, mp_image_t *old, mp_image_t
         new->w*(new->bpp/8), new->h, old->stride[0], new->stride[0]);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
 
@@ -161,7 +161,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
             mpi->chroma_width, mpi->chroma_height,
             dmpi->stride[2], mpi->stride[2]);
     }
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf)
diff --git a/libmpcodecs/vf_delogo.c b/libmpcodecs/vf_delogo.c
index add6dc6b0..dd3714122 100644
--- a/libmpcodecs/vf_delogo.c
+++ b/libmpcodecs/vf_delogo.c
@@ -195,7 +195,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     if(mpi->flags&MP_IMGFLAG_DIRECT) {
@@ -223,7 +223,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     vf_clone_mpi_attributes(dmpi, mpi);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_denoise3d.c b/libmpcodecs/vf_denoise3d.c
index a952a2228..7619cca33 100644
--- a/libmpcodecs/vf_denoise3d.c
+++ b/libmpcodecs/vf_denoise3d.c
@@ -109,7 +109,7 @@ static void deNoise(unsigned char *Frame,        // mpi->planes[x]
 
 
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
         int cw= mpi->w >> mpi->chroma_x_shift;
         int ch= mpi->h >> mpi->chroma_y_shift;
         int W = mpi->w, H = mpi->h;
@@ -142,7 +142,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
                 vf->priv->Coefs[3] + 256);
 
         vf->priv->pmpi=dmpi; // save reference image
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_detc.c b/libmpcodecs/vf_detc.c
index 511ae3160..a27048bb0 100644
--- a/libmpcodecs/vf_detc.c
+++ b/libmpcodecs/vf_detc.c
@@ -310,10 +310,10 @@ static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
         }
 
         p->outframes++;
-        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
         int ret=0;
         mp_image_t *dmpi;
diff --git a/libmpcodecs/vf_dint.c b/libmpcodecs/vf_dint.c
index ac5bf54a5..18740a177 100644
--- a/libmpcodecs/vf_dint.c
+++ b/libmpcodecs/vf_dint.c
@@ -79,7 +79,7 @@ static int config (struct vf_instance *vf,
     return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
 }
 
-static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     int8_t rrow0[MAXROWSIZE];
     int8_t rrow1[MAXROWSIZE];
@@ -188,7 +188,7 @@ static int put_image (struct vf_instance *vf, mp_image_t *mpi, double pts)
     }
     vf->priv->was_dint = 0;
 //    mp_msg (MSGT_VFILTER, MSGL_INFO, "DI:%d/%d ", vf->priv->rdfr, vf->priv->dfr);
-    return vf_next_put_image (vf, mpi, pts);
+    return vf_next_put_image(vf, mpi, pts, endpts);
 }
 
 static int vf_open(vf_instance_t *vf, char *args){
diff --git a/libmpcodecs/vf_divtc.c b/libmpcodecs/vf_divtc.c
index 111e16f97..48112a9b6 100644
--- a/libmpcodecs/vf_divtc.c
+++ b/libmpcodecs/vf_divtc.c
@@ -258,7 +258,7 @@ static int match(struct vf_priv_s *p, int *diffs,
    return m;
    }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
    {
    mp_image_t *dmpi, *tmpi=0;
    int n, m, f, newphase;
@@ -373,12 +373,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
             }
       }
 
    imgop(copyop, dmpi, mpi, 0);
-   return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+   return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
    }
 
 static int analyze(struct vf_priv_s *p)
diff --git a/libmpcodecs/vf_down3dright.c b/libmpcodecs/vf_down3dright.c
index f1e1f49b0..d1c015d0f 100644
--- a/libmpcodecs/vf_down3dright.c
+++ b/libmpcodecs/vf_down3dright.c
@@ -96,7 +96,7 @@ static void toright(unsigned char *dst[3], unsigned char *src[3],
         }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
         mp_image_t *dmpi;
 
@@ -110,7 +110,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
         toright(dmpi->planes, mpi->planes, dmpi->stride,
                 mpi->stride, mpi->w, mpi->h, vf->priv);
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int config(struct vf_instance *vf,
diff --git a/libmpcodecs/vf_eq.c b/libmpcodecs/vf_eq.c
index c432b1368..1ee3a5970 100644
--- a/libmpcodecs/vf_eq.c
+++ b/libmpcodecs/vf_eq.c
@@ -132,7 +132,7 @@ static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int
 
 /* FIXME: add packed yuv version of process */
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
         mp_image_t *dmpi;
 
@@ -158,7 +158,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
                         vf->priv->contrast);
         }
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control(struct vf_instance *vf, int request, void* data)
diff --git a/libmpcodecs/vf_eq2.c b/libmpcodecs/vf_eq2.c
index 275f19698..e02a59c88 100644
--- a/libmpcodecs/vf_eq2.c
+++ b/libmpcodecs/vf_eq2.c
@@ -238,7 +238,7 @@ void apply_lut (eq2_param_t *par, unsigned char *dst, unsigned char *src,
 }
 
 static
-int put_image (vf_instance_t *vf, mp_image_t *src, double pts)
+int put_image (vf_instance_t *vf, mp_image_t *src, double pts, double endpts)
 {
   unsigned      i;
   vf_eq2_t      *eq2;
@@ -278,7 +278,7 @@ int put_image (vf_instance_t *vf, mp_image_t *src, double pts)
     }
   }
 
-  return vf_next_put_image (vf, dst, pts);
+  return vf_next_put_image(vf, dst, pts, endpts);
 }
 
 static
diff --git a/libmpcodecs/vf_expand.c b/libmpcodecs/vf_expand.c
index 85fae067c..ef9d9030c 100644
--- a/libmpcodecs/vf_expand.c
+++ b/libmpcodecs/vf_expand.c
@@ -398,12 +398,12 @@ static void draw_slice(struct vf_instance *vf,
     vf->priv->first_slice = 0;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     if (vf->priv->passthrough) {
       mp_image_t *dmpi = vf_get_image(vf->next, IMGFMT_MPEGPES,
                                       MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h);
       dmpi->planes[0]=mpi->planes[0];
-      return vf_next_put_image(vf,dmpi, pts);
+      return vf_next_put_image(vf, dmpi, pts, endpts);
     }
 
     if(mpi->flags&MP_IMGFLAG_DIRECT || mpi->flags&MP_IMGFLAG_DRAW_CALLBACK){
@@ -423,7 +423,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 	// we've used DR, so we're ready...
 	if(!(mpi->flags&MP_IMGFLAG_PLANAR))
 	    vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette
-	return vf_next_put_image(vf,vf->dmpi, pts);
+	return vf_next_put_image(vf, vf->dmpi, pts, endpts);
     }
 
     // hope we'll get DR buffer:
@@ -455,7 +455,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 #ifdef OSD_SUPPORT
     if(vf->priv->osd) draw_osd(vf,mpi->w,mpi->h);
 #endif
-    return vf_next_put_image(vf,vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_field.c b/libmpcodecs/vf_field.c
index fcf24be0b..1d735c9c3 100644
--- a/libmpcodecs/vf_field.c
+++ b/libmpcodecs/vf_field.c
@@ -38,7 +38,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,width,height/2,d_width,d_height,flags,outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
         MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
         mpi->width, mpi->height/2);
@@ -56,7 +56,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     } else
         vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
 
-    return vf_next_put_image(vf,vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_fil.c b/libmpcodecs/vf_fil.c
index 7df7eb0af..a16ea66a1 100644
--- a/libmpcodecs/vf_fil.c
+++ b/libmpcodecs/vf_fil.c
@@ -63,10 +63,10 @@ static int config(struct vf_instance *vf,
         (d_width*vf->priv->stridefactor)>>1, 2*d_height/vf->priv->stridefactor, flags, outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     if(mpi->flags&MP_IMGFLAG_DIRECT){
         // we've used DR, so we're ready...
-        return vf_next_put_image(vf,(mp_image_t*)mpi->priv, pts);
+        return vf_next_put_image(vf, (mp_image_t*)mpi->priv, pts, endpts);
     }
 
     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
@@ -84,7 +84,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     } else
         vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
 
-    return vf_next_put_image(vf,vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_filmdint.c b/libmpcodecs/vf_filmdint.c
index 2e43bc1a1..3795170a0 100644
--- a/libmpcodecs/vf_filmdint.c
+++ b/libmpcodecs/vf_filmdint.c
@@ -1136,7 +1136,7 @@ find_breaks(struct vf_priv_s *p, struct frame_stats *s)
 
 #define ITOC(X) (!(X) ? ' ' : (X) + ((X)>9 ? 'a'-10 : '0'))
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
     struct vf_priv_s *p = vf->priv;
@@ -1331,7 +1331,7 @@ 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;
+    return show_fields ? vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE) : 0;
 }
 
 static int query_format(struct vf_instance *vf, unsigned int fmt)
diff --git a/libmpcodecs/vf_fixpts.c b/libmpcodecs/vf_fixpts.c
index ae32b40d8..6bf17ee40 100644
--- a/libmpcodecs/vf_fixpts.c
+++ b/libmpcodecs/vf_fixpts.c
@@ -38,7 +38,7 @@ struct vf_priv_s {
     unsigned print:1;
 };
 
-static int put_image(vf_instance_t *vf, mp_image_t *src, double pts)
+static int put_image(vf_instance_t *vf, mp_image_t *src, double pts, double endpts)
 {
     struct vf_priv_s *p = vf->priv;
 
@@ -63,7 +63,7 @@ static int put_image(vf_instance_t *vf, mp_image_t *src, double pts)
     } else {
         pts = MP_NOPTS_VALUE;
     }
-    return vf_next_put_image(vf, src, pts);
+    return vf_next_put_image(vf, src, pts, endpts);
 }
 
 static void uninit(vf_instance_t *vf)
diff --git a/libmpcodecs/vf_flip.c b/libmpcodecs/vf_flip.c
index e8660ceb5..742e9fdfb 100644
--- a/libmpcodecs/vf_flip.c
+++ b/libmpcodecs/vf_flip.c
@@ -59,12 +59,12 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     if(mpi->flags&MP_IMGFLAG_DIRECT){
 	// we've used DR, so we're ready...
 	if(!(mpi->flags&MP_IMGFLAG_PLANAR))
 	    ((mp_image_t*)mpi->priv)->planes[1] = mpi->planes[1]; // passthrough rgb8 palette
-	return vf_next_put_image(vf,(mp_image_t*)mpi->priv, pts);
+	return vf_next_put_image(vf, (mp_image_t*)mpi->priv, pts, endpts);
     }
 
     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
@@ -85,7 +85,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     } else
 	vf->dmpi->planes[1]=mpi->planes[1]; // passthru bgr8 palette!!!
 
-    return vf_next_put_image(vf,vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_framestep.c b/libmpcodecs/vf_framestep.c
index 701e6afba..8a126790b 100644
--- a/libmpcodecs/vf_framestep.c
+++ b/libmpcodecs/vf_framestep.c
@@ -89,7 +89,7 @@ struct vf_priv_s {
 };
 
 /* Filter handler */
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t        *dmpi;
     struct vf_priv_s  *priv;
@@ -139,7 +139,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
         dmpi->height    = mpi->height;
 
         /* Chain to next filter / output ... */
-        return vf_next_put_image(vf, dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
     }
 
     /* Skip the frame */
diff --git a/libmpcodecs/vf_fspp.c b/libmpcodecs/vf_fspp.c
index 09b90096b..9bb967710 100644
--- a/libmpcodecs/vf_fspp.c
+++ b/libmpcodecs/vf_fspp.c
@@ -523,7 +523,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi)
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
@@ -574,7 +574,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
 #if HAVE_MMXEXT_INLINE
     if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf)
diff --git a/libmpcodecs/vf_geq.c b/libmpcodecs/vf_geq.c
index 6360f5da1..6414ec3b2 100644
--- a/libmpcodecs/vf_geq.c
+++ b/libmpcodecs/vf_geq.c
@@ -78,7 +78,7 @@ static double cr(void *vf, double x, double y){
     return getpix(vf, x, y, 2);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     int x,y, plane;
 
@@ -124,7 +124,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     vf->priv->framenum++;
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_gradfun.c b/libmpcodecs/vf_gradfun.c
index 2e64a42c8..8e84027b1 100644
--- a/libmpcodecs/vf_gradfun.c
+++ b/libmpcodecs/vf_gradfun.c
@@ -295,7 +295,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi)
     mpi->flags |= MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi = vf->dmpi;
     int p;
@@ -326,7 +326,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
                        dmpi->stride[p], mpi->stride[p]);
     }
 
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int query_format(struct vf_instance *vf, unsigned int fmt)
diff --git a/libmpcodecs/vf_halfpack.c b/libmpcodecs/vf_halfpack.c
index 981d09e28..2b4c8c669 100644
--- a/libmpcodecs/vf_halfpack.c
+++ b/libmpcodecs/vf_halfpack.c
@@ -163,7 +163,7 @@ static void (*halfpack)(unsigned char *dst, unsigned char *src[3],
 	int dststride, int srcstride[3], int w, int h);
 
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
 	const uint8_t *src[MP_MAX_PLANES] = {
 		mpi->planes[0] + mpi->stride[0]*vf->priv->field,
@@ -187,7 +187,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
 			mpi->stride, mpi->w, mpi->h);
 	}
 
-	return vf_next_put_image(vf,dmpi, pts);
+	return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int config(struct vf_instance *vf,
diff --git a/libmpcodecs/vf_harddup.c b/libmpcodecs/vf_harddup.c
index 5b6c2ff01..249b37ae9 100644
--- a/libmpcodecs/vf_harddup.c
+++ b/libmpcodecs/vf_harddup.c
@@ -31,7 +31,7 @@ struct vf_priv_s {
     mp_image_t *last_mpi;
 };
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
 
@@ -49,7 +49,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
         dmpi->stride[2] = mpi->stride[2];
     }
 
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control(struct vf_instance *vf, int request, void* data)
@@ -61,7 +61,7 @@ static int control(struct vf_instance *vf, int request, void* data)
         // has been called earlier in the filter chain
         // since the last put_image. This is reasonable
         // because we're handling a duplicate frame!
-        if (put_image(vf, vf->priv->last_mpi, MP_NOPTS_VALUE))
+        if (put_image(vf, vf->priv->last_mpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE))
             return CONTROL_TRUE;
         break;
     }
diff --git a/libmpcodecs/vf_hqdn3d.c b/libmpcodecs/vf_hqdn3d.c
index eba3439d8..922254492 100644
--- a/libmpcodecs/vf_hqdn3d.c
+++ b/libmpcodecs/vf_hqdn3d.c
@@ -208,7 +208,7 @@ static void deNoise(unsigned char *Frame,        // mpi->planes[x]
 }
 
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
         int cw= mpi->w >> mpi->chroma_x_shift;
         int ch= mpi->h >> mpi->chroma_y_shift;
         int W = mpi->w, H = mpi->h;
@@ -238,7 +238,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
                 vf->priv->Coefs[2],
                 vf->priv->Coefs[3]);
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_hue.c b/libmpcodecs/vf_hue.c
index 177142f03..80a3bc0c3 100644
--- a/libmpcodecs/vf_hue.c
+++ b/libmpcodecs/vf_hue.c
@@ -76,7 +76,7 @@ static void (*process)(uint8_t *udst, uint8_t *vdst, uint8_t *usrc, uint8_t *vsr
 
 /* FIXME: add packed yuv version of process */
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
         mp_image_t *dmpi;
 
@@ -107,7 +107,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
                         vf->priv->hue, vf->priv->saturation);
         }
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control(struct vf_instance *vf, int request, void* data)
diff --git a/libmpcodecs/vf_il.c b/libmpcodecs/vf_il.c
index 210e30d3f..079ea791d 100644
--- a/libmpcodecs/vf_il.c
+++ b/libmpcodecs/vf_il.c
@@ -73,7 +73,7 @@ static void interleave(uint8_t *dst, uint8_t *src, int w, int h, int dstStride,
     }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int w;
     FilterParam *luma  = &vf->priv->lumaParam;
     FilterParam *chroma= &vf->priv->chromaParam;
@@ -100,7 +100,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
             dmpi->stride[2], mpi->stride[2], chroma->interleave, luma->swap);
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_ilpack.c b/libmpcodecs/vf_ilpack.c
index 731d93f20..214c07c62 100644
--- a/libmpcodecs/vf_ilpack.c
+++ b/libmpcodecs/vf_ilpack.c
@@ -373,7 +373,7 @@ static void ilpack(unsigned char *dst, unsigned char *src[3],
 }
 
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
 
@@ -384,7 +384,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
 
     ilpack(dmpi->planes[0], mpi->planes, dmpi->stride[0], mpi->stride, mpi->w, mpi->h, vf->priv->pack);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int config(struct vf_instance *vf,
diff --git a/libmpcodecs/vf_ivtc.c b/libmpcodecs/vf_ivtc.c
index 5a19d24ab..9b41533fe 100644
--- a/libmpcodecs/vf_ivtc.c
+++ b/libmpcodecs/vf_ivtc.c
@@ -452,10 +452,10 @@ static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi)
     }
 
     p->outframes++;
-    return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+    return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     int ret=0;
     struct vf_priv_s *p = vf->priv;
diff --git a/libmpcodecs/vf_kerndeint.c b/libmpcodecs/vf_kerndeint.c
index c5197fc54..f69c6e67c 100644
--- a/libmpcodecs/vf_kerndeint.c
+++ b/libmpcodecs/vf_kerndeint.c
@@ -74,7 +74,7 @@ static inline int IsYUY2(mp_image_t *mpi)
 #define PLANAR_U 1
 #define PLANAR_V 2
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int cw= mpi->w >> mpi->chroma_x_shift;
     int ch= mpi->h >> mpi->chroma_y_shift;
     int W = mpi->w, H = mpi->h;
@@ -98,7 +98,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     mp_image_t *dmpi, *pmpi;
 
     if(!vf->priv->do_deinterlace)
-        return vf_next_put_image(vf, mpi, pts);
+        return vf_next_put_image(vf, mpi, pts, endpts);
 
     dmpi=vf_get_image(vf->next,mpi->imgfmt,
         MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE,
@@ -273,7 +273,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         }
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_lavc.c b/libmpcodecs/vf_lavc.c
index 62dcf91a4..e6bbc50d3 100644
--- a/libmpcodecs/vf_lavc.c
+++ b/libmpcodecs/vf_lavc.c
@@ -82,7 +82,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,width,height,d_width,d_height,flags,IMGFMT_MPEGPES);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t* dmpi;
     int out_size;
     AVFrame *pic= vf->priv->pic;
@@ -116,7 +116,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, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_lavfi.c b/libmpcodecs/vf_lavfi.c
index 0f6e71a05..905b13bfe 100644
--- a/libmpcodecs/vf_lavfi.c
+++ b/libmpcodecs/vf_lavfi.c
@@ -300,7 +300,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi)
     mpi->priv = buf;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     AVFilterBufferRef *buf;
     mp_image_t *cmpi = NULL;
diff --git a/libmpcodecs/vf_mcdeint.c b/libmpcodecs/vf_mcdeint.c
index 1b2d1bbaf..f2fc4711c 100644
--- a/libmpcodecs/vf_mcdeint.c
+++ b/libmpcodecs/vf_mcdeint.c
@@ -282,7 +282,7 @@ return; //caused problems, dunno why
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
@@ -298,7 +298,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_mirror.c b/libmpcodecs/vf_mirror.c
index 5ac05e914..06c299ba1 100644
--- a/libmpcodecs/vf_mirror.c
+++ b/libmpcodecs/vf_mirror.c
@@ -83,7 +83,7 @@ static void mirror(unsigned char* dst,unsigned char* src,int dststride,int srcst
 
 //===========================================================================//
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     // hope we'll get DR buffer:
@@ -108,7 +108,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         dmpi->planes[1]=mpi->planes[1]; // passthrough rgb8 palette
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_noise.c b/libmpcodecs/vf_noise.c
index 0fe9dcb96..244294a7b 100644
--- a/libmpcodecs/vf_noise.c
+++ b/libmpcodecs/vf_noise.c
@@ -339,7 +339,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
         mp_image_t *dmpi;
 
         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
@@ -365,7 +365,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_ow.c b/libmpcodecs/vf_ow.c
index f7fb02db7..4647068cd 100644
--- a/libmpcodecs/vf_ow.c
+++ b/libmpcodecs/vf_ow.c
@@ -233,7 +233,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
@@ -251,7 +251,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
     filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_palette.c b/libmpcodecs/vf_palette.c
index fc6764b0b..eafac4d02 100644
--- a/libmpcodecs/vf_palette.c
+++ b/libmpcodecs/vf_palette.c
@@ -112,7 +112,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     uint8_t *old_palette = mpi->planes[1];
 
@@ -171,7 +171,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     }
     mpi->planes[1] = old_palette;
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_perspective.c b/libmpcodecs/vf_perspective.c
index f5a9d6be3..e826195ab 100644
--- a/libmpcodecs/vf_perspective.c
+++ b/libmpcodecs/vf_perspective.c
@@ -260,7 +260,7 @@ static inline void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int
     }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int cw= mpi->w >> mpi->chroma_x_shift;
     int ch= mpi->h >> mpi->chroma_y_shift;
 
@@ -286,7 +286,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
                 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift);
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_phase.c b/libmpcodecs/vf_phase.c
index 101290dec..790ffa199 100644
--- a/libmpcodecs/vf_phase.c
+++ b/libmpcodecs/vf_phase.c
@@ -196,7 +196,7 @@ static enum mode analyze_plane(unsigned char *old, unsigned char *new,
    return mode;
    }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
    {
    mp_image_t *dmpi;
    int w;
@@ -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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
    }
 
 static void uninit(struct vf_instance *vf)
diff --git a/libmpcodecs/vf_pp.c b/libmpcodecs/vf_pp.c
index a26b28065..9721554d0 100644
--- a/libmpcodecs/vf_pp.c
+++ b/libmpcodecs/vf_pp.c
@@ -128,7 +128,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
 	// no DR, so get a new image! hope we'll get DR buffer:
 	vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
@@ -153,7 +153,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 		    mpi->pict_type);
 #endif
     }
-    return vf_next_put_image(vf,vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_pp7.c b/libmpcodecs/vf_pp7.c
index e47d642ed..6d6963db6 100644
--- a/libmpcodecs/vf_pp7.c
+++ b/libmpcodecs/vf_pp7.c
@@ -372,7 +372,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     if(mpi->flags&MP_IMGFLAG_DIRECT){
@@ -404,7 +404,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_pullup.c b/libmpcodecs/vf_pullup.c
index 5d08768b7..09dbd0f42 100644
--- a/libmpcodecs/vf_pullup.c
+++ b/libmpcodecs/vf_pullup.c
@@ -104,7 +104,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi)
 }
 #endif
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     struct pullup_context *c = vf->priv->ctx;
     struct pullup_buffer *b;
@@ -230,7 +230,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     }
     dmpi = vf_get_image(vf->next, mpi->imgfmt,
         MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
@@ -249,7 +249,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     pullup_release_frame(f);
     return ret;
 }
diff --git a/libmpcodecs/vf_qp.c b/libmpcodecs/vf_qp.c
index 8dd935e59..31c9b5060 100644
--- a/libmpcodecs/vf_qp.c
+++ b/libmpcodecs/vf_qp.c
@@ -99,7 +99,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
         mp_image_t *dmpi;
         int x,y;
 
@@ -139,7 +139,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
             }
         }
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_rectangle.c b/libmpcodecs/vf_rectangle.c
index 21bc209de..c169246dc 100644
--- a/libmpcodecs/vf_rectangle.c
+++ b/libmpcodecs/vf_rectangle.c
@@ -83,7 +83,7 @@ control(struct vf_instance *vf, int request, void *data)
     return 0;
 }
 static int
-put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){
+put_image(struct vf_instance *vf, mp_image_t* mpi, double pts, double endpts){
     mp_image_t* dmpi;
     unsigned int bpp = mpi->bpp / 8;
     int x, y, w, h;
@@ -152,7 +152,7 @@ put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){
             p += dmpi->stride[0];
         }
     }
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int
diff --git a/libmpcodecs/vf_remove_logo.c b/libmpcodecs/vf_remove_logo.c
index 7469ced1d..0841ef6aa 100644
--- a/libmpcodecs/vf_remove_logo.c
+++ b/libmpcodecs/vf_remove_logo.c
@@ -774,7 +774,7 @@ static void convert_yv12(const vf_instance_t * const vf, const char * const sour
  * filter, has the logo removed by the filter, and is then sent to the next
  * filter.
  */
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     dmpi=vf_get_image(vf->next,vf->priv->fmt,
@@ -813,7 +813,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         return 0;
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_rgbtest.c b/libmpcodecs/vf_rgbtest.c
index cbed6ed36..1e15e71eb 100644
--- a/libmpcodecs/vf_rgbtest.c
+++ b/libmpcodecs/vf_rgbtest.c
@@ -113,7 +113,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,width,height,d_width,d_height,flags,vf->priv->fmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     int x, y;
     int w = vf->priv->w > 0 ? vf->priv->w : mpi->w;
@@ -137,7 +137,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
          }
      }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_rotate.c b/libmpcodecs/vf_rotate.c
index 08d73bec2..8abf6c94a 100644
--- a/libmpcodecs/vf_rotate.c
+++ b/libmpcodecs/vf_rotate.c
@@ -84,7 +84,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,height,width,d_height,d_width,flags,outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     // hope we'll get DR buffer:
@@ -109,7 +109,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette
     }
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_sab.c b/libmpcodecs/vf_sab.c
index 203c468dd..b131c394f 100644
--- a/libmpcodecs/vf_sab.c
+++ b/libmpcodecs/vf_sab.c
@@ -241,7 +241,7 @@ if((x/32)&1){
     }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int cw= mpi->w >> mpi->chroma_x_shift;
     int ch= mpi->h >> mpi->chroma_y_shift;
 
@@ -255,7 +255,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     blur(dmpi->planes[1], mpi->planes[1], cw    , ch   , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
     blur(dmpi->planes[2], mpi->planes[2], cw    , ch   , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_scale.c b/libmpcodecs/vf_scale.c
index 8eca5120a..ef50261ea 100644
--- a/libmpcodecs/vf_scale.c
+++ b/libmpcodecs/vf_scale.c
@@ -459,7 +459,7 @@ static void draw_slice(struct vf_instance *vf,
     scale(vf->priv->ctx, vf->priv->ctx2, src, stride, y, h, dmpi->planes, dmpi->stride, vf->priv->interlaced);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi=mpi->priv;
 
 //  printf("vf_scale::put_image(): processing whole frame! dmpi=%p flag=%d\n",
@@ -483,7 +483,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     if(vf->priv->palette) dmpi->planes[1]=vf->priv->palette; // export palette!
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control(struct vf_instance *vf, int request, void* data){
diff --git a/libmpcodecs/vf_screenshot.c b/libmpcodecs/vf_screenshot.c
index 992ea6df3..9aafac3a2 100644
--- a/libmpcodecs/vf_screenshot.c
+++ b/libmpcodecs/vf_screenshot.c
@@ -194,7 +194,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi)
     mpi->priv=vf->dmpi;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi = (mp_image_t *)mpi->priv;
 
@@ -224,7 +224,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
         vf->priv->store_slices = 0;
     }
 
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control (vf_instance_t *vf, int request, void *data)
diff --git a/libmpcodecs/vf_smartblur.c b/libmpcodecs/vf_smartblur.c
index 0ccd36938..6de67bf5e 100644
--- a/libmpcodecs/vf_smartblur.c
+++ b/libmpcodecs/vf_smartblur.c
@@ -182,7 +182,7 @@ static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride,
     }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int cw= mpi->w >> mpi->chroma_x_shift;
     int ch= mpi->h >> mpi->chroma_y_shift;
     int threshold = vf->priv->luma.threshold || vf->priv->chroma.threshold;
@@ -198,7 +198,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     blur(dmpi->planes[1], mpi->planes[1], cw    , ch   , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
     blur(dmpi->planes[2], mpi->planes[2], cw    , ch   , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_softpulldown.c b/libmpcodecs/vf_softpulldown.c
index 1a66e5607..fed233971 100644
--- a/libmpcodecs/vf_softpulldown.c
+++ b/libmpcodecs/vf_softpulldown.c
@@ -35,7 +35,7 @@ struct vf_priv_s {
     long long out;
 };
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
     int ret = 0;
@@ -61,7 +61,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         vf->priv->out++;
         if (flags & MP_IMGFIELD_REPEAT_FIRST) {
             my_memcpy_pic(dmpi->planes[0],
@@ -97,10 +97,10 @@ 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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         vf->priv->out++;
         if (flags & MP_IMGFIELD_REPEAT_FIRST) {
-            ret |= vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
+            ret |= vf_next_put_image(vf, mpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
             vf->priv->out++;
             state=0;
         } else {
diff --git a/libmpcodecs/vf_softskip.c b/libmpcodecs/vf_softskip.c
index 150c3e7b7..c0189949f 100644
--- a/libmpcodecs/vf_softskip.c
+++ b/libmpcodecs/vf_softskip.c
@@ -31,7 +31,7 @@ struct vf_priv_s {
     int skipflag;
 };
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
 
@@ -51,7 +51,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
         dmpi->stride[2] = mpi->stride[2];
     }
 
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int control(struct vf_instance *vf, int request, void* data)
diff --git a/libmpcodecs/vf_spp.c b/libmpcodecs/vf_spp.c
index 19257fb09..97cacdc6f 100644
--- a/libmpcodecs/vf_spp.c
+++ b/libmpcodecs/vf_spp.c
@@ -470,7 +470,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
         mp_image_t *dmpi;
 
         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
@@ -519,7 +519,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
         if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
 
-        return vf_next_put_image(vf,dmpi, pts);
+        return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_stereo3d.c b/libmpcodecs/vf_stereo3d.c
index f26d95df3..641519e32 100644
--- a/libmpcodecs/vf_stereo3d.c
+++ b/libmpcodecs/vf_stereo3d.c
@@ -283,7 +283,7 @@ static int config(struct vf_instance *vf, int width, int height, int d_width,
                           d_width, d_height, flags, outfmt);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
     if (vf->priv->in.fmt == vf->priv->out.fmt) { //nothing to do
@@ -384,7 +384,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
             break;
         }
     }
-    return vf_next_put_image(vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static int query_format(struct vf_instance *vf, unsigned int fmt)
diff --git a/libmpcodecs/vf_swapuv.c b/libmpcodecs/vf_swapuv.c
index 4d0e8fcb1..c8c0d61f9 100644
--- a/libmpcodecs/vf_swapuv.c
+++ b/libmpcodecs/vf_swapuv.c
@@ -48,7 +48,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->priv=(void*)dmpi;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     if(mpi->flags&MP_IMGFLAG_DIRECT){
@@ -67,7 +67,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     vf_clone_mpi_attributes(dmpi, mpi);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_telecine.c b/libmpcodecs/vf_telecine.c
index 3ffa87faf..3d90c98d6 100644
--- a/libmpcodecs/vf_telecine.c
+++ b/libmpcodecs/vf_telecine.c
@@ -33,7 +33,7 @@ struct vf_priv_s {
     int frame;
 };
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t *dmpi;
     int ret;
@@ -63,7 +63,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
                 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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         /* Fallthrough */
     case 1:
     case 2:
@@ -77,7 +77,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
                 chroma_width, mpi->chroma_height,
                 dmpi->stride[2], mpi->stride[2]);
         }
-        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) || ret;
+        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE, MP_NOPTS_VALUE) || ret;
     case 3:
         my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
             mpi->planes[0]+mpi->stride[0], w, mpi->h/2,
@@ -92,7 +92,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
                 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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         my_memcpy_pic(dmpi->planes[0], mpi->planes[0], w, mpi->h/2,
             dmpi->stride[0]*2, mpi->stride[0]*2);
         if (mpi->flags & MP_IMGFLAG_PLANAR) {
diff --git a/libmpcodecs/vf_test.c b/libmpcodecs/vf_test.c
index bef06120e..a96e077c0 100644
--- a/libmpcodecs/vf_test.c
+++ b/libmpcodecs/vf_test.c
@@ -269,7 +269,7 @@ static void ring2Test(uint8_t *dst, int stride, int off)
         }
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     int frame= vf->priv->frame_num;
 
@@ -302,7 +302,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     frame++;
     vf->priv->frame_num= frame;
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_tfields.c b/libmpcodecs/vf_tfields.c
index 7eec78673..e97376220 100644
--- a/libmpcodecs/vf_tfields.c
+++ b/libmpcodecs/vf_tfields.c
@@ -328,7 +328,7 @@ static void (*qpel_4tap)(unsigned char *d, unsigned char *s, int w, int h, int d
 
 static int continue_buffered_image(struct vf_instance *vf);
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
 	vf->priv->buffered_mpi = mpi;
 	vf->priv->buffered_pts = pts;
@@ -392,7 +392,7 @@ static int continue_buffered_image(struct vf_instance *vf)
 				dmpi->stride[1] = 2*mpi->stride[1];
 				dmpi->stride[2] = 2*mpi->stride[2];
 			}
-			ret |= vf_next_put_image(vf, dmpi, calc_pts(pts, i));
+			ret |= vf_next_put_image(vf, dmpi, calc_pts(pts, i), MP_NOPTS_VALUE);
 			if (correct_pts)
 				break;
 			else
@@ -422,7 +422,7 @@ static int continue_buffered_image(struct vf_instance *vf)
 				deint(dmpi->planes[2], dmpi->stride[2], mpi->planes[2], mpi->stride[2],
 					mpi->chroma_width, mpi->chroma_height, (i^!tff));
 			}
-			ret |= vf_next_put_image(vf, dmpi, calc_pts(pts, i));
+			ret |= vf_next_put_image(vf, dmpi, calc_pts(pts, i), MP_NOPTS_VALUE);
 			if (correct_pts)
 				break;
 			else
@@ -448,7 +448,7 @@ static int continue_buffered_image(struct vf_instance *vf)
 					mpi->chroma_width, mpi->chroma_height/2,
 					dmpi->stride[2], mpi->stride[2]*2, (i^!tff));
 			}
-			ret |= vf_next_put_image(vf, dmpi, calc_pts(pts, i));
+			ret |= vf_next_put_image(vf, dmpi, calc_pts(pts, i), MP_NOPTS_VALUE);
 			if (correct_pts)
 				break;
 			else
diff --git a/libmpcodecs/vf_tile.c b/libmpcodecs/vf_tile.c
index 9ec037ef4..44f14c9fb 100644
--- a/libmpcodecs/vf_tile.c
+++ b/libmpcodecs/vf_tile.c
@@ -107,7 +107,7 @@ static int config(struct vf_instance *vf,
 }
 
 /* Filter handler */
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     mp_image_t        *dmpi;
     struct vf_priv_s  *priv;
@@ -184,7 +184,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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     }
     else {
         /* Skip the frame */
diff --git a/libmpcodecs/vf_tinterlace.c b/libmpcodecs/vf_tinterlace.c
index 8cd6ac89b..2fe3c2e7b 100644
--- a/libmpcodecs/vf_tinterlace.c
+++ b/libmpcodecs/vf_tinterlace.c
@@ -37,7 +37,7 @@ struct vf_priv_s {
     mp_image_t *dmpi;
 };
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts)
 {
     int ret = 0;
     mp_image_t *dmpi;
@@ -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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         }
         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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         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, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         }
         break;
     }
diff --git a/libmpcodecs/vf_unsharp.c b/libmpcodecs/vf_unsharp.c
index 56e85f473..12aec2390 100644
--- a/libmpcodecs/vf_unsharp.c
+++ b/libmpcodecs/vf_unsharp.c
@@ -179,7 +179,7 @@ static void get_image( struct vf_instance *vf, mp_image_t *mpi ) {
     mpi->flags |= MP_IMGFLAG_DIRECT;
 }
 
-static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) {
+static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts) {
     mp_image_t *dmpi = mpi->priv;
     mpi->priv = NULL;
 
@@ -202,7 +202,7 @@ static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) {
         __asm__ volatile ("sfence\n\t");
 #endif
 
-    return vf_next_put_image( vf, dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit( struct vf_instance *vf ) {
diff --git a/libmpcodecs/vf_uspp.c b/libmpcodecs/vf_uspp.c
index dd417009c..9f1709793 100644
--- a/libmpcodecs/vf_uspp.c
+++ b/libmpcodecs/vf_uspp.c
@@ -275,7 +275,7 @@ static void get_image(struct vf_instance *vf, mp_image_t *mpi){
     mpi->flags|=MP_IMGFLAG_DIRECT;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
 
     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
@@ -307,7 +307,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 static void uninit(struct vf_instance *vf){
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index 6511460f7..ce5d51345 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -34,6 +34,7 @@
 
 struct vf_priv_s {
     double pts;
+    double endpts;
     const vo_functions_t *vo;
 };
 #define video_out (vf->priv->vo)
@@ -136,6 +137,11 @@ static int control(struct vf_instance *vf, int request, void* data)
 	*(double *)data = vf->priv->pts;
 	return CONTROL_TRUE;
     }
+    case VFCTRL_GET_ENDPTS:
+    {
+	*(double *)data = vf->priv->endpts;
+	return CONTROL_TRUE;
+    }
     }
     // return video_out->control(request,data);
     return CONTROL_UNKNOWN;
@@ -160,10 +166,11 @@ static void get_image(struct vf_instance *vf,
 }
 
 static int put_image(struct vf_instance *vf,
-        mp_image_t *mpi, double pts){
+        mp_image_t *mpi, double pts, double endpts){
   if(!vo_config_count) return 0; // vo not configured?
   // record pts (potentially modified by filters) for main loop
   vf->priv->pts = pts;
+  vf->priv->endpts = endpts;
   // first check, maybe the vo/vf plugin implements draw_image using mpi:
   if(video_out->control(VOCTRL_DRAW_IMAGE,mpi)==VO_TRUE) return 1; // done.
   // nope, fallback to old draw_frame/draw_slice:
diff --git a/libmpcodecs/vf_yadif.c b/libmpcodecs/vf_yadif.c
index ccd050f03..aeec5fcc9 100644
--- a/libmpcodecs/vf_yadif.c
+++ b/libmpcodecs/vf_yadif.c
@@ -396,7 +396,7 @@ static int config(struct vf_instance *vf,
 
 static int continue_buffered_image(struct vf_instance *vf);
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int tff;
 
     if(vf->priv->parity < 0) {
@@ -415,7 +415,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
     vf->priv->buffered_pts = pts;
 
     if(vf->priv->do_deinterlace == 0)
-        return vf_next_put_image(vf, mpi, pts);
+        return vf_next_put_image(vf, mpi, pts, endpts);
     else if(vf->priv->do_deinterlace == 1){
         vf->priv->do_deinterlace= 2;
         return 0;
@@ -443,7 +443,7 @@ static int continue_buffered_image(struct vf_instance *vf)
         filter(vf->priv, dmpi->planes, dmpi->stride, mpi->w, mpi->h, i ^ tff ^ 1, tff);
         if (correct_pts && i < (vf->priv->mode & 1))
             vf_queue_frame(vf, continue_buffered_image);
-        ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/);
+        ret |= vf_next_put_image(vf, dmpi, pts /*FIXME*/, MP_NOPTS_VALUE);
         if (correct_pts)
             break;
         if(i<(vf->priv->mode&1))
diff --git a/libmpcodecs/vf_yuvcsp.c b/libmpcodecs/vf_yuvcsp.c
index 102ce1453..efb3c7118 100644
--- a/libmpcodecs/vf_yuvcsp.c
+++ b/libmpcodecs/vf_yuvcsp.c
@@ -48,7 +48,7 @@ static inline int clamp_c(int x){
     return (x > 240) ? 240 : (x < 16) ? 16 : x;
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     int i,j;
     uint8_t *y_in, *cb_in, *cr_in;
     uint8_t *y_out, *cb_out, *cr_out;
@@ -76,7 +76,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
             cr_out[i*vf->dmpi->stride[2]+j] = clamp_c(cr_in[i*mpi->stride[2]+j]);
         }
 
-    return vf_next_put_image(vf,vf->dmpi, pts);
+    return vf_next_put_image(vf, vf->dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_yvu9.c b/libmpcodecs/vf_yvu9.c
index 1f74261cc..28f158d28 100644
--- a/libmpcodecs/vf_yvu9.c
+++ b/libmpcodecs/vf_yvu9.c
@@ -45,7 +45,7 @@ static int config(struct vf_instance *vf,
     return vf_next_config(vf,width,height,d_width,d_height,flags,IMGFMT_YV12);
 }
 
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
     mp_image_t *dmpi;
     int y,w,h;
 
@@ -75,7 +75,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 
     vf_clone_mpi_attributes(dmpi, mpi);
 
-    return vf_next_put_image(vf,dmpi, pts);
+    return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 //===========================================================================//
diff --git a/libmpcodecs/vf_zrmjpeg.c b/libmpcodecs/vf_zrmjpeg.c
index 6d3c7b2aa..ef5d5f00a 100644
--- a/libmpcodecs/vf_zrmjpeg.c
+++ b/libmpcodecs/vf_zrmjpeg.c
@@ -817,7 +817,7 @@ static int config(struct vf_instance *vf, int width, int height, int d_width,
  * \param mpi pointer to mp_image_t structure
  * \param pts
  */
-static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
+static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts, double endpts){
 	struct vf_priv_s *priv = vf->priv;
 	int size = 0;
 	int i;
@@ -833,7 +833,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
 			MP_IMGTYPE_EXPORT, 0, mpi->w, mpi->h);
 	dmpi->planes[0] = (uint8_t*)priv->buf;
 	dmpi->planes[1] = (uint8_t*)size;
-	return vf_next_put_image(vf,dmpi, pts);
+	return vf_next_put_image(vf, dmpi, pts, endpts);
 }
 
 /// query_format entrypoint for the ZRMJPEG vf filter
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index 29e434962..b70dae468 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -886,14 +886,23 @@ int ds_get_packet(demux_stream_t *ds, unsigned char **start)
 
 int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts)
 {
+    double dummy;
+    return ds_get_packet_pts_endpts(ds, start, pts, &dummy);
+}
+
+int ds_get_packet_pts_endpts(demux_stream_t *ds, unsigned char **start, double *pts, double *endpts)
+{
     int len;
     *pts = MP_NOPTS_VALUE;
+    *endpts = MP_NOPTS_VALUE;
     len = ds_get_packet(ds, start);
     if (len < 0)
         return len;
     // Return pts unless this read starts from the middle of a packet
     if (len == ds->buffer_pos)
         *pts = ds->current->pts;
+    if (len == ds->buffer_size)
+        *endpts = ds->current->endpts;
     return len;
 }
 
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index 516e663b5..eeb878bb8 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -405,6 +405,7 @@ static inline int demux_getc(demux_stream_t *ds){
 void ds_free_packs(demux_stream_t *ds);
 int ds_get_packet(demux_stream_t *ds,unsigned char **start);
 int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts);
+int ds_get_packet_pts_endpts(demux_stream_t *ds, unsigned char **start, double *pts, double *endpts);
 int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start,
                       double *pts, double *endpts);
 double ds_get_next_pts(demux_stream_t *ds);
diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h
index 9060caa02..ddf180b05 100644
--- a/libmpdemux/stheader.h
+++ b/libmpdemux/stheader.h
@@ -38,6 +38,7 @@
   /* audio: last known pts value in output from decoder \
    * video: predicted/interpolated PTS of the current frame */ \
   double pts; \
+  double endpts; \
   /* codec-specific: */ \
   void* context;   /* codec-specific stuff (usually HANDLE or struct pointer) */ \
   char* lang; /* track language */ \
@@ -102,6 +103,7 @@ typedef struct sh_video {
   float next_frame_time;
   double last_pts;
   double buffered_pts[64];
+  double buffered_endpts[64];
   int num_buffered_pts;
   // output format: (set by demuxer)
   float fps;              // frames per second (set only if constant fps)
diff --git a/mencoder.c b/mencoder.c
index 0f6774c9e..9fc3ebe25 100644
--- a/mencoder.c
+++ b/mencoder.c
@@ -463,9 +463,9 @@ static int slowseek(float end_pts, demux_stream_t *d_video,
 
         if (vfilter) {
             int softskip = (vfilter->control(vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) == CONTROL_TRUE);
-            void *decoded_frame = decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip, MP_NOPTS_VALUE, NULL);
+            void *decoded_frame = decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip, MP_NOPTS_VALUE, MP_NOPTS_VALUE, NULL);
 	    if (decoded_frame)
-		filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);
+		filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 	    else if (frame_data->flush)
 		return 2;
         }
@@ -1504,7 +1504,7 @@ default:
                      (!sh_video->vfilter ||
                       ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE);
     void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size,
-                                       drop_frame, MP_NOPTS_VALUE, NULL);
+                                       drop_frame, MP_NOPTS_VALUE, MP_NOPTS_VALUE, NULL);
     if (frame_data.flush && !decoded_frame)
         at_eof = 3;
     if (did_seek && sh_video->pts != MP_NOPTS_VALUE) {
@@ -1517,7 +1517,7 @@ default:
     // sh_video->pts causes flickering with subtitles and complaints from MPEG-4
     // encoder due to not being monotonic.
     // If you change this please note the reason here!
-    blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, v_muxer_time + sub_offset);}
+    blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, v_muxer_time + sub_offset, MP_NOPTS_VALUE);}
     v_muxer_time = adjusted_muxer_time(mux_v); // update after muxing
 
     if (sh_video->vf_initialized < 0) mencoder_exit(1, NULL);
diff --git a/mplayer.c b/mplayer.c
index 3bffb9792..c620eb5ed 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -1777,6 +1777,7 @@ static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
     int in_size;
     int hit_eof = 0;
     double pts;
+    double endpts;
 
     while (1) {
         int drop_frame = 0;
@@ -1787,7 +1788,7 @@ static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
         if (vf_output_queued_frame(sh_video->vfilter))
             break;
         current_module = "video_read_frame";
-        in_size = ds_get_packet_pts(d_video, &start, &pts);
+        in_size = ds_get_packet_pts_endpts(d_video, &start, &pts, &endpts);
         if (in_size < 0) {
             // try to extract last frames in case of decoder lag
             in_size = 0;
@@ -1799,13 +1800,13 @@ static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
         if (in_size > max_framesize)
             max_framesize = in_size;
         current_module = "decode video";
-        decoded_frame  = decode_video(sh_video, start, in_size, drop_frame, pts, NULL);
+        decoded_frame  = decode_video(sh_video, start, in_size, drop_frame, pts, endpts, NULL);
         if (decoded_frame) {
             update_subtitles(sh_video, sh_video->pts, mpctx->d_sub, 0);
             update_teletext(sh_video, mpctx->demuxer, 0);
             update_osd_msg();
             current_module = "filter video";
-            if (filter_video(sh_video, decoded_frame, sh_video->pts))
+            if (filter_video(sh_video, decoded_frame, sh_video->pts, sh_video->endpts))
                 break;
         } else if (drop_frame)
             return -1;
@@ -2491,7 +2492,7 @@ static double update_video(int *blit_frame)
             // still frame has been reached, no need to decode
             if ((in_size > 0 || flush) && !decoded_frame)
             decoded_frame = decode_video(sh_video, start, in_size, drop_frame,
-                                         sh_video->pts, &full_frame);
+                                         sh_video->pts, sh_video->endpts, &full_frame);
 
             if (flush && !decoded_frame)
                 return -1;
@@ -2512,13 +2513,15 @@ static double update_video(int *blit_frame)
 
         current_module = "filter_video";
         *blit_frame    = (decoded_frame && filter_video(sh_video, decoded_frame,
-                                                        sh_video->pts));
+                                                        sh_video->pts, sh_video->endpts));
     } else {
         int res = generate_video_frame(sh_video, mpctx->d_video);
         if (!res)
             return -1;
         ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter,
                                                       VFCTRL_GET_PTS, &sh_video->pts);
+        ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter,
+                                                      VFCTRL_GET_ENDPTS, &sh_video->endpts);
         if (sh_video->pts == MP_NOPTS_VALUE) {
             mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_PtsAfterFiltersMissing);
             sh_video->pts = sh_video->last_pts;
@@ -3795,7 +3798,7 @@ goto_enable_cache:
                 update_osd_msg();
             } else {
                 int frame_time_remaining = 0;
-                int blit_frame = 1;
+                int blit_frame = mpctx->num_buffered_frames > 0;
                 // skip timing after seek
                 int skip_timing = mpctx->startup_decode_retry > 0;
 
@@ -3822,13 +3825,25 @@ goto_enable_cache:
                         goto goto_next_file;
                     }
                     if (frame_time < 0) {
+                        // try to figure out duration of last frame
+                        if (correct_pts && mpctx->sh_video->endpts != MP_NOPTS_VALUE &&
+                            mpctx->sh_video->pts != MP_NOPTS_VALUE &&
+                            mpctx->sh_video->endpts > mpctx->sh_video->pts) {
+                            frame_time = mpctx->sh_video->endpts - mpctx->sh_video->pts;
+                        } else {
+                            frame_time = mpctx->sh_video->frametime;
+                        }
+                        mpctx->sh_video->frametime = -1;
+                        mpctx->sh_video->endpts = MP_NOPTS_VALUE;
+                    }
+                    if (frame_time < 0) {
                         // if we have no more video, sleep some arbitrary time
                         frame_time = 1.0 / 20.0;
                         // Ensure vo_pts is updated so that ao_pcm will not hang.
                         advance_timer(frame_time);
                         // only stop playing when audio is at end as well
                         if (!mpctx->sh_audio || (mpctx->d_audio->eof && !ds_fill_buffer(mpctx->d_audio)))
-                            mpctx->eof = 1;
+                            mpctx->eof = mpctx->time_frame <= 0;
                     } else {
                         // might return with !eof && !blit_frame if !correct_pts
                         mpctx->num_buffered_frames += blit_frame;
-- 
2.11.0

_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@xxxxxxxxxxxx
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng