changeset 18917:d9a75b26da6c

Add a new video pts tracking mode, enabled by option -correct-pts. This mode has the following differences: - Video timing is correct for streams with B frames, at least with some demuxers. - Video filters can modify frame timestamps and insert new frames, and removing frames is handled better than before. - Some things are known to break, it's not usable as the default yet. Things should work as before when the -correct-pts option is not used.
author uau
date Thu, 06 Jul 2006 06:58:17 +0000
parents a95ed361d16b
children 58b4379d19b0
files cfg-mplayer.h libmpcodecs/dec_video.c libmpcodecs/dec_video.h libmpcodecs/vd.h libmpcodecs/vd_ffmpeg.c libmpcodecs/vf.c libmpcodecs/vf.h libmpcodecs/vf_tfields.c libmpcodecs/vf_vo.c libmpcodecs/vf_yadif.c libmpdemux/demux_mkv.c libmpdemux/demuxer.c libmpdemux/demuxer.h libmpdemux/stheader.h mplayer.c
diffstat 15 files changed, 252 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/cfg-mplayer.h	Thu Jul 06 05:05:00 2006 +0000
+++ b/cfg-mplayer.h	Thu Jul 06 06:58:17 2006 +0000
@@ -349,6 +349,8 @@
 	{"playlist", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL},
 
 	// a-v sync stuff:
+        {"correct-pts", &correct_pts, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+        {"no-correct-pts", &correct_pts, CONF_TYPE_FLAG, 0, 1, 0, NULL},
 	{"noautosync", &autosync, CONF_TYPE_FLAG, 0, 0, -1, NULL},
 	{"autosync", &autosync, CONF_TYPE_INT, CONF_RANGE, 0, 10000, NULL},
 //	{"dapsync", &dapsync, CONF_TYPE_FLAG, 0, 0, 1, NULL},
--- a/libmpcodecs/dec_video.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/dec_video.c	Thu Jul 06 06:58:17 2006 +0000
@@ -137,6 +137,18 @@
     if(mpvdec) mpvdec->control(sh_video, VDCTRL_RESYNC_STREAM, NULL);
 }
 
+int get_current_video_decoder_lag(sh_video_t *sh_video)
+{
+    int ret;
+
+    if (!mpvdec)
+	return -1;
+    ret = mpvdec->control(sh_video, VDCTRL_QUERY_UNSEEN_FRAMES, NULL);
+    if (ret >= 10)
+	return ret-10;
+    return -1;
+}
+
 void uninit_video(sh_video_t *sh_video){
     if(!sh_video->inited) return;
     mp_msg(MSGT_DECVIDEO,MSGL_V,MSGTR_UninitVideoStr,sh_video->codec->drv);
@@ -311,6 +323,36 @@
 double tt;
 int ret;
 
+ if (correct_pts) {
+     int delay = get_current_video_decoder_lag(sh_video);
+     if (delay >= 0) {
+	 if (delay > sh_video->num_buffered_pts)
+#if 0
+	     // this is disabled because vd_ffmpeg reports the same lag
+	     // after seek even when there are no buffered frames,
+	     // leading to incorrect error messages
+	     mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Not enough buffered pts\n");
+#else
+	 ;
+#endif
+	 else
+	     sh_video->num_buffered_pts = delay;
+     }
+     if (sh_video->num_buffered_pts ==
+	                     sizeof(sh_video->buffered_pts)/sizeof(double))
+	 mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Too many buffered pts\n");
+     else {
+	 int i, j;
+	 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--)
+	     sh_video->buffered_pts[j] = sh_video->buffered_pts[j-1];
+	 sh_video->buffered_pts[i] = pts;
+	 sh_video->num_buffered_pts++;
+     }
+ }
+
 //if(!(sh_video->ds->flags&1) || sh_video->ds->pack_no<5)
 mpi=mpvdec->decode(sh_video, start, in_size, drop_frame);
 
@@ -333,6 +375,11 @@
 
 if(!mpi || drop_frame) return 0; // error / skipped frame
 
+ if (correct_pts) {
+     sh_video->num_buffered_pts--;
+     pts = sh_video->buffered_pts[sh_video->num_buffered_pts];
+ }
+
 //vo_draw_image(video_out,mpi);
 vf=sh_video->vfilter;
 ret = vf->put_image(vf,mpi, pts); // apply video filters and call the leaf vo/ve
--- a/libmpcodecs/dec_video.h	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/dec_video.h	Thu Jul 06 06:58:17 2006 +0000
@@ -19,5 +19,6 @@
 extern int set_video_colors(sh_video_t *sh_video,char *item,int value);
 extern int set_rectangle(sh_video_t *sh_video,int param,int value);
 extern void resync_video_stream(sh_video_t *sh_video);
+extern int get_current_video_decoder_lag(sh_video_t *sh_video);
 
 extern int divx_quality;
--- a/libmpcodecs/vd.h	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vd.h	Thu Jul 06 06:58:17 2006 +0000
@@ -24,6 +24,7 @@
 #define VDCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
 #define VDCTRL_GET_EQUALIZER 7 /* get color options (brightness,contrast etc) */
 #define VDCTRL_RESYNC_STREAM 8 /* seeking */
+#define VDCTRL_QUERY_UNSEEN_FRAMES 9 /* current decoder lag */
 
 // callbacks:
 int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outfmt);
--- a/libmpcodecs/vd_ffmpeg.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vd_ffmpeg.c	Thu Jul 06 06:58:17 2006 +0000
@@ -188,7 +188,9 @@
     break;
     case VDCTRL_RESYNC_STREAM:
         avcodec_flush_buffers(avctx);
-    return CONTROL_TRUE;
+	return CONTROL_TRUE;
+    case VDCTRL_QUERY_UNSEEN_FRAMES:
+	return avctx->has_b_frames + 10;
     }
     return CONTROL_UNKNOWN;
 }
--- a/libmpcodecs/vf.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vf.c	Thu Jul 06 06:58:17 2006 +0000
@@ -558,6 +558,38 @@
 	dst->qscale= src->qscale;
     }
 }
+
+void vf_queue_frame(vf_instance_t *vf, int (*func)(vf_instance_t *))
+{
+    vf->continue_buffered_image = func;
+}
+
+// Output the next buffered image (if any) from the filter chain.
+// The queue could be kept as a simple stack/list instead avoiding the
+// looping here, but there's currently no good context variable where
+// that could be stored so this was easier to implement.
+
+int vf_output_queued_frame(vf_instance_t *vf)
+{
+    while (1) {
+	int ret;
+	vf_instance_t *current;
+	vf_instance_t *last=NULL;
+	int (*tmp)(vf_instance_t *);
+	for (current = vf; current; current = current->next)
+	    if (current->continue_buffered_image)
+		last = current;
+	if (!last)
+	    return 0;
+	tmp = last->continue_buffered_image;
+	last->continue_buffered_image = NULL;
+	ret = tmp(last);
+	if (ret)
+	    return ret;
+    }
+}
+
+
 /**
  * \brief Video config() function wrapper
  *
--- a/libmpcodecs/vf.h	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vf.h	Thu Jul 06 06:58:17 2006 +0000
@@ -43,6 +43,8 @@
     void (*draw_slice)(struct vf_instance_s* vf,
         unsigned char** src, int* stride, int w,int h, int x, int y);
     void (*uninit)(struct vf_instance_s* vf);
+
+    void (*continue_buffered_image)(struct vf_instance_s* vf);
     // caps:
     unsigned int default_caps; // used by default query_format()
     unsigned int default_reqs; // used by default config()
@@ -93,6 +95,8 @@
 
 unsigned int vf_match_csp(vf_instance_t** vfp,unsigned int* list,unsigned int preferred);
 void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src);
+void vf_queue_frame(vf_instance_t *vf, int (*)(vf_instance_t *));
+int vf_output_queued_frame(vf_instance_t *vf);
 
 // default wrappers:
 int vf_next_config(struct vf_instance_s* vf,
--- a/libmpcodecs/vf_tfields.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vf_tfields.c	Thu Jul 06 06:58:17 2006 +0000
@@ -15,6 +15,9 @@
 struct vf_priv_s {
 	int mode;
 	int parity;
+	int buffered_i;
+	mp_image_t *buffered_mpi;
+	double buffered_pts;
 };
 
 static inline void *my_memcpy_pic(void * dst, void * src, int bytesPerLine, int height, int dstStride, int srcStride)
@@ -311,9 +314,27 @@
 static void (*qpel_li)(unsigned char *d, unsigned char *s, int w, int h, int ds, int ss, int up);
 static void (*qpel_4tap)(unsigned char *d, unsigned char *s, int w, int h, int ds, int ss, int up);
 
+static int continue_buffered_image(struct vf_instance_s *);
+extern int correct_pts;
+
 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts)
 {
-	int i;
+	vf->priv->buffered_mpi = mpi;
+	vf->priv->buffered_pts = pts;
+	vf->priv->buffered_i = 0;
+	return continue_buffered_image(vf);
+}
+
+static int continue_buffered_image(struct vf_instance_s *vf)
+{
+	int i=vf->priv->buffered_i;
+	double pts = vf->priv->buffered_pts;
+	mp_image_t *mpi = vf->priv->buffered_mpi;
+
+	if (i == 0)
+		vf_queue_frame(vf, continue_buffered_image);
+	pts += i * .02;  // XXX not right
+
 	int ret=0;
 	mp_image_t *dmpi;
 	void (*qpel)(unsigned char *, unsigned char *, int, int, int, int, int);
@@ -344,7 +365,7 @@
 
 	switch (vf->priv->mode) {
 	case 0:
-		for (i=0; i<2; i++) {
+		for (; i<2; i++) {
 			dmpi = vf_get_image(vf->next, mpi->imgfmt,
 				MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
 				mpi->width, mpi->height/2);
@@ -356,12 +377,15 @@
 				dmpi->stride[1] = 2*mpi->stride[1];
 				dmpi->stride[2] = 2*mpi->stride[2];
 			}
-			ret |= vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
-			if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
+			ret |= vf_next_put_image(vf, dmpi, pts);
+			if (correct_pts)
+				break;
+			else
+				if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
 		}
 		break;
 	case 1:
-		for (i=0; i<2; i++) {
+		for (; i<2; i++) {
 			dmpi = vf_get_image(vf->next, mpi->imgfmt,
 				MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
 				mpi->width, mpi->height);
@@ -383,14 +407,17 @@
 				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, MP_NOPTS_VALUE);
-			if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
+			ret |= vf_next_put_image(vf, dmpi, pts);
+			if (correct_pts)
+				break;
+			else
+				if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
 		}
 		break;
 	case 2:
 	case 3:
 	case 4:
-		for (i=0; i<2; i++) {
+		for (; i<2; i++) {
 			dmpi = vf_get_image(vf->next, mpi->imgfmt,
 				MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
 				mpi->width, mpi->height/2);
@@ -406,11 +433,15 @@
 					mpi->chroma_width, mpi->chroma_height/2,
 					dmpi->stride[2], mpi->stride[2]*2, (i^!tff));
 			}
-			ret |= vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
-			if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
+			ret |= vf_next_put_image(vf, dmpi, pts);
+			if (correct_pts)
+				break;
+			else
+				if (!i) vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
 		}
 		break;
 	}
+	vf->priv->buffered_i = 1;
 	return ret;
 }
 
--- a/libmpcodecs/vf_vo.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vf_vo.c	Thu Jul 06 06:58:17 2006 +0000
@@ -12,7 +12,8 @@
 
 //===========================================================================//
 
-#define video_out ((vo_functions_t*)(vf->priv))
+struct priv_t {double pts; vo_functions_t *vo;};
+#define video_out (((struct priv_t *)(vf->priv))->vo)
 
 static int query_format(struct vf_instance_s* vf, unsigned int fmt); /* forward declaration */
 
@@ -102,6 +103,8 @@
 static int put_image(struct vf_instance_s* vf,
         mp_image_t *mpi, double pts){
   if(!vo_config_count) return 0; // vo not configured?
+  // record pts (potentially modified by filters) for main loop
+  ((struct priv_t *)vf->priv)->pts = pts;
   // 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:
--- a/libmpcodecs/vf_yadif.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpcodecs/vf_yadif.c	Thu Jul 06 06:58:17 2006 +0000
@@ -47,6 +47,10 @@
 struct vf_priv_s {
     int mode;
     int parity;
+    int buffered_i;
+    int buffered_tff;
+    double buffered_pts;
+    mp_image_t *buffered_mpi;
     int stride[3];
     uint8_t *ref[4][3];
 };
@@ -150,10 +154,11 @@
 	return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
 }
 
+static int continue_buffered_image(struct vf_instance_s *vf);
+extern int correct_pts;
+
 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
-    mp_image_t *dmpi;
-    int ret=0;
-    int tff, i;
+    int tff;
 
     if(vf->priv->parity < 0) {
         if (mpi->fields & MP_IMGFIELD_ORDERED)
@@ -165,18 +170,41 @@
 
     store_ref(vf->priv, mpi->planes, mpi->stride, mpi->w, mpi->h);
 
-    for(i=0; i<=(vf->priv->mode&1); i++){
+    vf->priv->buffered_mpi = mpi;
+    vf->priv->buffered_tff = tff;
+    vf->priv->buffered_i = 0;
+    vf->priv->buffered_pts = pts;
+
+    return continue_buffered_image(vf);
+}
+
+static int continue_buffered_image(struct vf_instance_s *vf)
+{
+    mp_image_t *mpi = vf->priv->buffered_mpi;
+    int tff = vf->priv->buffered_tff;
+    double pts = vf->priv->buffered_pts;
+    int i;
+    int ret=0;
+    mp_image_t *dmpi;
+
+    pts += vf->priv->buffered_i * .02; // XXX not right
+
+    for(i = vf->priv->buffered_i; i<=(vf->priv->mode&1); i++){
         dmpi=vf_get_image(vf->next,mpi->imgfmt,
             MP_IMGTYPE_TEMP,
             MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
             mpi->width,mpi->height);
         vf_clone_mpi_attributes(dmpi, mpi);
         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*/);
+        if (correct_pts)
+            break;
         if(i<(vf->priv->mode&1))
             vf_next_control(vf, VFCTRL_FLIP_PAGE, NULL);
     }
-
+    vf->priv->buffered_i = 1;
     return ret;
 }
 
--- a/libmpdemux/demux_mkv.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpdemux/demux_mkv.c	Thu Jul 06 06:58:17 2006 +0000
@@ -1690,12 +1690,12 @@
       else if (!strcmp(track->codec_id, MKV_V_MPEG1))
         {
           bih->biCompression = mmioFOURCC('m', 'p', 'g', '1');
-          track->reorder_timecodes = 1;
+          track->reorder_timecodes = !correct_pts;
         }
       else if (!strcmp(track->codec_id, MKV_V_MPEG2))
         {
           bih->biCompression = mmioFOURCC('m', 'p', 'g', '2');
-          track->reorder_timecodes = 1;
+          track->reorder_timecodes = !correct_pts;
         }
       else if (!strcmp(track->codec_id, MKV_V_MPEG4_AVC))
         {
@@ -1706,7 +1706,7 @@
               bih = (BITMAPINFOHEADER *) realloc (bih, bih->biSize);
               memcpy (bih + 1, track->private_data, track->private_size);
             }
-          track->reorder_timecodes = 1;
+          track->reorder_timecodes = !correct_pts;
         }
       else
         {
--- a/libmpdemux/demuxer.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpdemux/demuxer.c	Thu Jul 06 06:58:17 2006 +0000
@@ -355,7 +355,7 @@
       ds->pos=p->pos;
       ds->dpos+=p->len; // !!!
       ++ds->pack_no;
-      if(p->pts){
+      if (p->pts != (correct_pts ? MP_NOPTS_VALUE : 0)) {
         ds->pts=p->pts;
         ds->pts_bytes=0;
       }
@@ -511,10 +511,11 @@
             *start = NULL;
             return -1;
 	}
-	// Should use MP_NOPTS_VALUE for "unknown pts" in the packets too
-	if (ds->current->pts)
-	    *pts = ds->current->pts;
     }
+    // Should use MP_NOPTS_VALUE for "unknown pts" in the packets too
+    // Return pts unless this read starts from the middle of a packet
+    if (!ds->buffer_pos && (correct_pts || ds->current->pts))
+	*pts = ds->current->pts;
     len=ds->buffer_size-ds->buffer_pos;
     *start = &ds->buffer[ds->buffer_pos];
     ds->buffer_pos+=len;
@@ -624,6 +625,8 @@
 
 int extension_parsing=1; // 0=off 1=mixed (used only for unstable formats)
 
+int correct_pts=0;
+
 /*
   NOTE : Several demuxers may be opened at the same time so
   demuxers should NEVER rely on an external var to enable them
--- a/libmpdemux/demuxer.h	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpdemux/demuxer.h	Thu Jul 06 06:58:17 2006 +0000
@@ -126,6 +126,8 @@
 
 struct demuxer_st;
 
+extern int correct_pts;
+
 /**
  * Demuxer description structure
  */
@@ -182,7 +184,9 @@
   demux_packet_t* dp=(demux_packet_t*)malloc(sizeof(demux_packet_t));
   dp->len=len;
   dp->next=NULL;
-  dp->pts=0;
+  // still using 0 by default in case there is some code that uses 0 for both
+  // unknown and a valid pts value
+  dp->pts=correct_pts ? MP_NOPTS_VALUE : 0;
   dp->pos=0;
   dp->flags=0;
   dp->refcount=1;
--- a/libmpdemux/stheader.h	Thu Jul 06 05:05:00 2006 +0000
+++ b/libmpdemux/stheader.h	Thu Jul 06 06:58:17 2006 +0000
@@ -64,6 +64,8 @@
   // timing (mostly for mpeg):
   double pts;     // predicted/interpolated PTS of the current frame
   double i_pts;   // PTS for the _next_ I/P frame
+  double buffered_pts[20];
+  int num_buffered_pts;
   // output format: (set by demuxer)
   float fps;              // frames per second (set only if constant fps)
   float frametime;        // 1/fps
--- a/mplayer.c	Thu Jul 06 05:05:00 2006 +0000
+++ b/mplayer.c	Thu Jul 06 06:58:17 2006 +0000
@@ -2466,6 +2466,40 @@
 }
 
 
+static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video)
+{
+    unsigned char *start;
+    int in_size;
+    int hit_eof=0;
+    double pts;
+
+    while (1) {
+	current_module = "decode video";
+	// XXX Time used in this call is not counted in any performance
+	// timer now
+	if (vf_output_queued_frame(sh_video->vfilter))
+	    break;
+	current_module = "video_read_frame";
+	in_size = ds_get_packet_pts(d_video, &start, &pts);
+	if (in_size < 0) {
+	    // try to extract last frames in case of decoder lag
+	    in_size = 0;
+	    pts = 1e300;
+	    hit_eof = 1;
+	}
+	if (in_size > max_framesize)
+	    max_framesize = in_size;
+	if (pts == MP_NOPTS_VALUE)
+	    mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts value from demuxer MISSING\n");
+	if (decode_video(sh_video, start, in_size, 0, pts))
+	    break;
+	if (hit_eof)
+	    return 0;
+    }
+    return 1;
+}
+
+
 int main(int argc,char* argv[]){
 
 
@@ -3505,9 +3539,11 @@
 inited_flags|=INITED_VO;
 }
 
+struct {double pts; vo_functions_t *vo;} vf_vo_data;
+vf_vo_data.vo = video_out;
 current_module="init_video_filters";
 {
-  char* vf_arg[] = { "_oldargs_", (char*)video_out , NULL };
+  char* vf_arg[] = { "_oldargs_", (char*)&vf_vo_data , NULL };
   sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg);
 }
 #ifdef HAVE_MENU
@@ -3594,6 +3630,7 @@
 //float v_frame=0;    // Video
 float time_frame=0; // Timer
 //float num_frames=0;      // number of frames played
+double last_pts = MP_NOPTS_VALUE;
 int grab_frames=0;
 int drop_frame=0;     // current dropping status
 int dropped_frames=0; // how many frames dropped since last non-dropped frame
@@ -3768,7 +3805,7 @@
     //--------------------  Decode a frame: -----------------------
     blit_frame = 0; // Don't blit if we hit EOF
     vdecode_time=video_time_usage;
-    while(1)
+    if (!correct_pts) while(1)
     {   unsigned char* start=NULL;
 	int in_size;
 	// get it!
@@ -3803,6 +3840,32 @@
 	blit_frame=decode_video(sh_video,start,in_size,drop_frame, MP_NOPTS_VALUE);
 	break;
     }
+    else while (1) {
+	if (!generate_video_frame(sh_video, d_video)) {
+	    eof = 1;
+	    break;
+	}
+	sh_video->pts = vf_vo_data.pts;
+	if (sh_video->pts == MP_NOPTS_VALUE) {
+	    mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts after filters MISSING\n");
+	    sh_video->pts == last_pts;
+	}
+	if (last_pts == MP_NOPTS_VALUE)
+	    last_pts = sh_video->pts;
+	else if (last_pts >= sh_video->pts) {
+	    last_pts = sh_video->pts;
+	    mp_msg(MSGT_CPLAYER, MSGL_WARN, "pts value <= previous");
+	}
+	frame_time = sh_video->pts - last_pts;
+	last_pts = sh_video->pts;
+	sh_video->timer += frame_time;
+	time_frame += frame_time;  // for nosound
+	if(sh_audio)
+	    sh_audio->delay -= frame_time;
+	blit_frame = 1;
+	break;
+    }
+	
     vdecode_time=video_time_usage-vdecode_time;
     //------------------------ frame decoded. --------------------
 
@@ -4728,6 +4791,8 @@
 	 current_module="seek_video_reset";
          resync_video_stream(sh_video);
          if(vo_config_count) video_out->control(VOCTRL_RESET,NULL);
+	 sh_video->num_buffered_pts = 0;
+	 last_pts = MP_NOPTS_VALUE;
       }
       
       if(sh_audio){