summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)