changeset 4218:3931c41f740a

Added new syncengine thanks to a new previously undocumented feature of the em8300, this might fix playback on both slow and fast machines (more testing needed). This also requires users to get the em8300 driver from cvs until the next version is released (will probably happen this weekend) Added lots of comments, should be pretty easy to understand most of the internals now Added lots of brackets to if's for's while's etc, this is not a cosmetical thing but rather due to the fact I got some very odd bugs with else's since I didn't properly use brackets (and it's the K&R standard to have brackets everywhere) Fixed some bugs that would occur when disabling libmp1e Switched to default to the new naming scheme of device nodes, the driver will slowly switch over to this state, if it can't find devices under the new name it will try the old naming scheme I stopped opening devices in non-blocking mode, it would break the new syncengine which tries to burst data to the device (alot of times meaning it will fill the fifo pretty fast which would previously result in jerkyness on fast machines) The device now sets the initial state of the pts and speed (probably not needed, but assumption is the mother of all fuckups =) Keep the control interface open during the entire duration of the libvo device, we might need this to flush video buffers on seeking (currently not implemented, therefore seeking is broken) This is beta stuff to the driver, I will get some users to test it for me and do my best to fix seeking as soon as possible...
author mswitch
date Thu, 17 Jan 2002 10:33:47 +0000
parents 2b141fcd69dd
children 70888f501b4a
files libvo/vo_dxr3.c
diffstat 1 files changed, 177 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_dxr3.c	Thu Jan 17 09:32:22 2002 +0000
+++ b/libvo/vo_dxr3.c	Thu Jan 17 10:33:47 2002 +0000
@@ -6,6 +6,13 @@
  */
 
 /* ChangeLog added 2002-01-10
+ * 2002-01-17:
+ *  Testrelease of new sync engine (using previously undocumented feature of em8300). Seeking does not work with this one!
+ *
+ * 2002-01-15:
+ *  Preliminary subpic support with -vc mpegpes and dvd's
+ *  Device interfaces tries the new naming scheme by default (even though most users probably still use the old one)
+ *
  * 2002-01-10:
  *  I rehauled the entire codebase. I have now changed to
  *  Kernighan & Ritchie codingstyle, please mail me if you 
@@ -43,14 +50,14 @@
 
 #ifdef USE_MP1E
 /* libmp1e specific stuff */
-rte_context *mp1e_context = NULL;
-rte_codec *mp1e_codec = NULL;
-rte_buffer mp1e_buffer;
-#endif
+static rte_context *mp1e_context = NULL;
+static rte_codec *mp1e_codec = NULL;
+static rte_buffer mp1e_buffer;
 
 /* Color buffer data used with libmp1e */
 static unsigned char *picture_data[3];
-static unsigned int picture_linesize[3];
+static int picture_linesize[3];
+#endif
 
 /* Resolutions and positions */
 static int v_width, v_height;
@@ -78,65 +85,91 @@
 };
 
 #ifdef USE_MP1E
-void write_dxr3(rte_context* context, void* data, size_t size, void* user_data)
+void write_dxr3(rte_context *context, void *data, size_t size, void *user_data)
 {
 	size_t data_left = size;
 	/* Set the timestamp of the next video packet */
-	if (ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts) < 0)
+	if (ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts) < 0) {
 		printf("VO: [dxr3] Unable to set pts\n");
+	}
 	
-	/* Write the entire video packet */
-	while (data_left)
+	/* Force data into the buffer */
+	while (data_left) {
 		data_left -= write(fd_video, (void*) data + (size - data_left), data_left);
+	}
 }
 #endif
 
-extern int vidmode;
-
 static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, uint32_t height, uint32_t fullscreen, char *title, uint32_t format)
 {
-	int tmp1,tmp2;
+	int tmp1, tmp2;
+	em8300_register_t reg;
 	char devname[80];
 	
 	/* Open the control interface */
-	if (vo_subdevice)
+	if (vo_subdevice) {
 		sprintf(devname, "/dev/em8300-%s", vo_subdevice);
-	else
-		sprintf(devname, "/dev/em8300");
+	} else {
+		/* Try new naming scheme by default */
+		sprintf(devname, "/dev/em8300-0");
+	}
 	fd_control = open(devname, O_WRONLY);
 	if (fd_control < 1) {
-		printf("VO: [dxr3] Error opening %s for writing!\n", devname);
-		return -1;
+		/* Fall back to old naming scheme */
+		printf("VO: [dxr3] Error opening %s for writing, trying /dev/em8300 instead\n", devname);
+		sprintf(devname, "/dev/em8300");
+		fd_control = open(devname, O_WRONLY);
+		if (fd_control < 1) {
+			printf("VO: [dxr3] Error opening /dev/em8300 for writing as well!\nBailing\n");
+			return -1;
+		}
 	}
 
-	/* Open the video packet interface */
-	if (vo_subdevice)
+	/* Open the video interface */
+	if (vo_subdevice) {
 		sprintf(devname, "/dev/em8300_mv-%s", vo_subdevice);
-	else
-		sprintf(devname, "/dev/em8300_mv");
-	fd_video = open(devname, O_WRONLY | O_NONBLOCK);
+	} else {
+		/* Try new naming scheme by default */
+		sprintf(devname, "/dev/em8300_mv-0");
+	}
+	fd_video = open(devname, O_WRONLY);
 	if (fd_video < 0) {
-		printf("VO: [dxr3] Error opening %s for writing!\n", devname);
-		uninit();
-		return -1;
-	} else
+		/* Fall back to old naming scheme */
+		printf("VO: [dxr3] Error opening %s for writing, trying /dev/em8300_mv instead\n", devname);
+		sprintf(devname, "/dev/em8300_mv");
+		fd_video = open(devname, O_WRONLY);
+		if (fd_video < 0) {
+			printf("VO: [dxr3] Error opening /dev/em8300_mv for writing as well!\nBailing\n");
+			uninit();
+			return -1;
+		}
+	} else {
 		printf("VO: [dxr3] Opened %s\n", devname);
-
-	/* Open the subpicture packet interface */
-	if (vo_subdevice)
+	}
+	
+	/* Open the subpicture interface */
+	if (vo_subdevice) {
 		sprintf(devname, "/dev/em8300_sp-%s", vo_subdevice);
-	else
-		sprintf(devname, "/dev/em8300_sp");
+	} else {
+		/* Try new naming scheme by default */
+		sprintf(devname, "/dev/em8300_sp-0");
+	}
 	fd_spu = open(devname, O_WRONLY);
 	if (fd_spu < 0) {
-		printf("VO: [dxr3] Error opening %s for writing!\n", devname);
-		uninit();
-		return -1;
+		/* Fall back to old naming scheme */
+		printf("VO: [dxr3] Error opening %s for writing, trying /dev/em8300_sp instead\n", devname);
+		sprintf(devname, "/dev/em8300_sp");
+		fd_spu = open(devname, O_WRONLY);
+		if (fd_spu < 0) {
+			printf("VO: [dxr3] Error opening /dev/em8300_sp for writing as well!\nBailing\n");
+			uninit();
+			return -1;
+		}
 	}
     
-	/* Subpic code isn't working yet, don't set to ON 
-	 * unless you are really sure what you are doing 
-	 */
+	/* This activates the subpicture processor, you can safely disable this and still send */
+	/* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
+	/* up in a lockup */
 	ioval = EM8300_SPUMODE_ON;
 	if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
 		printf("VO: [dxr3] Unable to set subpicture mode!\n");
@@ -146,9 +179,21 @@
 
 	/* Set the playmode to play (just in case another app has set it to something else) */
 	ioval = EM8300_PLAYMODE_PLAY;
-	if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0)
+	if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
 		printf("VO: [dxr3] Unable to set playmode!\n");
-    
+	}
+	
+	/* Set start pts and speed */
+	ioctl(fd_control, EM8300_IOCTL_SCR_SET, &vo_pts);
+	ioval = 0x900;
+	ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
+	/* Start em8300 prebuffering and sync engine */
+	reg.microcode_register = 1;
+	reg.reg = 0;
+	reg.val = MVCOMMAND_SYNC;
+	ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
+
+	/* Store some variables statically that we need later in another scope */
 	img_format = format;
 	v_width = scr_width;
 	v_height = scr_height;
@@ -160,6 +205,7 @@
 	s_height *= 16;
     
 	/* Try to figure out whether to use widescreen output or not */
+	/* Anamorphic widescreen modes makes this a pain in the ass */
 	tmp1 = abs(height - ((width / 4) * 3));
 	tmp2 = abs(height - (int) (width / 2.35));
 	if (tmp1 < tmp2) {
@@ -170,7 +216,6 @@
 		printf("VO: [dxr3] Setting aspect ratio to 16:9\n");
 	}
 	ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
-	close(fd_control);
     
 	if (format == IMGFMT_YV12 || format == IMGFMT_YUY2 || format == IMGFMT_BGR24) {
 #ifdef USE_MP1E
@@ -196,6 +241,7 @@
 			return -1;
 		}
 	
+		/* I wonder if we could benefit from using mpeg2 em8300-wise (hardware processing) */
 		if (!rte_set_format(mp1e_context, "mpeg1")) {
 			printf("VO: [dxr3] Unable to set format\n");
 			uninit();
@@ -205,29 +251,31 @@
 		rte_set_mode(mp1e_context, RTE_VIDEO);
 		mp1e_codec = rte_codec_set(mp1e_context, RTE_STREAM_VIDEO, 0, "mpeg1-video");
 
-		if (vo_fps < 24.0)
+		if (vo_fps < 24.0) {
 			frame_rate = RTE_RATE_1;
-		else if (vo_fps < 25.0)
+		} else if (vo_fps < 25.0) {
 			frame_rate = RTE_RATE_2;
-		else if (vo_fps < 29.97)
+		} else if (vo_fps < 29.97) {
 			frame_rate = RTE_RATE_3;
-		else if (vo_fps < 30.0)
+		} else if (vo_fps < 30.0) {
 			frame_rate = RTE_RATE_4;
-		else if (vo_fps < 50.0)
+		} else if (vo_fps < 50.0) {
 			frame_rate = RTE_RATE_5;
-		else if (vo_fps < 59.97)
+		} else if (vo_fps < 59.97) {
 			frame_rate = RTE_RATE_6;
-		else if (vo_fps < 60.0)
+		} else if (vo_fps < 60.0) {
 			frame_rate = RTE_RATE_7;
-		else if (vo_fps > 60.0)
+		} else if (vo_fps > 60.0) {
 			frame_rate = RTE_RATE_8;
-		else
+		} else {
 			frame_rate = RTE_RATE_NORATE;
+		}
 
-		if (format == IMGFMT_YUY2)
+		if (format == IMGFMT_YUY2) {
 			pixel_format = RTE_YUYV;
-		else
+		} else {
 			pixel_format = RTE_YUV420;
+		}
 		if (!rte_set_video_parameters(mp1e_context, pixel_format, mp1e_context->width, mp1e_context->height, frame_rate, 3e6, "I")) {
 			printf("VO: [dxr3] Unable to set mp1e context!\n");
 			rte_context_destroy(mp1e_context);
@@ -246,32 +294,34 @@
 		}
 
 		/* This stuff calculations the relative position of video and osd on screen */
-		osd_w=s_width;
-		d_pos_x=(s_width-v_width)/2;
+		/* Old stuff taken from the dvb driver, should be removed when introducing spuenc */
+		osd_w = s_width;
+		d_pos_x = (s_width - v_width) / 2;
 		if (d_pos_x < 0) {
 			s_pos_x = -d_pos_x;
 			d_pos_x = 0;
 			osd_w = s_width;
-		} else
+		} else {
 			s_pos_x = 0;
-    
+		}
 		osd_h = s_height;
-		d_pos_y = (s_height-v_height)/2;
+		d_pos_y = (s_height - v_height) / 2;
 		if (d_pos_y < 0) {
-			s_pos_y =- d_pos_y;
+			s_pos_y = -d_pos_y;
 			d_pos_y = 0;
 			osd_h = s_height;
-		} else
+		} else {
 			s_pos_y = 0;
-    
-		printf("VO: [dxr3] Position mapping: %d;%d => %d;%d\n", s_pos_x, s_pos_y, d_pos_x, d_pos_y);
+		}
                 
 		size = s_width * s_height;
 
 		if (format == IMGFMT_YUY2) {
+			/* YUY2 Needs no conversion, so no need for a pixel buffer */
 			picture_data[0] = NULL;
 			picture_linesize[0] = s_width * 2;
 		} else {
+			/* Create a pixel buffer and set up pointers for color components */
 			picture_data[0] = malloc((size * 3)/2);
 			picture_data[1] = picture_data[0] + size;
 			picture_data[2] = picture_data[1] + size / 4;
@@ -280,15 +330,15 @@
 			picture_linesize[2] = s_width / 2;
 		}
 
-	
-		if(!rte_start_encoding(mp1e_context)) {
+		if (!rte_start_encoding(mp1e_context)) {
 			printf("VO: [dxr3] Unable to start mp1e encoding!\n");
 			uninit();
 			return -1;
 		}
 
-		if(format == IMGFMT_BGR24)
+		if (format == IMGFMT_BGR24) {
 			yuv2rgb_init(24, MODE_BGR);
+		}
 		return 0;
 #endif
 		return -1;
@@ -309,6 +359,7 @@
 
 static void draw_alpha(int x0, int y0, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
 {
+#ifdef USE_MP1E
 	/* This function draws the osd and subtitles etc. It will change to use spuenc soon */
 	switch (img_format) {
 	case IMGFMT_BGR24:
@@ -321,11 +372,14 @@
 			picture_data[0] + (x0 + d_pos_x) * 2 + (y0 + d_pos_y) * picture_linesize[0], picture_linesize[0]);
 		break;
 	}
+#endif
 }
 
 static void draw_osd(void)
 {
-	vo_draw_text(osd_w, osd_h, draw_alpha);
+	if (img_format != IMGFMT_MPEGPES) {
+		vo_draw_text(osd_w, osd_h, draw_alpha);
+	}
 }
 
 static uint32_t draw_frame(uint8_t * src[])
@@ -335,17 +389,25 @@
 		size_t data_left = p->size;
 
 		if (p->id == 0x20) {
-			if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts) < 0)
+			/* Set subpic timestamp */
+			if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts) < 0) {
 				printf("VO: [dxr3] Unable to set pts\n");
+			}
 
-			while (data_left)
+			/* Force subpic data into buffer */
+			while (data_left) {
 				data_left -= write(fd_spu, (void*) (p->data + p->size-data_left), data_left);
+			}
 		} else {
-			if (ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts) < 0)
+			/* Set frame timestamp */
+			if (ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts) < 0) {
 				printf("VO: [dxr3] Unable to set pts\n");
-		
-			while (data_left)
+			}
+
+			/* Force video data into buffer */
+			while (data_left) {
 				data_left -= write(fd_video, (void*) (p->data + p->size-data_left), data_left);
+			}
 		}
 		return 0;
 	}
@@ -356,12 +418,14 @@
 	} else if (img_format == IMGFMT_BGR24) {
 		/* BGR24 needs to be converted to YUV420 before libmp1e will touch it */
 		int x, y, w = v_width, h = v_height;
-		unsigned char *s,*dY,*dU,*dV;
+		unsigned char *s, *dY, *dU, *dV;
 	
-		if (d_pos_x+w>picture_linesize[0])
+		if ((d_pos_x + w) > picture_linesize[0]) {
 			w = picture_linesize[0] - d_pos_x;
-		if (d_pos_y+h>s_height)
+		}
+		if ((d_pos_y + h) > s_height) {
 			h = s_height - d_pos_y;
+		}
 
 		s = src[0] + s_pos_y * (w * 3);
 
@@ -384,6 +448,10 @@
 
 static void flip_page(void)
 {
+	static int prev_pts = 0;
+	if (prev_pts > vo_pts) {
+		printf("WARNING: Seeking will break a/v sync currently\n");
+	}
 #ifdef USE_MP1E
 	if (img_format == IMGFMT_YV12) {
 		mp1e_buffer.data = picture_data[0];
@@ -396,23 +464,27 @@
 		mp1e_buffer.user_data = NULL;
 		rte_push_video_buffer(mp1e_context, &mp1e_buffer);
 	}
+	prev_pts = vo_pts;
 #endif
 }
 
 static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
 {
+#ifdef USE_MP1E
 	if (img_format == IMGFMT_YV12) {
 		int y;
-		unsigned char *s,*s1;
-		unsigned char *d,*d1;
+		unsigned char *s, *s1;
+		unsigned char *d, *d1;
 
 		x0 += d_pos_x;
 		y0 += d_pos_y;
 
-		if ((x0 + w) > picture_linesize[0])
-			w = picture_linesize[0]-x0;
-		if ((y0 + h) > s_height)
-			h = s_height-y0;
+		if ((x0 + w) > picture_linesize[0]) {
+			w = picture_linesize[0] - x0;
+		}
+		if ((y0 + h) > s_height) {
+			h = s_height - y0;
+		}
 
 		s = srcimg[0] + s_pos_x + s_pos_y * stride[0];
 		d = picture_data[0] + x0 + y0 * picture_linesize[0];
@@ -441,6 +513,7 @@
 		}
 		return 0;
 	}
+#endif
 	return -1;
 }
 
@@ -448,33 +521,46 @@
 {
 	uint32_t flag = 0;
 	
-	if (format == IMGFMT_MPEGPES)
-		flag = 0x2 | 0x4 | 0x8;
+	if (format == IMGFMT_MPEGPES) {
+		/* Hardware accelerated | Hardware supports subpics | Hardware handles syncing */
+		flag = 0x2 | 0x8 | 0x100;
 #ifdef USE_MP1E
-	if (format == IMGFMT_YV12)
-		flag = 0x1 | 0x4;
-	if (format == IMGFMT_YUY2)
-		flag = 0x1 | 0x4;
-	if (format == IMGFMT_BGR24)
-		flag = 0x1 | 0x4;
-	else
+	} else if (format == IMGFMT_YV12) {
+		/* Conversion needed | OSD Supported | Hardware handles syncing */
+		flag = 0x1 | 0x4 | 0x100;
+	} else if (format == IMGFMT_YUY2) {
+		/* Conversion needed | OSD Supported | Hardware handles syncing */
+		flag = 0x1 | 0x4 | 0x100;
+	} else if (format == IMGFMT_BGR24) {
+		/* Conversion needed | OSD Supported | Hardware handles syncing */
+		flag = 0x1 | 0x4 | 0x100;
+	} else {
 		printf("VO: [dxr3] Format unsupported, mail dholm@iname.com\n");
 #else
-	else
+	} else {
 		printf("VO: [dxr3] You have disabled libmp1e support, you won't be able to play this format!\n");
 #endif
+	}
 	return flag;
 }
 
 static void uninit(void)
 {
 	printf("VO: [dxr3] Uninitializing\n");
-	if (picture_data[0])
+#ifdef USE_MP1E
+	if (picture_data[0]) {
 		free(picture_data[0]);
-	if (fd_video)
+	}
+#endif
+	if (fd_video) {
 		close(fd_video);
-	if(fd_spu)
+	}
+	if (fd_spu) {
 		close(fd_spu);
+	}
+	if (fd_control) {
+		close(fd_control);
+	}
 }
 
 static void check_events(void)