Do _not_ use rbx on x86_64, it will fail to compile with PIC, besides it
[mplayer/glamo.git] / libvo / vo_dxr3.c
blobc5fa8a970d5938418b0297783752ea0f3fbb00c0
1 /*
2 * DXR3/H+ video output
4 * Copyright (C) 2002-2003 David Holm <david@realityrift.com>
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <linux/em8300.h>
24 #include <sys/ioctl.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/select.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <time.h>
35 #include <math.h>
37 #include "config.h"
38 #include "mp_msg.h"
39 #include "help_mp.h"
40 #if HAVE_MALLOC_H
41 #include <malloc.h>
42 #endif
43 #include "fastmemcpy.h"
45 #include "video_out.h"
46 #include "video_out_internal.h"
47 #include "aspect.h"
48 #include "spuenc.h"
49 #include "sub.h"
50 #ifdef CONFIG_GUI
51 #include "gui/interface.h"
52 #endif
53 #ifdef CONFIG_X11
54 #include "x11_common.h"
55 #endif
56 #include "libavutil/avstring.h"
58 #define SPU_SUPPORT
60 static const vo_info_t info =
62 "DXR3/H+ video out",
63 "dxr3",
64 "David Holm <dholm@iname.com>",
67 const LIBVO_EXTERN (dxr3)
69 /* Resolutions and positions */
70 static int v_width, v_height;
71 static int s_width, s_height;
72 static int osd_w, osd_h;
73 static int img_format;
75 /* Configuration values
76 * Don't declare these static, they
77 * should be accessible from the gui.
79 int dxr3_prebuf = 0;
80 int dxr3_newsync = 0;
81 int dxr3_overlay = 0;
82 int dxr3_device_num = 0;
83 int dxr3_norm = 0;
85 #define MAX_STR_SIZE 80 /* length for the static strings */
87 /* File descriptors */
88 static int fd_control = -1;
89 static int fd_video = -1;
90 static int fd_spu = -1;
91 static char fdv_name[MAX_STR_SIZE];
92 static char fds_name[MAX_STR_SIZE];
94 #ifdef SPU_SUPPORT
95 /* on screen display/subpics */
96 static char *osdpicbuf;
97 static int osdpicbuf_w;
98 static int osdpicbuf_h;
99 static int disposd;
100 static encodedata *spued;
101 static encodedata *spubuf;
102 #endif
105 /* Static variable used in ioctl's */
106 static int ioval;
107 static int prev_pts;
108 static int pts_offset;
109 static int old_vmode = -1;
112 /* Begin overlay.h */
114 Simple analog overlay API for DXR3/H+ linux driver.
116 Henrik Johansson
120 /* Pattern drawing callback used by the calibration functions.
121 The function is expected to:
122 Clear the entire screen.
123 Fill the screen with color bgcol (0xRRGGBB)
124 Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
127 typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
128 int xpos, int ypos, int width, int height, void *arg);
130 struct coeff {
131 float k,m;
134 typedef struct {
135 int dev;
137 int xres, yres,depth;
138 int xoffset,yoffset,xcorr;
139 int jitter;
140 int stability;
141 int keycolor;
142 struct coeff colcal_upper[3];
143 struct coeff colcal_lower[3];
144 float color_interval;
146 pattern_drawer_cb draw_pattern;
147 void *dp_arg;
148 } overlay_t;
151 static overlay_t *overlay_init(int dev);
152 static int overlay_release(overlay_t *);
154 static int overlay_read_state(overlay_t *o, char *path);
155 static int overlay_write_state(overlay_t *o, char *path);
157 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
158 static int overlay_set_mode(overlay_t *o, int mode);
159 static int overlay_set_attribute(overlay_t *o, int attribute, int val);
160 static int overlay_set_keycolor(overlay_t *o, int color);
161 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
162 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
164 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
165 static void overlay_update_params(overlay_t *o);
166 static int overlay_signalmode(overlay_t *o, int mode);
167 /* End overlay.h */
170 #ifdef CONFIG_X11
171 #define KEY_COLOR 0x80a040
172 static XWindowAttributes xwin_attribs;
173 static overlay_t *overlay_data;
174 #endif
177 /* Functions for working with the em8300's internal clock */
178 /* End of internal clock functions */
180 static int control(uint32_t request, void *data, ...)
182 switch (request) {
183 case VOCTRL_GUISUPPORT:
184 return VO_TRUE;
185 case VOCTRL_GUI_NOWINDOW:
186 if (dxr3_overlay) {
187 return VO_FALSE;
189 return VO_TRUE;
190 case VOCTRL_SET_SPU_PALETTE:
191 if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
192 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToLoadNewSPUPalette);
193 return VO_ERROR;
195 return VO_TRUE;
196 #ifdef CONFIG_X11
197 case VOCTRL_ONTOP:
198 vo_x11_ontop();
199 return VO_TRUE;
200 case VOCTRL_FULLSCREEN:
201 if (dxr3_overlay) {
202 vo_x11_fullscreen();
203 overlay_signalmode(overlay_data,
204 vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
205 EM8300_OVERLAY_SIGNAL_WITH_VGA);
206 return VO_TRUE;
208 return VO_FALSE;
209 #endif
210 case VOCTRL_RESUME:
211 if (dxr3_newsync) {
212 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
213 pts_offset = vo_pts - (ioval << 1);
214 if (pts_offset < 0) {
215 pts_offset = 0;
219 if (dxr3_prebuf) {
220 ioval = EM8300_PLAYMODE_PLAY;
221 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
222 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
225 return VO_TRUE;
226 case VOCTRL_PAUSE:
227 if (dxr3_prebuf) {
228 ioval = EM8300_PLAYMODE_PAUSED;
229 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
230 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
233 return VO_TRUE;
234 case VOCTRL_RESET:
235 if (dxr3_prebuf) {
236 close(fd_video);
237 fd_video = open(fdv_name, O_WRONLY);
238 close(fd_spu);
239 fd_spu = open(fds_name, O_WRONLY);
240 fsync(fd_video);
241 fsync(fd_spu);
243 return VO_TRUE;
244 case VOCTRL_QUERY_FORMAT:
246 uint32_t flag = 0;
248 if (*((uint32_t*)data) != IMGFMT_MPEGPES)
249 return 0;
251 flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
252 if (dxr3_prebuf)
253 flag |= VFCAP_TIMER;
254 return flag;
256 case VOCTRL_SET_EQUALIZER:
258 va_list ap;
259 int value;
260 em8300_bcs_t bcs;
262 va_start(ap, data);
263 value = va_arg(ap, int);
264 va_end(ap);
266 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
267 return VO_FALSE;
268 if (!strcasecmp(data, "brightness"))
269 bcs.brightness = (value+100)*5;
270 else if (!strcasecmp(data, "contrast"))
271 bcs.contrast = (value+100)*5;
272 else if (!strcasecmp(data, "saturation"))
273 bcs.saturation = (value+100)*5;
274 else return VO_FALSE;
276 if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
277 return VO_FALSE;
278 return VO_TRUE;
280 case VOCTRL_GET_EQUALIZER:
282 va_list ap;
283 int *value;
284 em8300_bcs_t bcs;
286 va_start(ap, data);
287 value = va_arg(ap, int*);
288 va_end(ap);
290 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
291 return VO_FALSE;
293 if (!strcasecmp(data, "brightness"))
294 *value = (bcs.brightness/5)-100;
295 else if (!strcasecmp(data, "contrast"))
296 *value = (bcs.contrast/5)-100;
297 else if (!strcasecmp(data, "saturation"))
298 *value = (bcs.saturation/5)-100;
299 else return VO_FALSE;
301 return VO_TRUE;
304 return VO_NOTIMPL;
307 void calculate_cvals(unsigned long mask, int *shift, int *prec)
309 /* Calculate shift and precision */
310 (*shift) = 0;
311 (*prec) = 0;
313 while (!(mask & 0x1)) {
314 (*shift)++;
315 mask >>= 1;
318 while (mask & 0x1) {
319 (*prec)++;
320 mask >>= 1;
324 static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
326 int tmp1, tmp2, size;
327 em8300_register_t reg;
328 extern float monitor_aspect;
330 /* Softzoom turned on, downscale */
331 /* This activates the subpicture processor, you can safely disable this and still send */
332 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
333 /* up in a lockup */
334 ioval = EM8300_SPUMODE_ON;
335 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
336 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetSubpictureMode);
337 uninit();
338 return -1;
341 /* Set the playmode to play (just in case another app has set it to something else) */
342 ioval = EM8300_PLAYMODE_PLAY;
343 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
344 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
347 /* Start em8300 prebuffering and sync engine */
348 reg.microcode_register = 1;
349 reg.reg = 0;
350 reg.val = MVCOMMAND_SYNC;
351 ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
353 /* Clean buffer by syncing it */
354 ioval = EM8300_SUBDEVICE_VIDEO;
355 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
356 ioval = EM8300_SUBDEVICE_AUDIO;
357 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
359 /* Sync the video device to make sure the buffers are empty
360 * and set the playback speed to normal. Also reset the
361 * em8300 internal clock.
363 fsync(fd_video);
364 ioval = 0x900;
365 ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
367 /* Store some variables statically that we need later in another scope */
368 img_format = format;
369 v_width = width;
370 v_height = height;
372 /* Set monitor_aspect to avoid jitter */
373 monitor_aspect = (float) width / (float) height;
375 if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
376 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToGetTVNorm);
377 old_vmode = -1;
380 /* adjust TV norm */
381 if (dxr3_norm != 0) {
382 if (dxr3_norm == 5) {
383 ioval = EM8300_VIDEOMODE_NTSC;
384 } else if (dxr3_norm == 4) {
385 ioval = EM8300_VIDEOMODE_PAL60;
386 } else if (dxr3_norm == 3) {
387 ioval = EM8300_VIDEOMODE_PAL;
388 } else if (dxr3_norm == 2) {
389 if (vo_fps > 28) {
390 ioval = EM8300_VIDEOMODE_PAL60;
391 } else {
392 ioval = EM8300_VIDEOMODE_PAL;
395 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
396 ioval == EM8300_VIDEOMODE_PAL60 ? mp_msg(MSGT_VO,MSGL_INFO, "PAL-60") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
397 printf(".\n");
398 } else {
399 if (vo_fps > 28) {
400 ioval = EM8300_VIDEOMODE_NTSC;
401 } else {
402 ioval = EM8300_VIDEOMODE_PAL;
405 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
406 ioval == EM8300_VIDEOMODE_NTSC ? mp_msg(MSGT_VO,MSGL_INFO, "NTSC") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
407 printf(".\n");
410 if (old_vmode != ioval) {
411 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
412 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetTVNorm);
418 /* libavcodec requires a width and height that is x|16 */
419 aspect_save_orig(width, height);
420 aspect_save_prescale(d_width, d_height);
421 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
422 if (ioval == EM8300_VIDEOMODE_NTSC) {
423 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForNTSC);
424 aspect_save_screenres(352, 240);
425 } else {
426 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForPALSECAM);
427 aspect_save_screenres(352, 288);
429 aspect(&s_width, &s_height, A_ZOOM);
430 s_width -= s_width % 16;
431 s_height -= s_height % 16;
433 /* Try to figure out whether to use widescreen output or not */
434 /* Anamorphic widescreen modes makes this a pain in the ass */
435 tmp1 = abs(d_height - ((d_width / 4) * 3));
436 tmp2 = abs(d_height - (int) (d_width / 2.35));
437 if (tmp1 < tmp2) {
438 ioval = EM8300_ASPECTRATIO_4_3;
439 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo43);
440 } else {
441 ioval = EM8300_ASPECTRATIO_16_9;
442 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo169);
444 ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
446 #ifdef SPU_SUPPORT
447 #ifdef CONFIG_FREETYPE
448 if (ioval == EM8300_ASPECTRATIO_16_9) {
449 s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
450 } else {
451 s_width *= 0.84;
453 //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
454 #else
455 s_width*=2;
456 s_height*=2;
457 #endif
459 osdpicbuf = calloc( 1,s_width * s_height);
460 if (osdpicbuf == NULL) {
461 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
462 return -1;
464 spued = (encodedata *) malloc(sizeof(encodedata));
465 if (spued == NULL) {
466 free( osdpicbuf );
467 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
468 return -1;
470 spubuf = (encodedata *) malloc(sizeof(encodedata));
471 if (spubuf == NULL) {
472 free( osdpicbuf );
473 free( spued );
474 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
475 return -1;
477 osd_w = s_width;
478 osd_h = s_height;
479 osdpicbuf_w = s_width;
480 osdpicbuf_h = s_height;
482 spubuf->count=0;
483 pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
485 #endif
487 #ifdef CONFIG_X11
488 if (dxr3_overlay) {
489 XVisualInfo vinfo;
490 XSetWindowAttributes xswa;
491 XSizeHints hint;
492 unsigned long xswamask;
493 Colormap cmap;
494 XColor key_color;
495 Window junkwindow;
496 Screen *scr;
497 int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
498 em8300_overlay_screen_t ovlscr;
499 em8300_attribute_t ovlattr;
501 vo_dx = (vo_screenwidth - d_width) / 2;
502 vo_dy = (vo_screenheight - d_height) / 2;
503 vo_dwidth = d_width;
504 vo_dheight = d_height;
505 #ifdef CONFIG_GUI
506 if (use_gui) {
507 guiGetEvent(guiSetShVideo, 0);
508 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
509 XClearWindow(mDisplay, vo_window);
510 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
511 depth = xwin_attribs.depth;
512 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
513 depth = 24;
515 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
516 } else
517 #endif
519 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
520 depth = xwin_attribs.depth;
521 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
522 depth = 24;
524 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
525 vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy,
526 d_width, d_height, flags,
527 CopyFromParent, "Viewing Window", title);
528 xswa.background_pixel = KEY_COLOR;
529 xswa.border_pixel = 0;
530 xswamask = CWBackPixel | CWBorderPixel;
531 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa);
534 /* Start setting up overlay */
535 XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
536 overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
537 overlay_read_state(overlay_data, NULL);
539 /* Allocate keycolor */
540 cmap = vo_x11_create_colormap(&vinfo);
541 calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
542 calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
543 calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
545 key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
546 key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
547 key_color.blue = (KEY_COLOR & 0xff) * 256;
548 key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
549 ((key_color.green >> (16 - green_prec)) << green_shift) +
550 ((key_color.blue >> (16 - blue_prec)) << blue_shift));
551 key_color.flags = DoRed | DoGreen | DoBlue;
552 if (!XAllocColor(mDisplay, cmap, &key_color)) {
553 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToAllocateKeycolor);
554 return -1;
557 acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
558 if (key_color.pixel != KEY_COLOR) {
559 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToAllocateExactKeycolor, key_color.pixel);
562 /* Set keycolor and activate overlay */
563 XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
564 XClearWindow(mDisplay, vo_window);
565 overlay_set_keycolor(overlay_data, key_color.pixel);
566 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
567 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
569 #endif
571 return 0;
574 static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
576 #ifdef SPU_SUPPORT
577 unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
578 int by = 0;
579 register int lx, ly;
580 register int stride = 0;
582 for (ly = 0; ly < h - 1; ly++)
584 for(lx = 0; lx < w; lx++ )
585 if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
586 by+=osdpicbuf_w;
587 stride+=srcstride;
589 pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
590 #endif
593 extern int vo_osd_changed_flag;
594 extern mp_osd_obj_t* vo_osd_list;
596 static void draw_osd(void)
598 #ifdef SPU_SUPPORT
599 static int cleared = 0;
600 int changed = 0;
602 if ((disposd % 15) == 0)
605 mp_osd_obj_t* obj = vo_osd_list;
606 vo_update_osd( osd_w,osd_h );
607 while( obj )
609 if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
610 obj=obj->next;
613 if ( changed )
615 vo_draw_text(osd_w, osd_h, draw_alpha);
616 memset(osdpicbuf, 0, s_width * s_height);
617 cleared=0;
619 else
621 if ( !cleared )
623 spued->count=spubuf->count;
624 fast_memcpy( spued->data,spubuf->data,DATASIZE );
625 cleared=1;
630 /* could stand some check here to see if the subpic hasn't changed
631 * as if it hasn't and we re-send it it will "blink" as the last one
632 * is turned off, and the new one (same one) is turned on
634 /* Subpics are not stable yet =(
635 expect lockups if you enable */
636 #if 1
637 write(fd_spu, spued->data, spued->count);
638 #endif
640 disposd++;
641 #endif
645 static int draw_frame(uint8_t * src[])
647 vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
649 #ifdef SPU_SUPPORT
650 if (p->id == 0x20) {
651 write(fd_spu, p->data, p->size);
652 } else
653 #endif
654 write(fd_video, p->data, p->size);
655 return 0;
658 static void flip_page(void)
660 #ifdef CONFIG_X11
661 if (dxr3_overlay) {
662 int event = vo_x11_check_events(mDisplay);
663 if (event & VO_EVENT_RESIZE) {
664 Window junkwindow;
665 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
666 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
667 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
669 if (event & VO_EVENT_EXPOSE) {
670 Window junkwindow;
671 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
672 XClearWindow(mDisplay, vo_window);
673 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
674 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
675 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
678 #endif
680 if (dxr3_newsync) {
681 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
682 ioval <<= 1;
683 if (vo_pts == 0) {
684 ioval = 0;
685 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
686 pts_offset = 0;
687 } else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
688 ioval = (vo_pts + pts_offset) >> 1;
689 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
690 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
691 pts_offset = vo_pts - (ioval << 1);
692 if (pts_offset < 0) {
693 pts_offset = 0;
696 ioval = vo_pts + pts_offset;
697 ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
698 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
699 prev_pts = vo_pts;
700 } else if (dxr3_prebuf) {
701 ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
702 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
706 static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
708 return -1;
711 static void uninit(void)
713 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Uninitializing);
714 #ifdef CONFIG_X11
715 if (dxr3_overlay) {
716 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
717 overlay_release(overlay_data);
719 #ifdef CONFIG_GUI
720 if (!use_gui) {
721 #endif
722 vo_x11_uninit();
724 #ifdef CONFIG_GUI
726 #endif
728 #endif
729 if (old_vmode != -1) {
730 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
731 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedRestoringTVNorm);
735 if (fd_video) {
736 close(fd_video);
738 if (fd_spu) {
739 close(fd_spu);
741 if (fd_control) {
742 close(fd_control);
744 #ifdef SPU_SUPPORT
745 if(osdpicbuf) {
746 free(osdpicbuf);
748 if(spued) {
749 free(spued);
751 #endif
754 static void check_events(void)
758 static int preinit(const char *arg)
760 char devname[MAX_STR_SIZE];
761 int fdflags = O_WRONLY;
763 /* Parse commandline */
764 while (arg) {
765 if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
766 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_EnablingPrebuffering);
767 dxr3_prebuf = 1;
768 } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
769 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingNewSyncEngine);
770 dxr3_newsync = 1;
771 } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
772 #ifdef CONFIG_X11
773 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingOverlay);
774 dxr3_overlay = 1;
775 #else
776 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorYouNeedToCompileMplayerWithX11);
777 #endif
778 } else if (!strncmp("norm=", arg, 5)) {
779 arg += 5;
780 // dxr3_norm is 0 (-> don't change norm) by default
781 // but maybe someone changes this in the future
783 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_WillSetTVNormTo);
785 if (*arg == '5') {
786 dxr3_norm = 5;
787 mp_msg(MSGT_VO,MSGL_INFO, "NTSC");
788 } else if (*arg == '4') {
789 dxr3_norm = 4;
790 mp_msg(MSGT_VO,MSGL_INFO, "PAL-60");
791 } else if (*arg == '3') {
792 dxr3_norm = 3;
793 mp_msg(MSGT_VO,MSGL_INFO, "PAL");
794 } else if (*arg == '2') {
795 dxr3_norm = 2;
796 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALPAL60);
797 } else if (*arg == '1') {
798 dxr3_norm = 1;
799 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALNTSC);
800 } else if (*arg == '0') {
801 dxr3_norm = 0;
802 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseCurrentNorm);
803 } else {
804 dxr3_norm = 0;
805 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseUnknownNormSuppliedCurrentNorm);
808 mp_msg(MSGT_VO,MSGL_INFO, ".\n");
809 } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
810 dxr3_device_num = arg[0];
813 arg = strchr(arg, ':');
814 if (arg) {
815 arg++;
820 /* Open the control interface */
821 sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
822 fd_control = open(devname, fdflags);
823 if (fd_control < 1) {
824 /* Fall back to old naming scheme */
825 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTrying, devname);
826 sprintf(devname, "/dev/em8300");
827 fd_control = open(devname, fdflags);
828 if (fd_control < 1) {
829 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWell);
830 return -1;
832 } else {
833 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
836 /* Open the video interface */
837 sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
838 fd_video = open(devname, fdflags);
839 if (fd_video < 0) {
840 /* Fall back to old naming scheme */
841 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingMV, devname);
842 sprintf(devname, "/dev/em8300_mv");
843 fd_video = open(devname, fdflags);
844 if (fd_video < 0) {
845 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellMV);
846 uninit();
847 return -1;
849 } else {
850 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
852 strcpy(fdv_name, devname);
854 /* Open the subpicture interface */
855 sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
856 fd_spu = open(devname, fdflags);
857 if (fd_spu < 0) {
858 /* Fall back to old naming scheme */
859 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingSP, devname);
860 sprintf(devname, "/dev/em8300_sp");
861 fd_spu = open(devname, fdflags);
862 if (fd_spu < 0) {
863 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellSP);
864 uninit();
865 return -1;
867 } else {
868 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
870 strcpy(fds_name, devname);
872 #ifdef CONFIG_X11
873 if (dxr3_overlay) {
875 /* Fucked up hack needed to enable overlay.
876 * Will be removed as soon as I figure out
877 * how to make it work like it should
879 Display *dpy;
880 overlay_t *ov;
881 XWindowAttributes attribs;
883 dpy = XOpenDisplay(NULL);
884 if (!dpy) {
885 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToOpenDisplayDuringHackSetup);
886 return -1;
888 XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
889 ov = overlay_init(fd_control);
890 overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
891 overlay_read_state(ov, NULL);
892 overlay_set_keycolor(ov, KEY_COLOR);
893 overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
894 overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
895 overlay_release(ov);
896 XCloseDisplay(dpy);
897 /* End of fucked up hack */
899 /* Initialize overlay and X11 */
900 overlay_data = overlay_init(fd_control);
901 #ifdef CONFIG_GUI
902 if (!use_gui) {
903 #endif
904 if (!vo_init()) {
905 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToInitX11);
906 return -1;
908 #ifdef CONFIG_GUI
910 #endif
912 #endif
914 if (dxr3_newsync) {
915 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
916 pts_offset = vo_pts - (ioval << 1);
917 if (pts_offset < 0) {
918 pts_offset = 0;
922 return 0;
925 /* Begin overlay.c */
926 static int update_parameters(overlay_t *o)
928 overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
929 overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
930 overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
931 overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
932 overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
933 return 0;
936 static int overlay_set_attribute(overlay_t *o, int attribute, int value)
938 em8300_attribute_t attr;
940 attr.attribute = attribute;
941 attr.value = value;
942 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
944 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayAttribute);
945 return -1;
948 return 0;
951 static overlay_t *overlay_init(int dev)
953 overlay_t *o;
955 o = (overlay_t *) malloc(sizeof(overlay_t));
957 if(!o)
958 return NULL;
960 memset(o,0,sizeof(overlay_t));
962 o->dev = dev;
963 o->xres = 1280; o->yres=1024; o->xcorr=1000;
964 o->color_interval=10;
966 return o;
969 static int overlay_release(overlay_t *o)
971 if(o)
972 free(o);
974 return 0;
976 #define TYPE_INT 1
977 #define TYPE_XINT 2
978 #define TYPE_COEFF 3
979 #define TYPE_FLOAT 4
981 struct lut_entry {
982 char *name;
983 int type;
984 void *ptr;
987 static struct lut_entry *new_lookuptable(overlay_t *o)
989 struct lut_entry m[] = {
990 {"xoffset", TYPE_INT, &o->xoffset},
991 {"yoffset", TYPE_INT, &o->yoffset},
992 {"xcorr", TYPE_INT, &o->xcorr},
993 {"jitter", TYPE_INT, &o->jitter},
994 {"stability", TYPE_INT, &o->stability},
995 {"keycolor", TYPE_XINT, &o->keycolor},
996 {"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
997 {"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
998 {"color_interval", TYPE_FLOAT, &o->color_interval},
999 {0,0,0}
1000 },*p;
1002 p = malloc(sizeof(m));
1003 memcpy(p,m,sizeof(m));
1004 return p;
1007 static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
1008 int i;
1010 for(i=0; lut[i].name; i++) {
1011 if(!strcmp(name,lut[i].name)) {
1012 *ptr = lut[i].ptr;
1013 *type = lut[i].type;
1014 return 1;
1017 return 0;
1020 static int overlay_read_state(overlay_t *o, char *p)
1022 char *a,*tok;
1023 char path[128],fname[128],tmp[128],line[256];
1024 FILE *fp;
1025 struct lut_entry *lut;
1026 void *ptr;
1027 int type;
1028 int j;
1030 if(!p) {
1031 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1032 av_strlcat(fname,"/.overlay", sizeof( fname ));
1033 } else
1034 av_strlcpy(fname, p, sizeof( fname ));
1036 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1037 av_strlcat(fname, tmp, sizeof( fname ));
1039 if(!(fp=fopen(fname,"r")))
1040 return -1;
1042 lut = new_lookuptable(o);
1044 while(!feof(fp)) {
1045 if(!fgets(line,256,fp))
1046 break;
1047 tok=strtok(line," ");
1048 if(lookup_parameter(o,lut,tok,&ptr,&type)) {
1049 tok=strtok(NULL," ");
1050 switch(type) {
1051 case TYPE_INT:
1052 sscanf(tok,"%d",(int *)ptr);
1053 break;
1054 case TYPE_XINT:
1055 sscanf(tok,"%x",(int *)ptr);
1056 break;
1057 case TYPE_FLOAT:
1058 sscanf(tok,"%f",(float *)ptr);
1059 break;
1060 case TYPE_COEFF:
1061 for(j=0;j<3;j++) {
1062 sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1063 tok=strtok(NULL," ");
1064 sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1065 tok=strtok(NULL," ");
1067 break;
1073 update_parameters(o);
1075 free(lut);
1076 fclose(fp);
1077 return 0;
1080 static void overlay_update_params(overlay_t *o) {
1081 update_parameters(o);
1084 static int overlay_write_state(overlay_t *o, char *p)
1086 char *a;
1087 char path[128],fname[128],tmp[128];
1088 FILE *fp;
1089 char line[256],*tok;
1090 struct lut_entry *lut;
1091 int i,j;
1093 if(!p) {
1094 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1095 av_strlcat(fname,"/.overlay", sizeof( fname ));
1096 } else
1097 av_strlcpy(fname, p, sizeof( fname ));
1099 if(access(fname, W_OK|X_OK|R_OK)) {
1100 if(mkdir(fname,0766))
1101 return -1;
1104 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1105 av_strlcat(fname, tmp, sizeof( fname ));
1107 if(!(fp=fopen(fname,"w")))
1108 return -1;
1110 lut = new_lookuptable(o);
1112 for(i=0; lut[i].name; i++) {
1113 fprintf(fp,"%s ",lut[i].name);
1114 switch(lut[i].type) {
1115 case TYPE_INT:
1116 fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1117 break;
1118 case TYPE_XINT:
1119 fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1120 break;
1121 case TYPE_FLOAT:
1122 fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1123 break;
1124 case TYPE_COEFF:
1125 for(j=0;j<3;j++)
1126 fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1127 ((struct coeff *)lut[i].ptr)[j].m);
1128 fprintf(fp,"\n");
1129 break;
1133 fclose(fp);
1134 return 0;
1137 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1139 em8300_overlay_screen_t scr;
1141 o->xres = xres;
1142 o->yres = yres;
1143 o->depth = depth;
1145 scr.xsize = xres;
1146 scr.ysize = yres;
1148 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1150 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayScreen);
1151 return -1;
1153 return 0;
1156 static int overlay_set_mode(overlay_t *o, int mode)
1158 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1159 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedEnablingOverlay);
1160 return -1;
1162 return 0;
1165 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1167 em8300_overlay_window_t win;
1168 win.xpos = xpos;
1169 win.ypos = ypos;
1170 win.width = width;
1171 win.height = height;
1173 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1175 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1176 return -1;
1178 return 0;
1181 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1183 em8300_bcs_t bcs;
1184 bcs.brightness = brightness;
1185 bcs.contrast = contrast;
1186 bcs.saturation = saturation;
1188 if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1190 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayBcs);
1191 return -1;
1193 return 0;
1196 static int col_interp(float x, struct coeff c)
1198 float y;
1199 y = x*c.k + c.m;
1200 if(y > 255)
1201 y = 255;
1202 if(y < 0)
1203 y = 0;
1204 return rint(y);
1207 static int overlay_set_keycolor(overlay_t *o, int color) {
1208 int r = (color & 0xff0000) >> 16;
1209 int g = (color & 0x00ff00) >> 8;
1210 int b = (color & 0x0000ff);
1211 float ru,gu,bu;
1212 float rl,gl,bl;
1213 int upper,lower;
1215 ru = r+o->color_interval;
1216 gu = g+o->color_interval;
1217 bu = b+o->color_interval;
1219 rl = r-o->color_interval;
1220 gl = g-o->color_interval;
1221 bl = b-o->color_interval;
1223 upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1224 (col_interp(gu, o->colcal_upper[1]) << 8) |
1225 (col_interp(bu, o->colcal_upper[2]));
1227 lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1228 (col_interp(gl, o->colcal_lower[1]) << 8) |
1229 (col_interp(bl, o->colcal_lower[2]));
1231 //printf("0x%06x 0x%06x\n",upper,lower);
1232 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1233 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1234 return 0;
1237 static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1239 float sx=0,sy=0,sxx=0,sxy=0;
1240 float delta,b;
1241 int i;
1243 for(i=0; i < n; i++) {
1244 sx=sx+x[i];
1245 sy=sy+y[i];
1246 sxx=sxx+x[i]*x[i];
1247 sxy=sxy+x[i]*y[i];
1250 delta=sxx*n-sx*sx;
1252 *m=(sxx*sy-sx*sxy)/delta;
1253 *k=(sxy*n-sx*sy)/delta;
1256 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1258 em8300_overlay_calibrate_t cal;
1259 em8300_overlay_window_t win;
1260 int x[256],r[256],g[256],b[256],n;
1261 float k,m;
1263 int i;
1265 o->draw_pattern=pd;
1266 o->dp_arg = arg;
1268 overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1269 overlay_set_screen(o, o->xres, o->yres, o->depth);
1271 /* Calibrate Y-offset */
1273 o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1275 cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1276 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1278 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayYOffsetValues);
1279 return -1;
1281 o->yoffset = cal.result;
1282 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_YOffset,cal.result);
1284 /* Calibrate X-offset */
1286 o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1288 cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1289 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1291 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXOffsetValues);
1292 return -1;
1294 o->xoffset = cal.result;
1295 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XOffset,cal.result);
1297 /* Calibrate X scale correction */
1299 o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1301 cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1302 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1304 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXScaleCorrection);
1305 return -1;
1307 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XCorrection,cal.result);
1308 o->xcorr = cal.result;
1310 win.xpos = 10;
1311 win.ypos = 10;
1312 win.width = o->xres-20;
1313 win.height = o->yres-20;
1314 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1315 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1316 exit(1);
1319 /* Calibrate key color upper limit */
1321 for(i=128,n=0; i <= 0xff; i+=4) {
1322 o->draw_pattern(i | (i << 8) | (i << 16), 0,
1323 (o->xres-200)/2,0,200,o->yres,o->dp_arg);
1325 cal.arg = i;
1326 cal.arg2 = 1;
1327 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1329 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1331 return -1 ;
1334 x[n] = i;
1335 r[n] = (cal.result>>16)&0xff;
1336 g[n] = (cal.result>>8)&0xff;
1337 b[n] = (cal.result)&0xff;
1338 n++;
1341 least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1342 least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1343 least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1345 /* Calibrate key color lower limit */
1347 for(i=128,n=0; i <= 0xff; i+=4) {
1348 o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1349 (o->xres-200)/2,0,200,o->yres, o->dp_arg);
1351 cal.arg = i;
1352 cal.arg2 = 2;
1353 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1355 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1357 return -1 ;
1359 x[n] = i;
1360 r[n] = (cal.result>>16)&0xff;
1361 g[n] = (cal.result>>8)&0xff;
1362 b[n] = (cal.result)&0xff;
1363 n++;
1366 least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1367 least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1368 least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1370 overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1372 return 0;
1376 static int overlay_signalmode(overlay_t *o, int mode) {
1377 if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1378 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSetSignalMix);
1379 return -1;
1381 return 0;
1383 /* End overlay.c */