Get rid of pointless and now unused defines.
[mplayer/glamo.git] / libvo / vo_dxr3.c
bloba3ee6573c8ce1bbecbf9decbfe4d11d71c96580d
1 /*
2 * vo_dxr3.c - DXR3/H+ video out
4 * Copyright (C) 2002-2003 David Holm <david@realityrift.com>
6 */
8 #include <linux/em8300.h>
9 #include <sys/ioctl.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <sys/select.h>
13 #include <unistd.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <time.h>
20 #include <math.h>
22 #include "config.h"
23 #include "mp_msg.h"
24 #include "help_mp.h"
25 #ifdef HAVE_MALLOC_H
26 #include <malloc.h>
27 #endif
28 #include "fastmemcpy.h"
30 #include "video_out.h"
31 #include "video_out_internal.h"
32 #include "aspect.h"
33 #include "spuenc.h"
34 #include "sub.h"
35 #ifdef CONFIG_GUI
36 #include "gui/interface.h"
37 #endif
38 #ifdef CONFIG_X11
39 #include "x11_common.h"
40 #endif
41 #include "libavutil/avstring.h"
43 #define SPU_SUPPORT
45 static const vo_info_t info =
47 "DXR3/H+ video out",
48 "dxr3",
49 "David Holm <dholm@iname.com>",
52 const LIBVO_EXTERN (dxr3)
54 /* Resolutions and positions */
55 static int v_width, v_height;
56 static int s_width, s_height;
57 static int osd_w, osd_h;
58 static int img_format;
60 /* Configuration values
61 * Don't declare these static, they
62 * should be accessible from the gui.
64 int dxr3_prebuf = 0;
65 int dxr3_newsync = 0;
66 int dxr3_overlay = 0;
67 int dxr3_device_num = 0;
68 int dxr3_norm = 0;
70 #define MAX_STR_SIZE 80 /* length for the static strings */
72 /* File descriptors */
73 static int fd_control = -1;
74 static int fd_video = -1;
75 static int fd_spu = -1;
76 static char fdv_name[MAX_STR_SIZE];
77 static char fds_name[MAX_STR_SIZE];
79 #ifdef SPU_SUPPORT
80 /* on screen display/subpics */
81 static char *osdpicbuf;
82 static int osdpicbuf_w;
83 static int osdpicbuf_h;
84 static int disposd;
85 static encodedata *spued;
86 static encodedata *spubuf;
87 #endif
90 /* Static variable used in ioctl's */
91 static int ioval;
92 static int prev_pts;
93 static int pts_offset;
94 static int old_vmode = -1;
97 /* Begin overlay.h */
99 Simple analog overlay API for DXR3/H+ linux driver.
101 Henrik Johansson
105 /* Pattern drawing callback used by the calibration functions.
106 The function is expected to:
107 Clear the entire screen.
108 Fill the screen with color bgcol (0xRRGGBB)
109 Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
112 typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
113 int xpos, int ypos, int width, int height, void *arg);
115 struct coeff {
116 float k,m;
119 typedef struct {
120 int dev;
122 int xres, yres,depth;
123 int xoffset,yoffset,xcorr;
124 int jitter;
125 int stability;
126 int keycolor;
127 struct coeff colcal_upper[3];
128 struct coeff colcal_lower[3];
129 float color_interval;
131 pattern_drawer_cb draw_pattern;
132 void *dp_arg;
133 } overlay_t;
136 static overlay_t *overlay_init(int dev);
137 static int overlay_release(overlay_t *);
139 static int overlay_read_state(overlay_t *o, char *path);
140 static int overlay_write_state(overlay_t *o, char *path);
142 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
143 static int overlay_set_mode(overlay_t *o, int mode);
144 static int overlay_set_attribute(overlay_t *o, int attribute, int val);
145 static int overlay_set_keycolor(overlay_t *o, int color);
146 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
147 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
149 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
150 static void overlay_update_params(overlay_t *o);
151 static int overlay_signalmode(overlay_t *o, int mode);
152 /* End overlay.h */
155 #ifdef CONFIG_X11
156 #define KEY_COLOR 0x80a040
157 static XWindowAttributes xwin_attribs;
158 static overlay_t *overlay_data;
159 #endif
162 /* Functions for working with the em8300's internal clock */
163 /* End of internal clock functions */
165 static int control(uint32_t request, void *data, ...)
167 switch (request) {
168 case VOCTRL_GUISUPPORT:
169 return VO_TRUE;
170 case VOCTRL_GUI_NOWINDOW:
171 if (dxr3_overlay) {
172 return VO_FALSE;
174 return VO_TRUE;
175 case VOCTRL_SET_SPU_PALETTE:
176 if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
177 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToLoadNewSPUPalette);
178 return VO_ERROR;
180 return VO_TRUE;
181 #ifdef CONFIG_X11
182 case VOCTRL_ONTOP:
183 vo_x11_ontop();
184 return VO_TRUE;
185 case VOCTRL_FULLSCREEN:
186 if (dxr3_overlay) {
187 vo_x11_fullscreen();
188 overlay_signalmode(overlay_data,
189 vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
190 EM8300_OVERLAY_SIGNAL_WITH_VGA);
191 return VO_TRUE;
193 return VO_FALSE;
194 #endif
195 case VOCTRL_RESUME:
196 if (dxr3_newsync) {
197 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
198 pts_offset = vo_pts - (ioval << 1);
199 if (pts_offset < 0) {
200 pts_offset = 0;
204 if (dxr3_prebuf) {
205 ioval = EM8300_PLAYMODE_PLAY;
206 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
207 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
210 return VO_TRUE;
211 case VOCTRL_PAUSE:
212 if (dxr3_prebuf) {
213 ioval = EM8300_PLAYMODE_PAUSED;
214 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
215 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
218 return VO_TRUE;
219 case VOCTRL_RESET:
220 if (dxr3_prebuf) {
221 close(fd_video);
222 fd_video = open(fdv_name, O_WRONLY);
223 close(fd_spu);
224 fd_spu = open(fds_name, O_WRONLY);
225 fsync(fd_video);
226 fsync(fd_spu);
228 return VO_TRUE;
229 case VOCTRL_QUERY_FORMAT:
231 uint32_t flag = 0;
233 if (*((uint32_t*)data) != IMGFMT_MPEGPES)
234 return 0;
236 flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
237 if (dxr3_prebuf)
238 flag |= VFCAP_TIMER;
239 return flag;
241 case VOCTRL_SET_EQUALIZER:
243 va_list ap;
244 int value;
245 em8300_bcs_t bcs;
247 va_start(ap, data);
248 value = va_arg(ap, int);
249 va_end(ap);
251 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
252 return VO_FALSE;
253 if (!strcasecmp(data, "brightness"))
254 bcs.brightness = (value+100)*5;
255 else if (!strcasecmp(data, "contrast"))
256 bcs.contrast = (value+100)*5;
257 else if (!strcasecmp(data, "saturation"))
258 bcs.saturation = (value+100)*5;
259 else return VO_FALSE;
261 if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
262 return VO_FALSE;
263 return VO_TRUE;
265 case VOCTRL_GET_EQUALIZER:
267 va_list ap;
268 int *value;
269 em8300_bcs_t bcs;
271 va_start(ap, data);
272 value = va_arg(ap, int*);
273 va_end(ap);
275 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
276 return VO_FALSE;
278 if (!strcasecmp(data, "brightness"))
279 *value = (bcs.brightness/5)-100;
280 else if (!strcasecmp(data, "contrast"))
281 *value = (bcs.contrast/5)-100;
282 else if (!strcasecmp(data, "saturation"))
283 *value = (bcs.saturation/5)-100;
284 else return VO_FALSE;
286 return VO_TRUE;
289 return VO_NOTIMPL;
292 void calculate_cvals(unsigned long mask, int *shift, int *prec)
294 /* Calculate shift and precision */
295 (*shift) = 0;
296 (*prec) = 0;
298 while (!(mask & 0x1)) {
299 (*shift)++;
300 mask >>= 1;
303 while (mask & 0x1) {
304 (*prec)++;
305 mask >>= 1;
309 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)
311 int tmp1, tmp2, size;
312 em8300_register_t reg;
313 extern float monitor_aspect;
315 /* Softzoom turned on, downscale */
316 /* This activates the subpicture processor, you can safely disable this and still send */
317 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
318 /* up in a lockup */
319 ioval = EM8300_SPUMODE_ON;
320 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
321 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetSubpictureMode);
322 uninit();
323 return -1;
326 /* Set the playmode to play (just in case another app has set it to something else) */
327 ioval = EM8300_PLAYMODE_PLAY;
328 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
329 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
332 /* Start em8300 prebuffering and sync engine */
333 reg.microcode_register = 1;
334 reg.reg = 0;
335 reg.val = MVCOMMAND_SYNC;
336 ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
338 /* Clean buffer by syncing it */
339 ioval = EM8300_SUBDEVICE_VIDEO;
340 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
341 ioval = EM8300_SUBDEVICE_AUDIO;
342 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
344 /* Sync the video device to make sure the buffers are empty
345 * and set the playback speed to normal. Also reset the
346 * em8300 internal clock.
348 fsync(fd_video);
349 ioval = 0x900;
350 ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
352 /* Store some variables statically that we need later in another scope */
353 img_format = format;
354 v_width = width;
355 v_height = height;
357 /* Set monitor_aspect to avoid jitter */
358 monitor_aspect = (float) width / (float) height;
360 if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
361 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToGetTVNorm);
362 old_vmode = -1;
365 /* adjust TV norm */
366 if (dxr3_norm != 0) {
367 if (dxr3_norm == 5) {
368 ioval = EM8300_VIDEOMODE_NTSC;
369 } else if (dxr3_norm == 4) {
370 ioval = EM8300_VIDEOMODE_PAL60;
371 } else if (dxr3_norm == 3) {
372 ioval = EM8300_VIDEOMODE_PAL;
373 } else if (dxr3_norm == 2) {
374 if (vo_fps > 28) {
375 ioval = EM8300_VIDEOMODE_PAL60;
376 } else {
377 ioval = EM8300_VIDEOMODE_PAL;
380 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
381 ioval == EM8300_VIDEOMODE_PAL60 ? mp_msg(MSGT_VO,MSGL_INFO, "PAL-60") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
382 printf(".\n");
383 } else {
384 if (vo_fps > 28) {
385 ioval = EM8300_VIDEOMODE_NTSC;
386 } else {
387 ioval = EM8300_VIDEOMODE_PAL;
390 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
391 ioval == EM8300_VIDEOMODE_NTSC ? mp_msg(MSGT_VO,MSGL_INFO, "NTSC") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
392 printf(".\n");
395 if (old_vmode != ioval) {
396 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
397 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetTVNorm);
403 /* libavcodec requires a width and height that is x|16 */
404 aspect_save_orig(width, height);
405 aspect_save_prescale(d_width, d_height);
406 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
407 if (ioval == EM8300_VIDEOMODE_NTSC) {
408 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForNTSC);
409 aspect_save_screenres(352, 240);
410 } else {
411 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForPALSECAM);
412 aspect_save_screenres(352, 288);
414 aspect(&s_width, &s_height, A_ZOOM);
415 s_width -= s_width % 16;
416 s_height -= s_height % 16;
418 /* Try to figure out whether to use widescreen output or not */
419 /* Anamorphic widescreen modes makes this a pain in the ass */
420 tmp1 = abs(d_height - ((d_width / 4) * 3));
421 tmp2 = abs(d_height - (int) (d_width / 2.35));
422 if (tmp1 < tmp2) {
423 ioval = EM8300_ASPECTRATIO_4_3;
424 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo43);
425 } else {
426 ioval = EM8300_ASPECTRATIO_16_9;
427 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo169);
429 ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
431 #ifdef SPU_SUPPORT
432 #ifdef CONFIG_FREETYPE
433 if (ioval == EM8300_ASPECTRATIO_16_9) {
434 s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
435 } else {
436 s_width *= 0.84;
438 //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
439 #else
440 s_width*=2;
441 s_height*=2;
442 #endif
444 osdpicbuf = calloc( 1,s_width * s_height);
445 if (osdpicbuf == NULL) {
446 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
447 return -1;
449 spued = (encodedata *) malloc(sizeof(encodedata));
450 if (spued == NULL) {
451 free( osdpicbuf );
452 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
453 return -1;
455 spubuf = (encodedata *) malloc(sizeof(encodedata));
456 if (spubuf == NULL) {
457 free( osdpicbuf );
458 free( spued );
459 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
460 return -1;
462 osd_w = s_width;
463 osd_h = s_height;
464 osdpicbuf_w = s_width;
465 osdpicbuf_h = s_height;
467 spubuf->count=0;
468 pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
470 #endif
472 #ifdef CONFIG_X11
473 if (dxr3_overlay) {
474 XVisualInfo vinfo;
475 XSetWindowAttributes xswa;
476 XSizeHints hint;
477 unsigned long xswamask;
478 Colormap cmap;
479 XColor key_color;
480 Window junkwindow;
481 Screen *scr;
482 int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
483 em8300_overlay_screen_t ovlscr;
484 em8300_attribute_t ovlattr;
486 vo_dx = (vo_screenwidth - d_width) / 2;
487 vo_dy = (vo_screenheight - d_height) / 2;
488 vo_dwidth = d_width;
489 vo_dheight = d_height;
490 #ifdef CONFIG_GUI
491 if (use_gui) {
492 guiGetEvent(guiSetShVideo, 0);
493 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
494 XClearWindow(mDisplay, vo_window);
495 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
496 depth = xwin_attribs.depth;
497 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
498 depth = 24;
500 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
501 } else
502 #endif
504 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
505 depth = xwin_attribs.depth;
506 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
507 depth = 24;
509 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
510 vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy,
511 d_width, d_height, flags,
512 CopyFromParent, "Viewing Window", title);
513 xswa.background_pixel = KEY_COLOR;
514 xswa.border_pixel = 0;
515 xswamask = CWBackPixel | CWBorderPixel;
516 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa);
519 /* Start setting up overlay */
520 XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
521 overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
522 overlay_read_state(overlay_data, NULL);
524 /* Allocate keycolor */
525 cmap = vo_x11_create_colormap(&vinfo);
526 calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
527 calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
528 calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
530 key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
531 key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
532 key_color.blue = (KEY_COLOR & 0xff) * 256;
533 key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
534 ((key_color.green >> (16 - green_prec)) << green_shift) +
535 ((key_color.blue >> (16 - blue_prec)) << blue_shift));
536 key_color.flags = DoRed | DoGreen | DoBlue;
537 if (!XAllocColor(mDisplay, cmap, &key_color)) {
538 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToAllocateKeycolor);
539 return -1;
542 acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
543 if (key_color.pixel != KEY_COLOR) {
544 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToAllocateExactKeycolor, key_color.pixel);
547 /* Set keycolor and activate overlay */
548 XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
549 XClearWindow(mDisplay, vo_window);
550 overlay_set_keycolor(overlay_data, key_color.pixel);
551 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
552 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
554 #endif
556 return 0;
559 static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
561 #ifdef SPU_SUPPORT
562 unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
563 int by = 0;
564 register int lx, ly;
565 register int stride = 0;
567 for (ly = 0; ly < h - 1; ly++)
569 for(lx = 0; lx < w; lx++ )
570 if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
571 by+=osdpicbuf_w;
572 stride+=srcstride;
574 pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
575 #endif
578 extern int vo_osd_changed_flag;
579 extern mp_osd_obj_t* vo_osd_list;
581 static void draw_osd(void)
583 #ifdef SPU_SUPPORT
584 static int cleared = 0;
585 int changed = 0;
587 if ((disposd % 15) == 0)
590 mp_osd_obj_t* obj = vo_osd_list;
591 vo_update_osd( osd_w,osd_h );
592 while( obj )
594 if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
595 obj=obj->next;
598 if ( changed )
600 vo_draw_text(osd_w, osd_h, draw_alpha);
601 memset(osdpicbuf, 0, s_width * s_height);
602 cleared=0;
604 else
606 if ( !cleared )
608 spued->count=spubuf->count;
609 fast_memcpy( spued->data,spubuf->data,DATASIZE );
610 cleared=1;
615 /* could stand some check here to see if the subpic hasn't changed
616 * as if it hasn't and we re-send it it will "blink" as the last one
617 * is turned off, and the new one (same one) is turned on
619 /* Subpics are not stable yet =(
620 expect lockups if you enable */
621 #if 1
622 write(fd_spu, spued->data, spued->count);
623 #endif
625 disposd++;
626 #endif
630 static int draw_frame(uint8_t * src[])
632 vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
634 #ifdef SPU_SUPPORT
635 if (p->id == 0x20) {
636 write(fd_spu, p->data, p->size);
637 } else
638 #endif
639 write(fd_video, p->data, p->size);
640 return 0;
643 static void flip_page(void)
645 #ifdef CONFIG_X11
646 if (dxr3_overlay) {
647 int event = vo_x11_check_events(mDisplay);
648 if (event & VO_EVENT_RESIZE) {
649 Window junkwindow;
650 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
651 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
652 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
654 if (event & VO_EVENT_EXPOSE) {
655 Window junkwindow;
656 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
657 XClearWindow(mDisplay, vo_window);
658 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
659 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
660 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
663 #endif
665 if (dxr3_newsync) {
666 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
667 ioval <<= 1;
668 if (vo_pts == 0) {
669 ioval = 0;
670 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
671 pts_offset = 0;
672 } else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
673 ioval = (vo_pts + pts_offset) >> 1;
674 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
675 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
676 pts_offset = vo_pts - (ioval << 1);
677 if (pts_offset < 0) {
678 pts_offset = 0;
681 ioval = vo_pts + pts_offset;
682 ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
683 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
684 prev_pts = vo_pts;
685 } else if (dxr3_prebuf) {
686 ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
687 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
691 static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
693 return -1;
696 static void uninit(void)
698 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Uninitializing);
699 #ifdef CONFIG_X11
700 if (dxr3_overlay) {
701 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
702 overlay_release(overlay_data);
704 #ifdef CONFIG_GUI
705 if (!use_gui) {
706 #endif
707 vo_x11_uninit();
709 #ifdef CONFIG_GUI
711 #endif
713 #endif
714 if (old_vmode != -1) {
715 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
716 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedRestoringTVNorm);
720 if (fd_video) {
721 close(fd_video);
723 if (fd_spu) {
724 close(fd_spu);
726 if (fd_control) {
727 close(fd_control);
729 #ifdef SPU_SUPPORT
730 if(osdpicbuf) {
731 free(osdpicbuf);
733 if(spued) {
734 free(spued);
736 #endif
739 static void check_events(void)
743 static int preinit(const char *arg)
745 char devname[MAX_STR_SIZE];
746 int fdflags = O_WRONLY;
748 /* Parse commandline */
749 while (arg) {
750 if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
751 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_EnablingPrebuffering);
752 dxr3_prebuf = 1;
753 } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
754 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingNewSyncEngine);
755 dxr3_newsync = 1;
756 } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
757 #ifdef CONFIG_X11
758 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingOverlay);
759 dxr3_overlay = 1;
760 #else
761 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorYouNeedToCompileMplayerWithX11);
762 #endif
763 } else if (!strncmp("norm=", arg, 5)) {
764 arg += 5;
765 // dxr3_norm is 0 (-> don't change norm) by default
766 // but maybe someone changes this in the future
768 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_WillSetTVNormTo);
770 if (*arg == '5') {
771 dxr3_norm = 5;
772 mp_msg(MSGT_VO,MSGL_INFO, "NTSC");
773 } else if (*arg == '4') {
774 dxr3_norm = 4;
775 mp_msg(MSGT_VO,MSGL_INFO, "PAL-60");
776 } else if (*arg == '3') {
777 dxr3_norm = 3;
778 mp_msg(MSGT_VO,MSGL_INFO, "PAL");
779 } else if (*arg == '2') {
780 dxr3_norm = 2;
781 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALPAL60);
782 } else if (*arg == '1') {
783 dxr3_norm = 1;
784 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALNTSC);
785 } else if (*arg == '0') {
786 dxr3_norm = 0;
787 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseCurrentNorm);
788 } else {
789 dxr3_norm = 0;
790 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseUnknownNormSuppliedCurrentNorm);
793 mp_msg(MSGT_VO,MSGL_INFO, ".\n");
794 } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
795 dxr3_device_num = arg[0];
798 arg = strchr(arg, ':');
799 if (arg) {
800 arg++;
805 /* Open the control interface */
806 sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
807 fd_control = open(devname, fdflags);
808 if (fd_control < 1) {
809 /* Fall back to old naming scheme */
810 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTrying, devname);
811 sprintf(devname, "/dev/em8300");
812 fd_control = open(devname, fdflags);
813 if (fd_control < 1) {
814 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWell);
815 return -1;
817 } else {
818 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
821 /* Open the video interface */
822 sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
823 fd_video = open(devname, fdflags);
824 if (fd_video < 0) {
825 /* Fall back to old naming scheme */
826 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingMV, devname);
827 sprintf(devname, "/dev/em8300_mv");
828 fd_video = open(devname, fdflags);
829 if (fd_video < 0) {
830 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellMV);
831 uninit();
832 return -1;
834 } else {
835 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
837 strcpy(fdv_name, devname);
839 /* Open the subpicture interface */
840 sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
841 fd_spu = open(devname, fdflags);
842 if (fd_spu < 0) {
843 /* Fall back to old naming scheme */
844 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingSP, devname);
845 sprintf(devname, "/dev/em8300_sp");
846 fd_spu = open(devname, fdflags);
847 if (fd_spu < 0) {
848 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellSP);
849 uninit();
850 return -1;
852 } else {
853 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
855 strcpy(fds_name, devname);
857 #ifdef CONFIG_X11
858 if (dxr3_overlay) {
860 /* Fucked up hack needed to enable overlay.
861 * Will be removed as soon as I figure out
862 * how to make it work like it should
864 Display *dpy;
865 overlay_t *ov;
866 XWindowAttributes attribs;
868 dpy = XOpenDisplay(NULL);
869 if (!dpy) {
870 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToOpenDisplayDuringHackSetup);
871 return -1;
873 XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
874 ov = overlay_init(fd_control);
875 overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
876 overlay_read_state(ov, NULL);
877 overlay_set_keycolor(ov, KEY_COLOR);
878 overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
879 overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
880 overlay_release(ov);
881 XCloseDisplay(dpy);
882 /* End of fucked up hack */
884 /* Initialize overlay and X11 */
885 overlay_data = overlay_init(fd_control);
886 #ifdef CONFIG_GUI
887 if (!use_gui) {
888 #endif
889 if (!vo_init()) {
890 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToInitX11);
891 return -1;
893 #ifdef CONFIG_GUI
895 #endif
897 #endif
899 if (dxr3_newsync) {
900 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
901 pts_offset = vo_pts - (ioval << 1);
902 if (pts_offset < 0) {
903 pts_offset = 0;
907 return 0;
910 /* Begin overlay.c */
911 static int update_parameters(overlay_t *o)
913 overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
914 overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
915 overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
916 overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
917 overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
918 return 0;
921 static int overlay_set_attribute(overlay_t *o, int attribute, int value)
923 em8300_attribute_t attr;
925 attr.attribute = attribute;
926 attr.value = value;
927 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
929 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayAttribute);
930 return -1;
933 return 0;
936 static overlay_t *overlay_init(int dev)
938 overlay_t *o;
940 o = (overlay_t *) malloc(sizeof(overlay_t));
942 if(!o)
943 return NULL;
945 memset(o,0,sizeof(overlay_t));
947 o->dev = dev;
948 o->xres = 1280; o->yres=1024; o->xcorr=1000;
949 o->color_interval=10;
951 return o;
954 static int overlay_release(overlay_t *o)
956 if(o)
957 free(o);
959 return 0;
961 #define TYPE_INT 1
962 #define TYPE_XINT 2
963 #define TYPE_COEFF 3
964 #define TYPE_FLOAT 4
966 struct lut_entry {
967 char *name;
968 int type;
969 void *ptr;
972 static struct lut_entry *new_lookuptable(overlay_t *o)
974 struct lut_entry m[] = {
975 {"xoffset", TYPE_INT, &o->xoffset},
976 {"yoffset", TYPE_INT, &o->yoffset},
977 {"xcorr", TYPE_INT, &o->xcorr},
978 {"jitter", TYPE_INT, &o->jitter},
979 {"stability", TYPE_INT, &o->stability},
980 {"keycolor", TYPE_XINT, &o->keycolor},
981 {"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
982 {"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
983 {"color_interval", TYPE_FLOAT, &o->color_interval},
984 {0,0,0}
985 },*p;
987 p = malloc(sizeof(m));
988 memcpy(p,m,sizeof(m));
989 return p;
992 static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
993 int i;
995 for(i=0; lut[i].name; i++) {
996 if(!strcmp(name,lut[i].name)) {
997 *ptr = lut[i].ptr;
998 *type = lut[i].type;
999 return 1;
1002 return 0;
1005 static int overlay_read_state(overlay_t *o, char *p)
1007 char *a,*tok;
1008 char path[128],fname[128],tmp[128],line[256];
1009 FILE *fp;
1010 struct lut_entry *lut;
1011 void *ptr;
1012 int type;
1013 int j;
1015 if(!p) {
1016 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1017 av_strlcat(fname,"/.overlay", sizeof( fname ));
1018 } else
1019 av_strlcpy(fname, p, sizeof( fname ));
1021 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1022 av_strlcat(fname, tmp, sizeof( fname ));
1024 if(!(fp=fopen(fname,"r")))
1025 return -1;
1027 lut = new_lookuptable(o);
1029 while(!feof(fp)) {
1030 if(!fgets(line,256,fp))
1031 break;
1032 tok=strtok(line," ");
1033 if(lookup_parameter(o,lut,tok,&ptr,&type)) {
1034 tok=strtok(NULL," ");
1035 switch(type) {
1036 case TYPE_INT:
1037 sscanf(tok,"%d",(int *)ptr);
1038 break;
1039 case TYPE_XINT:
1040 sscanf(tok,"%x",(int *)ptr);
1041 break;
1042 case TYPE_FLOAT:
1043 sscanf(tok,"%f",(float *)ptr);
1044 break;
1045 case TYPE_COEFF:
1046 for(j=0;j<3;j++) {
1047 sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1048 tok=strtok(NULL," ");
1049 sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1050 tok=strtok(NULL," ");
1052 break;
1058 update_parameters(o);
1060 free(lut);
1061 fclose(fp);
1062 return 0;
1065 static void overlay_update_params(overlay_t *o) {
1066 update_parameters(o);
1069 static int overlay_write_state(overlay_t *o, char *p)
1071 char *a;
1072 char path[128],fname[128],tmp[128];
1073 FILE *fp;
1074 char line[256],*tok;
1075 struct lut_entry *lut;
1076 int i,j;
1078 if(!p) {
1079 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1080 av_strlcat(fname,"/.overlay", sizeof( fname ));
1081 } else
1082 av_strlcpy(fname, p, sizeof( fname ));
1084 if(access(fname, W_OK|X_OK|R_OK)) {
1085 if(mkdir(fname,0766))
1086 return -1;
1089 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1090 av_strlcat(fname, tmp, sizeof( fname ));
1092 if(!(fp=fopen(fname,"w")))
1093 return -1;
1095 lut = new_lookuptable(o);
1097 for(i=0; lut[i].name; i++) {
1098 fprintf(fp,"%s ",lut[i].name);
1099 switch(lut[i].type) {
1100 case TYPE_INT:
1101 fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1102 break;
1103 case TYPE_XINT:
1104 fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1105 break;
1106 case TYPE_FLOAT:
1107 fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1108 break;
1109 case TYPE_COEFF:
1110 for(j=0;j<3;j++)
1111 fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1112 ((struct coeff *)lut[i].ptr)[j].m);
1113 fprintf(fp,"\n");
1114 break;
1118 fclose(fp);
1119 return 0;
1122 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1124 em8300_overlay_screen_t scr;
1126 o->xres = xres;
1127 o->yres = yres;
1128 o->depth = depth;
1130 scr.xsize = xres;
1131 scr.ysize = yres;
1133 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1135 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayScreen);
1136 return -1;
1138 return 0;
1141 static int overlay_set_mode(overlay_t *o, int mode)
1143 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1144 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedEnablingOverlay);
1145 return -1;
1147 return 0;
1150 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1152 em8300_overlay_window_t win;
1153 win.xpos = xpos;
1154 win.ypos = ypos;
1155 win.width = width;
1156 win.height = height;
1158 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1160 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1161 return -1;
1163 return 0;
1166 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1168 em8300_bcs_t bcs;
1169 bcs.brightness = brightness;
1170 bcs.contrast = contrast;
1171 bcs.saturation = saturation;
1173 if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1175 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayBcs);
1176 return -1;
1178 return 0;
1181 static int col_interp(float x, struct coeff c)
1183 float y;
1184 y = x*c.k + c.m;
1185 if(y > 255)
1186 y = 255;
1187 if(y < 0)
1188 y = 0;
1189 return rint(y);
1192 static int overlay_set_keycolor(overlay_t *o, int color) {
1193 int r = (color & 0xff0000) >> 16;
1194 int g = (color & 0x00ff00) >> 8;
1195 int b = (color & 0x0000ff);
1196 float ru,gu,bu;
1197 float rl,gl,bl;
1198 int upper,lower;
1200 ru = r+o->color_interval;
1201 gu = g+o->color_interval;
1202 bu = b+o->color_interval;
1204 rl = r-o->color_interval;
1205 gl = g-o->color_interval;
1206 bl = b-o->color_interval;
1208 upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1209 (col_interp(gu, o->colcal_upper[1]) << 8) |
1210 (col_interp(bu, o->colcal_upper[2]));
1212 lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1213 (col_interp(gl, o->colcal_lower[1]) << 8) |
1214 (col_interp(bl, o->colcal_lower[2]));
1216 //printf("0x%06x 0x%06x\n",upper,lower);
1217 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1218 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1219 return 0;
1222 static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1224 float sx=0,sy=0,sxx=0,sxy=0;
1225 float delta,b;
1226 int i;
1228 for(i=0; i < n; i++) {
1229 sx=sx+x[i];
1230 sy=sy+y[i];
1231 sxx=sxx+x[i]*x[i];
1232 sxy=sxy+x[i]*y[i];
1235 delta=sxx*n-sx*sx;
1237 *m=(sxx*sy-sx*sxy)/delta;
1238 *k=(sxy*n-sx*sy)/delta;
1241 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1243 em8300_overlay_calibrate_t cal;
1244 em8300_overlay_window_t win;
1245 int x[256],r[256],g[256],b[256],n;
1246 float k,m;
1248 int i;
1250 o->draw_pattern=pd;
1251 o->dp_arg = arg;
1253 overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1254 overlay_set_screen(o, o->xres, o->yres, o->depth);
1256 /* Calibrate Y-offset */
1258 o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1260 cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1261 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1263 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayYOffsetValues);
1264 return -1;
1266 o->yoffset = cal.result;
1267 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_YOffset,cal.result);
1269 /* Calibrate X-offset */
1271 o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1273 cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1274 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1276 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXOffsetValues);
1277 return -1;
1279 o->xoffset = cal.result;
1280 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XOffset,cal.result);
1282 /* Calibrate X scale correction */
1284 o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1286 cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1287 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1289 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXScaleCorrection);
1290 return -1;
1292 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XCorrection,cal.result);
1293 o->xcorr = cal.result;
1295 win.xpos = 10;
1296 win.ypos = 10;
1297 win.width = o->xres-20;
1298 win.height = o->yres-20;
1299 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1300 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1301 exit(1);
1304 /* Calibrate key color upper limit */
1306 for(i=128,n=0; i <= 0xff; i+=4) {
1307 o->draw_pattern(i | (i << 8) | (i << 16), 0,
1308 (o->xres-200)/2,0,200,o->yres,o->dp_arg);
1310 cal.arg = i;
1311 cal.arg2 = 1;
1312 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1314 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1316 return -1 ;
1319 x[n] = i;
1320 r[n] = (cal.result>>16)&0xff;
1321 g[n] = (cal.result>>8)&0xff;
1322 b[n] = (cal.result)&0xff;
1323 n++;
1326 least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1327 least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1328 least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1330 /* Calibrate key color lower limit */
1332 for(i=128,n=0; i <= 0xff; i+=4) {
1333 o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1334 (o->xres-200)/2,0,200,o->yres, o->dp_arg);
1336 cal.arg = i;
1337 cal.arg2 = 2;
1338 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1340 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1342 return -1 ;
1344 x[n] = i;
1345 r[n] = (cal.result>>16)&0xff;
1346 g[n] = (cal.result>>8)&0xff;
1347 b[n] = (cal.result)&0xff;
1348 n++;
1351 least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1352 least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1353 least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1355 overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1357 return 0;
1361 static int overlay_signalmode(overlay_t *o, int mode) {
1362 if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1363 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSetSignalMix);
1364 return -1;
1366 return 0;
1368 /* End overlay.c */