diff options
-rw-r--r-- | libvo/vo_dxr3.c | 268 |
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, ®); + + /* 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) |