diff libmpcodecs/dec_video.c @ 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 e60c8c7399d2
children 39d8fd7e7543
line wrap: on
line diff
--- 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