summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
authormswitch <mswitch@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-01-17 10:33:47 +0000
committermswitch <mswitch@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-01-17 10:33:47 +0000
commit94d8b9131db618a014d6d58ba3080e9597cae297 (patch)
tree4024c7c326613030c5bb13556ec29213c036f87e /libvo
parente53f6685ada75deb2e45b24bd81f0919d0203eb6 (diff)
downloadmpv-94d8b9131db618a014d6d58ba3080e9597cae297.tar.bz2
mpv-94d8b9131db618a014d6d58ba3080e9597cae297.tar.xz
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... git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4219 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libvo')
-rw-r--r--libvo/vo_dxr3.c268
1 files changed, 177 insertions, 91 deletions
diff --git a/libvo/vo_dxr3.c b/libvo/vo_dxr3.c
index 51b4e2936e..5b98850049 100644
--- a/libvo/vo_dxr3.c
+++ b/libvo/vo_dxr3.c
@@ -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 @@ LIBVO_EXTERN (dxr3)
#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 @@ static vo_info_t vo_info =
};
#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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
/* 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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
}
/* 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 @@ static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, ui
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 const vo_info_t* get_info(void)
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 @@ static void draw_alpha(int x0, int y0, int w, int h, unsigned char* src, unsigne
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 @@ static uint32_t draw_frame(uint8_t * src[])
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 @@ static uint32_t draw_frame(uint8_t * src[])
} 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 uint32_t draw_frame(uint8_t * src[])
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 @@ static void flip_page(void)
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 @@ static uint32_t draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0
}
return 0;
}
+#endif
return -1;
}
@@ -448,33 +521,46 @@ static uint32_t query_format(uint32_t format)
{
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)