[Mplayer-cvslog] CVS: main/libvo vo_dxr3.c,1.112,1.113

David Holm CVS mswitch at mplayerhq.hu
Wed Nov 27 00:32:47 CET 2002


Update of /cvsroot/mplayer/main/libvo
In directory mail:/var/tmp.root/cvs-serv32014/libvo

Modified Files:
	vo_dxr3.c 
Log Message:
10l found by Zoltan


Index: vo_dxr3.c
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/vo_dxr3.c,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -r1.112 -r1.113
--- vo_dxr3.c	26 Nov 2002 23:23:17 -0000	1.112
+++ vo_dxr3.c	26 Nov 2002 23:32:43 -0000	1.113
@@ -6,11 +6,11 @@
  */
 
 /* ChangeLog added 2002-01-10
- * 2002-01-03:
+ * 2002-11-03:
  *  Cleaned up syncing code and renamed setup variables so
  *   they can be accessed from the GUI.
  *
- * 2002-01-02:
+ * 2002-11-02:
  *  Added native overlay support, activate with :overlay
  *   you have to run dxr3view to modify settings (or manually
  *   edit the files in ~/.overlay.
@@ -95,7 +95,11 @@
  *  find any inconcistencies.
  */
  
+#ifdef __FreeBSD__
+#include <em8300.h>
+#else
 #include <linux/em8300.h>
+#endif
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -243,8 +247,28 @@
 #endif
 
 
+/* Internal variables used in syncing */
+static int last_pts, frame_last_pts = -1;
+static int64_t pts64;
+static int64_t frame_pts64;
+#define RESYNC_WINDOW_SIZE 50
+static int resync_window = 0;
+#define SKIP_TOLERANCE 200
+static int skip_count = 0;
+
+
 /* Functions for working with the em8300's internal clock */
-/* End of internal clock functions */
+struct {
+	int64_t	offset;
+	uint32_t last_pts;
+} scr_s;
+
+static void scr_reset();
+static void scr_start(int64_t vpts);
+static int64_t scr_get_time();
+static void scr_adjust(int64_t vpts);
+
+
 
 static uint32_t control(uint32_t request, void *data, ...)
 {
@@ -279,37 +303,38 @@
 #endif
 	case VOCTRL_RESUME:
 		if (dxr3_newsync) {
-			ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
-			pts_offset = vo_pts - (ioval << 1);
-			if (pts_offset < 0) {
+			pts_offset = vo_pts - scr_get_time();
+			if (pts_offset < 0) {	
 				pts_offset = 0;
 			}
 		}
-		
+				
 		if (dxr3_prebuf) {
-			ioval = EM8300_PLAYMODE_PLAY;
+			/*frame_last_pts = -1;
+			last_pts = vo_pts;
+			scr_adjust(pts64);*/
+			/*ioval = EM8300_PLAYMODE_PLAY;
 			if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
 				printf("VO: [dxr3] Unable to set playmode!\n");
-			}
+			}*/
 		}
 		return VO_TRUE;
 	case VOCTRL_PAUSE:
 		if (dxr3_prebuf) {
+			/* Pausing will also stop the internal clock, avoid it
 			ioval = EM8300_PLAYMODE_PAUSED;
 			if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
 				printf("VO: [dxr3] Unable to set playmode!\n");
-			}
+			}*/
 		}
 		return VO_TRUE;
 	case VOCTRL_RESET:
-		if (dxr3_prebuf) {
-			close(fd_video);
-			fd_video = open(fdv_name, O_WRONLY);
-			close(fd_spu);
-			fd_spu = open(fds_name, O_WRONLY);
-			fsync(fd_video);
-			fsync(fd_spu);
-		}
+		close(fd_video);
+		fd_video = open(fdv_name, O_WRONLY);
+		close(fd_spu);
+		fd_spu = open(fds_name, O_WRONLY);
+		fsync(fd_video);
+		fsync(fd_spu);
 		return VO_TRUE;
 	case VOCTRL_QUERY_FORMAT:
 	    {
@@ -319,8 +344,8 @@
 		    return 0;
 
 		flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
-		if (dxr3_prebuf)
-		    flag |= VFCAP_TIMER;
+		/*if (dxr3_prebuf)
+		    flag |= VFCAP_TIMER;*/
 		return flag;
 	    }
 	case VOCTRL_SET_EQUALIZER:
@@ -393,7 +418,7 @@
 
 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
 {
-	int tmp1, tmp2, size;
+	int tmp1, tmp2;
 	em8300_register_t reg;
 	extern float monitor_aspect;
 
@@ -409,11 +434,7 @@
 	}
 
 	/* Set the playmode to play (just in case another app has set it to something else) */
-#ifdef EM8300_PLAYMODE_SYNC
-	ioval = EM8300_PLAYMODE_SYNC;
-#else
 	ioval = EM8300_PLAYMODE_PLAY;
-#endif
 	if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
 		printf("VO: [dxr3] Unable to set playmode!\n");
 	}
@@ -422,7 +443,7 @@
 #ifdef MVCOMMAND_SYNC
 	reg.microcode_register = 1;
 	reg.reg = 0;
-	reg.val = MVCOMMAND_START;
+	reg.val = MVCOMMAND_SYNC;
 	ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
 #endif
 
@@ -524,11 +545,7 @@
 		unsigned long xswamask;
 		Colormap cmap;
 		XColor key_color;
-		Window junkwindow;
-		Screen *scr;
 		int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
-		em8300_overlay_screen_t ovlscr;
-		em8300_attribute_t ovlattr;
 
 		vo_dx = (vo_screenwidth - d_width) / 2;
 		vo_dy = (vo_screenheight - d_height) / 2;
@@ -563,10 +580,10 @@
 			hint.base_height = hint.height = vo_dheight;
 			hint.flags = PPosition | PSize;
 			vo_window = XCreateWindow(mDisplay, mRootWin, hint.x, hint.y, hint.width, hint.height, 0, depth, CopyFromParent, vinfo.visual, xswamask, &xswa);
-			vo_x11_classhint(mDisplay, vo_window, "Viewing Window");
+			vo_x11_classhint(mDisplay, vo_window, "DXR3 Overlay");
 			vo_hidecursor(mDisplay, vo_window);
 			vo_x11_selectinput_witherr(mDisplay, vo_window, StructureNotifyMask | KeyPressMask | PropertyChangeMask);
-			XSetStandardProperties(mDisplay, vo_window, "DXR3 Overlay", "DXR3 Overlay", None, NULL, 0, &hint);
+			XSetStandardProperties(mDisplay, vo_window, title, title, None, NULL, 0, &hint);
 			XSetWMNormalHints(mDisplay, vo_window, &hint);
 			XMapWindow(mDisplay, vo_window);
 			XFlush(mDisplay);
@@ -598,7 +615,7 @@
 		
 		acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
 		if (key_color.pixel != KEY_COLOR) {
-			printf("VO: [dxr3] Unable to allocate exact keycolor, using closest match (%0x)\n", key_color.pixel);	
+			printf("VO: [dxr3] Unable to allocate exact keycolor, using closest match (%0x)\n", (unsigned int) key_color.pixel);
 		}
 		
 		/* Set keycolor and activate overlay */
@@ -610,6 +627,25 @@
 	}
 #endif
 
+	/* Set up timers 
+	 * This must be the last thing we do otherwise the
+	 * timers will be off when we start sending frames
+	 * causing a resync the first thing we do, which
+	 * hopefully isn't necessary.
+	 */
+	last_pts = vo_pts;
+	scr_reset();
+	frame_pts64 = pts64 = vo_pts;
+	scr_start(pts64);
+	
+	if (dxr3_newsync) {
+		ioval = scr_get_time();
+		pts_offset = vo_pts - ioval;
+		if (pts_offset < 0) {
+			pts_offset = 0;
+		}
+	}
+	
 	return 0;
 }
 
@@ -683,23 +719,117 @@
 #endif
 }
 
-
 static uint32_t draw_frame(uint8_t * src[])
 {
 	vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
-
+	unsigned int pts;
+	uint8_t *c = p->data;
+	
 #ifdef SPU_SUPPORT
+	/* This is just a subpic, don't mess with timestamps */
 	if (p->id == 0x20) {
 		write(fd_spu, p->data, p->size);
-	} else
+		return 0;
+	}
 #endif
-		write(fd_video, p->data, p->size);
+
+	/* If seek occured, reset device */
+	if (vo_pts <= 0) {
+		printf("Something happened, reset\n");
+		control(VOCTRL_RESET, NULL);
+		frame_last_pts = -1;
+		scr_adjust(frame_pts64);
+	}
+	
+	/* Update frame timestamp */
+    	if (frame_last_pts < 0) {
+		frame_last_pts = p->timestamp;
+	}
+	frame_pts64 += p->timestamp - frame_last_pts;
+
+	if (dxr3_prebuf) {
+		int64_t delay = frame_pts64 - scr_get_time();
+		
+		if ((delay > 0) && (delay < 90000)) {
+			/* Frame is in sync with the em8300 */
+			uint32_t vpts32 = frame_pts64;
+			
+			if (resync_window == 0) {
+				/* Video has been synced, lock the
+				 * stream by activating the em8300
+				 * syncer.
+				 */
+				em8300_register_t reg;
+				printf("Video synced, lock stream\n");
+	    			reg.microcode_register = 1;
+				reg.reg = 0;
+			    	reg.val = MVCOMMAND_SYNC;
+				if (ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg) < 0) {
+					printf("VO: [dxr3] Unable to lock stream!\n");
+				}
+				resync_window = -RESYNC_WINDOW_SIZE;
+			}
+			
+			if (resync_window != 0 && resync_window > -RESYNC_WINDOW_SIZE) {
+				resync_window--;
+			}
+
+			if (ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vpts32) < 0) {
+				printf("VO: [dxr3] Unable to set video pts!\n");
+			}
+			/* Do some cpu throttling to avoid killing the cpu */
+			//usleep((delay / 0.09) / 2);
+		} else if (delay < 0) {
+			/* We are behind, count frames and start resync
+			 * if this goes on for too long.
+			 */
+			skip_count++;
+			if (skip_count > SKIP_TOLERANCE) {
+				scr_adjust(frame_pts64);
+				skip_count = 0;
+				resync_window = 0;
+			}
+			
+			if (resync_window == 0) {
+				/* Sync was lost, unlock the stream
+				 * and start recalibration
+				 */
+				em8300_register_t reg;
+				printf("Sync lost, unlock stream\n");
+    				reg.microcode_register = 1;
+				reg.reg = 0;
+		    		reg.val = MVCOMMAND_START;
+				if (ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg) < 0) {
+					printf("VO: [dxr3] Unable to release stream!\n");
+				}
+				resync_window = RESYNC_WINDOW_SIZE;
+			}
+			if ((resync_window) != 0 && (resync_window < RESYNC_WINDOW_SIZE)) {
+				resync_window++;
+			}
+		} else if (delay >= 90000) {
+			printf("VO: [dxr3] Warning, pts is %.02f seconds ahead of time!\n", delay / 90000.0);
+		}
+	}
+	
+	if (write(fd_video, p->data, p->size) < p->size) {
+		printf("VO: [dxr3] Lost some bytes\n");
+	}
+	
+	frame_last_pts = p->timestamp;
+
 	return 0;
 }
 
 static void flip_page(void)
 {
 #ifdef HAVE_X11
+	/* Update current timestamp */
+	if (vo_pts <= 0) {
+		last_pts = vo_pts;
+	}
+	pts64 += vo_pts - last_pts;
+	
 	if (dxr3_overlay) {
 		int event = vo_x11_check_events(mDisplay);
 		if (event & VO_EVENT_RESIZE) {
@@ -720,29 +850,22 @@
 #endif
 
 	if (dxr3_newsync) {
-		ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
-		ioval <<= 1;
+		ioval = scr_get_time();
 		if (vo_pts == 0) {
 			ioval = 0;
-			ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
+			scr_adjust(pts64);
 			pts_offset = 0;
 		} else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
-			ioval = (vo_pts + pts_offset) >> 1;
-	    		ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
-			ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
-			pts_offset = vo_pts - (ioval << 1);
-			if (pts_offset < 0) {
-				pts_offset = 0;
-			}
+			ioval = vo_pts + pts_offset;
+			scr_adjust(ioval);
 		}
 		ioval = vo_pts + pts_offset;
 		ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
 		ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
 		prev_pts = vo_pts;
-	} else if (dxr3_prebuf) {
-		ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
-		ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
 	}
+
+	last_pts = vo_pts;
 }
 
 static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
@@ -918,16 +1041,84 @@
 	}
 #endif
 
-	if (dxr3_newsync) {
-		ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
-		pts_offset = vo_pts - (ioval << 1);
-		if (pts_offset < 0) {
-			pts_offset = 0;
-		}
+	return 0;
+}
+
+
+/* em8300 clock handler */
+static void scr_reset()
+{
+	scr_s.last_pts = 0;
+	scr_s.offset = 0;
+}
+
+static void scr_start(int64_t vpts)
+{
+	uint32_t vpts32 = vpts >> 1;
+	
+	scr_s.last_pts = vpts32;
+	scr_s.offset = vpts - ((int64_t) vpts32 << 1);
+	
+	if (ioctl(fd_control, EM8300_IOCTL_SCR_SET, &vpts32) < 0) {
+		printf("VO: [dxr3] Unable to set scr!\n");
+	}
+	
+	vpts32 = 0x900;
+	if (ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &vpts32) < 0) {
+		printf("VO: [dxr3] Unable to set em8300 clockspeed!\n");
 	}
+}
 
-	return 0;
+static int64_t scr_get_time()
+{
+	uint32_t pts;
+	int64_t current;
+	
+	if (ioctl(fd_control, EM8300_IOCTL_SCR_GET, &pts) < 0) {
+		printf("VO: [dxr3] Unable to get scr!\n");
+	}
+
+	if (scr_s.last_pts > 0xf0000000 && pts < 0x10000000) {
+		scr_s.offset += (int64_t) 1 << 33;
+	}
+
+	if (pts == 0) {
+		printf("VO: [dxr3] Warning, returned pts is 0!\n");
+	}
+
+	scr_s.last_pts = pts;
+	current = ((int64_t) pts << 1) + scr_s.offset;
+
+	return current;
+}
+
+static void scr_adjust(int64_t vpts)
+{
+	uint32_t current_pts32;
+	int32_t offset32;
+	
+	if (ioctl(fd_control, EM8300_IOCTL_SCR_GET, &current_pts32) < 0) {
+		printf("VO: [dxr3] Unable to get scr!\n");
+	}
+	
+	scr_s.last_pts = current_pts32;
+	scr_s.offset = vpts - ((int64_t) current_pts32 << 1);
+	offset32 = scr_s.offset / 4;
+	
+	if (offset32 < (-7200 / 4) || offset32 > (7200 / 4)) {
+		uint32_t vpts32 = vpts >> 1;
+
+		if (ioctl(fd_control, EM8300_IOCTL_SCR_SET, &vpts32) < 0) {
+			printf("VO: [dxr3] Unable to set scr!\n");
+		}
+		
+		scr_s.last_pts = vpts32;
+		scr_s.offset = vpts - ((int64_t) vpts32 << 1);
+	}
 }
+/* End of em8300 clock handler */
+
+
 
 /* Begin overlay.c */
 static int update_parameters(overlay_t *o)




More information about the MPlayer-cvslog mailing list