Merge svn changes up to r29455
[mplayer.git] / libvo / vo_dxr3.c
blob898ee967560c095215405c53593880fdc982b017
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 #include "fastmemcpy.h"
42 #include "video_out.h"
43 #include "video_out_internal.h"
44 #include "aspect.h"
45 #include "spuenc.h"
46 #include "sub.h"
47 #ifdef CONFIG_X11
48 #include "x11_common.h"
49 #endif
50 #include "libavutil/avstring.h"
52 #define SPU_SUPPORT
54 static const vo_info_t info =
56 "DXR3/H+ video out",
57 "dxr3",
58 "David Holm <dholm@iname.com>",
61 const LIBVO_EXTERN (dxr3)
63 /* Resolutions and positions */
64 static int v_width, v_height;
65 static int s_width, s_height;
66 static int osd_w, osd_h;
67 static int img_format;
69 /* Configuration values
70 * Don't declare these static, they
71 * should be accessible from the gui.
73 int dxr3_prebuf = 0;
74 int dxr3_newsync = 0;
75 int dxr3_overlay = 0;
76 int dxr3_device_num = 0;
77 int dxr3_norm = 0;
79 #define MAX_STR_SIZE 80 /* length for the static strings */
81 /* File descriptors */
82 static int fd_control = -1;
83 static int fd_video = -1;
84 static int fd_spu = -1;
85 static char fdv_name[MAX_STR_SIZE];
86 static char fds_name[MAX_STR_SIZE];
88 #ifdef SPU_SUPPORT
89 /* on screen display/subpics */
90 static char *osdpicbuf;
91 static int osdpicbuf_w;
92 static int osdpicbuf_h;
93 static int disposd;
94 static encodedata *spued;
95 static encodedata *spubuf;
96 #endif
99 /* Static variable used in ioctl's */
100 static int ioval;
101 static int prev_pts;
102 static int pts_offset;
103 static int old_vmode = -1;
106 /* Begin overlay.h */
108 Simple analog overlay API for DXR3/H+ linux driver.
110 Henrik Johansson
114 /* Pattern drawing callback used by the calibration functions.
115 The function is expected to:
116 Clear the entire screen.
117 Fill the screen with color bgcol (0xRRGGBB)
118 Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
121 typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
122 int xpos, int ypos, int width, int height, void *arg);
124 struct coeff {
125 float k,m;
128 typedef struct {
129 int dev;
131 int xres, yres,depth;
132 int xoffset,yoffset,xcorr;
133 int jitter;
134 int stability;
135 int keycolor;
136 struct coeff colcal_upper[3];
137 struct coeff colcal_lower[3];
138 float color_interval;
140 pattern_drawer_cb draw_pattern;
141 void *dp_arg;
142 } overlay_t;
145 static overlay_t *overlay_init(int dev);
146 static int overlay_release(overlay_t *);
148 static int overlay_read_state(overlay_t *o, char *path);
149 static int overlay_write_state(overlay_t *o, char *path);
151 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
152 static int overlay_set_mode(overlay_t *o, int mode);
153 static int overlay_set_attribute(overlay_t *o, int attribute, int val);
154 static int overlay_set_keycolor(overlay_t *o, int color);
155 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
156 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
158 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
159 static void overlay_update_params(overlay_t *o);
160 static int overlay_signalmode(overlay_t *o, int mode);
161 /* End overlay.h */
164 #ifdef CONFIG_X11
165 #define KEY_COLOR 0x80a040
166 static XWindowAttributes xwin_attribs;
167 static overlay_t *overlay_data;
168 #endif
171 /* Functions for working with the em8300's internal clock */
172 /* End of internal clock functions */
174 static int control(uint32_t request, void *data)
176 switch (request) {
177 case VOCTRL_SET_SPU_PALETTE:
178 if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
179 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to load new SPU palette!\n");
180 return VO_ERROR;
182 return VO_TRUE;
183 #ifdef CONFIG_X11
184 case VOCTRL_ONTOP:
185 vo_x11_ontop();
186 return VO_TRUE;
187 case VOCTRL_FULLSCREEN:
188 if (dxr3_overlay) {
189 vo_x11_fullscreen();
190 overlay_signalmode(overlay_data,
191 vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
192 EM8300_OVERLAY_SIGNAL_WITH_VGA);
193 return VO_TRUE;
195 return VO_FALSE;
196 #endif
197 case VOCTRL_RESUME:
198 if (dxr3_newsync) {
199 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
200 pts_offset = vo_pts - (ioval << 1);
201 if (pts_offset < 0) {
202 pts_offset = 0;
206 if (dxr3_prebuf) {
207 ioval = EM8300_PLAYMODE_PLAY;
208 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
209 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set playmode!\n");
212 return VO_TRUE;
213 case VOCTRL_PAUSE:
214 if (dxr3_prebuf) {
215 ioval = EM8300_PLAYMODE_PAUSED;
216 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
217 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set playmode!\n");
220 return VO_TRUE;
221 case VOCTRL_RESET:
222 if (dxr3_prebuf) {
223 close(fd_video);
224 fd_video = open(fdv_name, O_WRONLY);
225 close(fd_spu);
226 fd_spu = open(fds_name, O_WRONLY);
227 fsync(fd_video);
228 fsync(fd_spu);
230 return VO_TRUE;
231 case VOCTRL_QUERY_FORMAT:
233 uint32_t flag = 0;
235 if (*((uint32_t*)data) != IMGFMT_MPEGPES)
236 return 0;
238 flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
239 if (dxr3_prebuf)
240 flag |= VFCAP_TIMER;
241 return flag;
243 case VOCTRL_SET_EQUALIZER:
245 em8300_bcs_t bcs;
246 struct voctrl_set_equalizer_args *args = data;
248 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
249 return VO_FALSE;
250 if (!strcasecmp(args->name, "brightness"))
251 bcs.brightness = (args->value+100)*5;
252 else if (!strcasecmp(args->name, "contrast"))
253 bcs.contrast = (args->value+100)*5;
254 else if (!strcasecmp(args->name, "saturation"))
255 bcs.saturation = (args->value+100)*5;
256 else return VO_FALSE;
258 if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
259 return VO_FALSE;
260 return VO_TRUE;
262 case VOCTRL_GET_EQUALIZER:
264 em8300_bcs_t bcs;
265 struct voctrl_get_equalizer_args *args = data;
267 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
268 return VO_FALSE;
270 if (!strcasecmp(args->name, "brightness"))
271 *args->valueptr = (bcs.brightness/5)-100;
272 else if (!strcasecmp(args->name, "contrast"))
273 *args->valueptr = (bcs.contrast/5)-100;
274 else if (!strcasecmp(args->name, "saturation"))
275 *args->valueptr = (bcs.saturation/5)-100;
276 else return VO_FALSE;
278 return VO_TRUE;
281 return VO_NOTIMPL;
284 void calculate_cvals(unsigned long mask, int *shift, int *prec)
286 /* Calculate shift and precision */
287 (*shift) = 0;
288 (*prec) = 0;
290 while (!(mask & 0x1)) {
291 (*shift)++;
292 mask >>= 1;
295 while (mask & 0x1) {
296 (*prec)++;
297 mask >>= 1;
301 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)
303 int tmp1, tmp2, size;
304 em8300_register_t reg;
306 /* Softzoom turned on, downscale */
307 /* This activates the subpicture processor, you can safely disable this and still send */
308 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
309 /* up in a lockup */
310 ioval = EM8300_SPUMODE_ON;
311 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
312 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set subpicture mode!\n");
313 uninit();
314 return -1;
317 /* Set the playmode to play (just in case another app has set it to something else) */
318 ioval = EM8300_PLAYMODE_PLAY;
319 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
320 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set playmode!\n");
323 /* Start em8300 prebuffering and sync engine */
324 reg.microcode_register = 1;
325 reg.reg = 0;
326 reg.val = MVCOMMAND_SYNC;
327 ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
329 /* Clean buffer by syncing it */
330 ioval = EM8300_SUBDEVICE_VIDEO;
331 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
332 ioval = EM8300_SUBDEVICE_AUDIO;
333 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
335 /* Sync the video device to make sure the buffers are empty
336 * and set the playback speed to normal. Also reset the
337 * em8300 internal clock.
339 fsync(fd_video);
340 ioval = 0x900;
341 ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
343 /* Store some variables statically that we need later in another scope */
344 img_format = format;
345 v_width = width;
346 v_height = height;
348 /* Set monitor_aspect to avoid jitter */
349 monitor_aspect = (float) width / (float) height;
351 if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
352 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to get TV norm!\n");
353 old_vmode = -1;
356 /* adjust TV norm */
357 if (dxr3_norm != 0) {
358 if (dxr3_norm == 5) {
359 ioval = EM8300_VIDEOMODE_NTSC;
360 } else if (dxr3_norm == 4) {
361 ioval = EM8300_VIDEOMODE_PAL60;
362 } else if (dxr3_norm == 3) {
363 ioval = EM8300_VIDEOMODE_PAL;
364 } else if (dxr3_norm == 2) {
365 if (vo_fps > 28) {
366 ioval = EM8300_VIDEOMODE_PAL60;
367 } else {
368 ioval = EM8300_VIDEOMODE_PAL;
371 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Auto-selected TV norm by framerate: ");
372 ioval == EM8300_VIDEOMODE_PAL60 ? mp_msg(MSGT_VO,MSGL_INFO, "PAL-60") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
373 printf(".\n");
374 } else {
375 if (vo_fps > 28) {
376 ioval = EM8300_VIDEOMODE_NTSC;
377 } else {
378 ioval = EM8300_VIDEOMODE_PAL;
381 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Auto-selected TV norm by framerate: ");
382 ioval == EM8300_VIDEOMODE_NTSC ? mp_msg(MSGT_VO,MSGL_INFO, "NTSC") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
383 printf(".\n");
386 if (old_vmode != ioval) {
387 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
388 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set TV norm!\n");
394 /* libavcodec requires a width and height that is x|16 */
395 aspect_save_orig(width, height);
396 aspect_save_prescale(d_width, d_height);
397 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
398 if (ioval == EM8300_VIDEOMODE_NTSC) {
399 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting up for NTSC.\n");
400 aspect_save_screenres(352, 240);
401 } else {
402 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting up for PAL/SECAM.\n");
403 aspect_save_screenres(352, 288);
405 aspect(&s_width, &s_height, A_ZOOM);
406 s_width -= s_width % 16;
407 s_height -= s_height % 16;
409 /* Try to figure out whether to use widescreen output or not */
410 /* Anamorphic widescreen modes makes this a pain in the ass */
411 tmp1 = abs(d_height - ((d_width / 4) * 3));
412 tmp2 = abs(d_height - (int) (d_width / 2.35));
413 if (tmp1 < tmp2) {
414 ioval = EM8300_ASPECTRATIO_4_3;
415 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting aspect ratio to 4:3.\n");
416 } else {
417 ioval = EM8300_ASPECTRATIO_16_9;
418 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting aspect ratio to 16:9.\n");
420 ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
422 #ifdef SPU_SUPPORT
423 #ifdef CONFIG_FREETYPE
424 if (ioval == EM8300_ASPECTRATIO_16_9) {
425 s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
426 } else {
427 s_width *= 0.84;
429 //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
430 #else
431 s_width*=2;
432 s_height*=2;
433 #endif
435 osdpicbuf = calloc( 1,s_width * s_height);
436 if (osdpicbuf == NULL) {
437 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] out of memory\n");
438 return -1;
440 spued = (encodedata *) malloc(sizeof(encodedata));
441 if (spued == NULL) {
442 free( osdpicbuf );
443 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] out of memory\n");
444 return -1;
446 spubuf = (encodedata *) malloc(sizeof(encodedata));
447 if (spubuf == NULL) {
448 free( osdpicbuf );
449 free( spued );
450 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] out of memory\n");
451 return -1;
453 osd_w = s_width;
454 osd_h = s_height;
455 osdpicbuf_w = s_width;
456 osdpicbuf_h = s_height;
458 spubuf->count=0;
459 pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
461 #endif
463 #ifdef CONFIG_X11
464 if (dxr3_overlay) {
465 XVisualInfo vinfo;
466 XSetWindowAttributes xswa;
467 XSizeHints hint;
468 unsigned long xswamask;
469 Colormap cmap;
470 XColor key_color;
471 Window junkwindow;
472 Screen *scr;
473 int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
474 em8300_overlay_screen_t ovlscr;
475 em8300_attribute_t ovlattr;
477 vo_dx = (vo_screenwidth - d_width) / 2;
478 vo_dy = (vo_screenheight - d_height) / 2;
479 vo_dwidth = d_width;
480 vo_dheight = d_height;
482 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
483 depth = xwin_attribs.depth;
484 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
485 depth = 24;
487 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
488 vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy,
489 d_width, d_height, flags,
490 CopyFromParent, "Viewing Window", title);
491 xswa.background_pixel = KEY_COLOR;
492 xswa.border_pixel = 0;
493 xswamask = CWBackPixel | CWBorderPixel;
494 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa);
497 /* Start setting up overlay */
498 XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
499 overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
500 overlay_read_state(overlay_data, NULL);
502 /* Allocate keycolor */
503 cmap = vo_x11_create_colormap(&vinfo);
504 calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
505 calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
506 calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
508 key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
509 key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
510 key_color.blue = (KEY_COLOR & 0xff) * 256;
511 key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
512 ((key_color.green >> (16 - green_prec)) << green_shift) +
513 ((key_color.blue >> (16 - blue_prec)) << blue_shift));
514 key_color.flags = DoRed | DoGreen | DoBlue;
515 if (!XAllocColor(mDisplay, cmap, &key_color)) {
516 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to allocate keycolor!\n");
517 return -1;
520 acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
521 if (key_color.pixel != KEY_COLOR) {
522 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to allocate exact keycolor, using closest match (0x%lx).\n", key_color.pixel);
525 /* Set keycolor and activate overlay */
526 XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
527 XClearWindow(mDisplay, vo_window);
528 overlay_set_keycolor(overlay_data, key_color.pixel);
529 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
530 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
532 #endif
534 return 0;
537 static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
539 #ifdef SPU_SUPPORT
540 unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
541 int by = 0;
542 register int lx, ly;
543 register int stride = 0;
545 for (ly = 0; ly < h - 1; ly++)
547 for(lx = 0; lx < w; lx++ )
548 if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
549 by+=osdpicbuf_w;
550 stride+=srcstride;
552 pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
553 #endif
556 extern int vo_osd_changed_flag;
557 extern mp_osd_obj_t* vo_osd_list;
559 static void draw_osd(void)
561 #ifdef SPU_SUPPORT
562 static int cleared = 0;
563 int changed = 0;
565 if ((disposd % 15) == 0)
568 mp_osd_obj_t* obj = vo_osd_list;
569 vo_update_osd( osd_w,osd_h );
570 while( obj )
572 if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
573 obj=obj->next;
576 if ( changed )
578 vo_draw_text(osd_w, osd_h, draw_alpha);
579 memset(osdpicbuf, 0, s_width * s_height);
580 cleared=0;
582 else
584 if ( !cleared )
586 spued->count=spubuf->count;
587 fast_memcpy( spued->data,spubuf->data,DATASIZE );
588 cleared=1;
593 /* could stand some check here to see if the subpic hasn't changed
594 * as if it hasn't and we re-send it it will "blink" as the last one
595 * is turned off, and the new one (same one) is turned on
597 /* Subpics are not stable yet =(
598 expect lockups if you enable */
599 #if 1
600 write(fd_spu, spued->data, spued->count);
601 #endif
603 disposd++;
604 #endif
608 static int draw_frame(uint8_t * src[])
610 vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
612 #ifdef SPU_SUPPORT
613 if (p->id == 0x20) {
614 write(fd_spu, p->data, p->size);
615 } else
616 #endif
617 write(fd_video, p->data, p->size);
618 return 0;
621 static void flip_page(void)
623 #ifdef CONFIG_X11
624 if (dxr3_overlay) {
625 int event = vo_x11_check_events(mDisplay);
626 if (event & VO_EVENT_RESIZE) {
627 Window junkwindow;
628 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
629 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
630 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
632 if (event & VO_EVENT_EXPOSE) {
633 Window junkwindow;
634 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
635 XClearWindow(mDisplay, vo_window);
636 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
637 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
638 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
641 #endif
643 if (dxr3_newsync) {
644 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
645 ioval <<= 1;
646 if (vo_pts == 0) {
647 ioval = 0;
648 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
649 pts_offset = 0;
650 } else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
651 ioval = (vo_pts + pts_offset) >> 1;
652 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
653 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
654 pts_offset = vo_pts - (ioval << 1);
655 if (pts_offset < 0) {
656 pts_offset = 0;
659 ioval = vo_pts + pts_offset;
660 ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
661 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
662 prev_pts = vo_pts;
663 } else if (dxr3_prebuf) {
664 ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
665 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
669 static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
671 return -1;
674 static void uninit(void)
676 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Uninitializing.\n");
677 #ifdef CONFIG_X11
678 if (dxr3_overlay) {
679 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
680 overlay_release(overlay_data);
682 vo_x11_uninit();
685 #endif
686 if (old_vmode != -1) {
687 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
688 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed restoring TV norm!\n");
692 if (fd_video) {
693 close(fd_video);
695 if (fd_spu) {
696 close(fd_spu);
698 if (fd_control) {
699 close(fd_control);
701 #ifdef SPU_SUPPORT
702 if(osdpicbuf) {
703 free(osdpicbuf);
705 if(spued) {
706 free(spued);
708 #endif
711 static void check_events(void)
715 static int preinit(const char *arg)
717 char devname[MAX_STR_SIZE];
718 int fdflags = O_WRONLY;
720 /* Parse commandline */
721 while (arg) {
722 if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
723 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Enabling prebuffering.\n");
724 dxr3_prebuf = 1;
725 } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
726 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Using new sync engine.\n");
727 dxr3_newsync = 1;
728 } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
729 #ifdef CONFIG_X11
730 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Using overlay.\n");
731 dxr3_overlay = 1;
732 #else
733 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error: Overlay requires compiling with X11 libs/headers installed.\n");
734 #endif
735 } else if (!strncmp("norm=", arg, 5)) {
736 arg += 5;
737 // dxr3_norm is 0 (-> don't change norm) by default
738 // but maybe someone changes this in the future
740 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Will set TV norm to: ");
742 if (*arg == '5') {
743 dxr3_norm = 5;
744 mp_msg(MSGT_VO,MSGL_INFO, "NTSC");
745 } else if (*arg == '4') {
746 dxr3_norm = 4;
747 mp_msg(MSGT_VO,MSGL_INFO, "PAL-60");
748 } else if (*arg == '3') {
749 dxr3_norm = 3;
750 mp_msg(MSGT_VO,MSGL_INFO, "PAL");
751 } else if (*arg == '2') {
752 dxr3_norm = 2;
753 mp_tmsg(MSGT_VO,MSGL_INFO, "auto-adjust to movie framerate (PAL/PAL-60)");
754 } else if (*arg == '1') {
755 dxr3_norm = 1;
756 mp_tmsg(MSGT_VO,MSGL_INFO, "auto-adjust to movie framerate (PAL/NTSC)");
757 } else if (*arg == '0') {
758 dxr3_norm = 0;
759 mp_tmsg(MSGT_VO,MSGL_INFO, "Use current norm.");
760 } else {
761 dxr3_norm = 0;
762 mp_tmsg(MSGT_VO,MSGL_INFO, "Unknown norm supplied. Use current norm.");
765 mp_msg(MSGT_VO,MSGL_INFO, ".\n");
766 } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
767 dxr3_device_num = arg[0];
770 arg = strchr(arg, ':');
771 if (arg) {
772 arg++;
777 /* Open the control interface */
778 sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
779 fd_control = open(devname, fdflags);
780 if (fd_control < 1) {
781 /* Fall back to old naming scheme */
782 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error opening %s for writing, trying /dev/em8300 instead.\n", devname);
783 sprintf(devname, "/dev/em8300");
784 fd_control = open(devname, fdflags);
785 if (fd_control < 1) {
786 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Error opening /dev/em8300 for writing as well!\nBailing out.\n");
787 return -1;
789 } else {
790 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Opened: %s.\n", devname);
793 /* Open the video interface */
794 sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
795 fd_video = open(devname, fdflags);
796 if (fd_video < 0) {
797 /* Fall back to old naming scheme */
798 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_mv instead.\n", devname);
799 sprintf(devname, "/dev/em8300_mv");
800 fd_video = open(devname, fdflags);
801 if (fd_video < 0) {
802 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Error opening /dev/em8300_mv for writing as well!\nBailing out.\n");
803 uninit();
804 return -1;
806 } else {
807 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Opened: %s.\n", devname);
809 strcpy(fdv_name, devname);
811 /* Open the subpicture interface */
812 sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
813 fd_spu = open(devname, fdflags);
814 if (fd_spu < 0) {
815 /* Fall back to old naming scheme */
816 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_sp instead.\n", devname);
817 sprintf(devname, "/dev/em8300_sp");
818 fd_spu = open(devname, fdflags);
819 if (fd_spu < 0) {
820 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Error opening /dev/em8300_sp for writing as well!\nBailing out.\n");
821 uninit();
822 return -1;
824 } else {
825 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Opened: %s.\n", devname);
827 strcpy(fds_name, devname);
829 #ifdef CONFIG_X11
830 if (dxr3_overlay) {
832 /* Fucked up hack needed to enable overlay.
833 * Will be removed as soon as I figure out
834 * how to make it work like it should
836 Display *dpy;
837 overlay_t *ov;
838 XWindowAttributes attribs;
840 dpy = XOpenDisplay(NULL);
841 if (!dpy) {
842 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to open display during overlay hack setup!\n");
843 return -1;
845 XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
846 ov = overlay_init(fd_control);
847 overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
848 overlay_read_state(ov, NULL);
849 overlay_set_keycolor(ov, KEY_COLOR);
850 overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
851 overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
852 overlay_release(ov);
853 XCloseDisplay(dpy);
854 /* End of fucked up hack */
856 /* Initialize overlay and X11 */
857 overlay_data = overlay_init(fd_control);
858 if (!vo_init()) {
859 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to init X11!\n");
860 return -1;
863 #endif
865 if (dxr3_newsync) {
866 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
867 pts_offset = vo_pts - (ioval << 1);
868 if (pts_offset < 0) {
869 pts_offset = 0;
873 return 0;
876 /* Begin overlay.c */
877 static int update_parameters(overlay_t *o)
879 overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
880 overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
881 overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
882 overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
883 overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
884 return 0;
887 static int overlay_set_attribute(overlay_t *o, int attribute, int value)
889 em8300_attribute_t attr;
891 attr.attribute = attribute;
892 attr.value = value;
893 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
895 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed setting overlay attribute.\n");
896 return -1;
899 return 0;
902 static overlay_t *overlay_init(int dev)
904 overlay_t *o;
906 o = (overlay_t *) malloc(sizeof(overlay_t));
908 if(!o)
909 return NULL;
911 memset(o,0,sizeof(overlay_t));
913 o->dev = dev;
914 o->xres = 1280; o->yres=1024; o->xcorr=1000;
915 o->color_interval=10;
917 return o;
920 static int overlay_release(overlay_t *o)
922 if(o)
923 free(o);
925 return 0;
927 #define TYPE_INT 1
928 #define TYPE_XINT 2
929 #define TYPE_COEFF 3
930 #define TYPE_FLOAT 4
932 struct lut_entry {
933 char *name;
934 int type;
935 void *ptr;
938 static struct lut_entry *new_lookuptable(overlay_t *o)
940 struct lut_entry m[] = {
941 {"xoffset", TYPE_INT, &o->xoffset},
942 {"yoffset", TYPE_INT, &o->yoffset},
943 {"xcorr", TYPE_INT, &o->xcorr},
944 {"jitter", TYPE_INT, &o->jitter},
945 {"stability", TYPE_INT, &o->stability},
946 {"keycolor", TYPE_XINT, &o->keycolor},
947 {"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
948 {"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
949 {"color_interval", TYPE_FLOAT, &o->color_interval},
950 {0,0,0}
951 },*p;
953 p = malloc(sizeof(m));
954 memcpy(p,m,sizeof(m));
955 return p;
958 static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
959 int i;
961 for(i=0; lut[i].name; i++) {
962 if(!strcmp(name,lut[i].name)) {
963 *ptr = lut[i].ptr;
964 *type = lut[i].type;
965 return 1;
968 return 0;
971 static int overlay_read_state(overlay_t *o, char *p)
973 char *a,*tok;
974 char path[128],fname[128],tmp[128],line[256];
975 FILE *fp;
976 struct lut_entry *lut;
977 void *ptr;
978 int type;
979 int j;
981 if(!p) {
982 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
983 av_strlcat(fname,"/.overlay", sizeof( fname ));
984 } else
985 av_strlcpy(fname, p, sizeof( fname ));
987 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
988 av_strlcat(fname, tmp, sizeof( fname ));
990 if(!(fp=fopen(fname,"r")))
991 return -1;
993 lut = new_lookuptable(o);
995 while(!feof(fp)) {
996 if(!fgets(line,256,fp))
997 break;
998 tok=strtok(line," ");
999 if(lookup_parameter(o,lut,tok,&ptr,&type)) {
1000 tok=strtok(NULL," ");
1001 switch(type) {
1002 case TYPE_INT:
1003 sscanf(tok,"%d",(int *)ptr);
1004 break;
1005 case TYPE_XINT:
1006 sscanf(tok,"%x",(int *)ptr);
1007 break;
1008 case TYPE_FLOAT:
1009 sscanf(tok,"%f",(float *)ptr);
1010 break;
1011 case TYPE_COEFF:
1012 for(j=0;j<3;j++) {
1013 sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1014 tok=strtok(NULL," ");
1015 sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1016 tok=strtok(NULL," ");
1018 break;
1024 update_parameters(o);
1026 free(lut);
1027 fclose(fp);
1028 return 0;
1031 static void overlay_update_params(overlay_t *o) {
1032 update_parameters(o);
1035 static int overlay_write_state(overlay_t *o, char *p)
1037 char *a;
1038 char path[128],fname[128],tmp[128];
1039 FILE *fp;
1040 char line[256],*tok;
1041 struct lut_entry *lut;
1042 int i,j;
1044 if(!p) {
1045 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1046 av_strlcat(fname,"/.overlay", sizeof( fname ));
1047 } else
1048 av_strlcpy(fname, p, sizeof( fname ));
1050 if(access(fname, W_OK|X_OK|R_OK)) {
1051 if(mkdir(fname,0766))
1052 return -1;
1055 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1056 av_strlcat(fname, tmp, sizeof( fname ));
1058 if(!(fp=fopen(fname,"w")))
1059 return -1;
1061 lut = new_lookuptable(o);
1063 for(i=0; lut[i].name; i++) {
1064 fprintf(fp,"%s ",lut[i].name);
1065 switch(lut[i].type) {
1066 case TYPE_INT:
1067 fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1068 break;
1069 case TYPE_XINT:
1070 fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1071 break;
1072 case TYPE_FLOAT:
1073 fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1074 break;
1075 case TYPE_COEFF:
1076 for(j=0;j<3;j++)
1077 fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1078 ((struct coeff *)lut[i].ptr)[j].m);
1079 fprintf(fp,"\n");
1080 break;
1084 fclose(fp);
1085 return 0;
1088 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1090 em8300_overlay_screen_t scr;
1092 o->xres = xres;
1093 o->yres = yres;
1094 o->depth = depth;
1096 scr.xsize = xres;
1097 scr.ysize = yres;
1099 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1101 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed setting overlay screen!\nExiting.\n");
1102 return -1;
1104 return 0;
1107 static int overlay_set_mode(overlay_t *o, int mode)
1109 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1110 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed enabling overlay!\nExiting.\n");
1111 return -1;
1113 return 0;
1116 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1118 em8300_overlay_window_t win;
1119 win.xpos = xpos;
1120 win.ypos = ypos;
1121 win.width = width;
1122 win.height = height;
1124 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1126 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed resizing overlay window!\n");
1127 return -1;
1129 return 0;
1132 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1134 em8300_bcs_t bcs;
1135 bcs.brightness = brightness;
1136 bcs.contrast = contrast;
1137 bcs.saturation = saturation;
1139 if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1141 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed setting overlay bcs!\n");
1142 return -1;
1144 return 0;
1147 static int col_interp(float x, struct coeff c)
1149 float y;
1150 y = x*c.k + c.m;
1151 if(y > 255)
1152 y = 255;
1153 if(y < 0)
1154 y = 0;
1155 return rint(y);
1158 static int overlay_set_keycolor(overlay_t *o, int color) {
1159 int r = (color & 0xff0000) >> 16;
1160 int g = (color & 0x00ff00) >> 8;
1161 int b = (color & 0x0000ff);
1162 float ru,gu,bu;
1163 float rl,gl,bl;
1164 int upper,lower;
1166 ru = r+o->color_interval;
1167 gu = g+o->color_interval;
1168 bu = b+o->color_interval;
1170 rl = r-o->color_interval;
1171 gl = g-o->color_interval;
1172 bl = b-o->color_interval;
1174 upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1175 (col_interp(gu, o->colcal_upper[1]) << 8) |
1176 (col_interp(bu, o->colcal_upper[2]));
1178 lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1179 (col_interp(gl, o->colcal_lower[1]) << 8) |
1180 (col_interp(bl, o->colcal_lower[2]));
1182 //printf("0x%06x 0x%06x\n",upper,lower);
1183 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1184 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1185 return 0;
1188 static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1190 float sx=0,sy=0,sxx=0,sxy=0;
1191 float delta,b;
1192 int i;
1194 for(i=0; i < n; i++) {
1195 sx=sx+x[i];
1196 sy=sy+y[i];
1197 sxx=sxx+x[i]*x[i];
1198 sxy=sxy+x[i]*y[i];
1201 delta=sxx*n-sx*sx;
1203 *m=(sxx*sy-sx*sxy)/delta;
1204 *k=(sxy*n-sx*sy)/delta;
1207 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1209 em8300_overlay_calibrate_t cal;
1210 em8300_overlay_window_t win;
1211 int x[256],r[256],g[256],b[256],n;
1212 float k,m;
1214 int i;
1216 o->draw_pattern=pd;
1217 o->dp_arg = arg;
1219 overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1220 overlay_set_screen(o, o->xres, o->yres, o->depth);
1222 /* Calibrate Y-offset */
1224 o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1226 cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1227 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1229 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed getting overlay Y-offset values!\nExiting.\n");
1230 return -1;
1232 o->yoffset = cal.result;
1233 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Yoffset: %d.\n",cal.result);
1235 /* Calibrate X-offset */
1237 o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1239 cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1240 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1242 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed getting overlay X-offset values!\nExiting.\n");
1243 return -1;
1245 o->xoffset = cal.result;
1246 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Xoffset: %d.\n",cal.result);
1248 /* Calibrate X scale correction */
1250 o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1252 cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1253 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1255 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed getting overlay X scale correction!\nExiting.\n");
1256 return -1;
1258 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Xcorrection: %d.\n",cal.result);
1259 o->xcorr = cal.result;
1261 win.xpos = 10;
1262 win.ypos = 10;
1263 win.width = o->xres-20;
1264 win.height = o->yres-20;
1265 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1266 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Failed resizing overlay window!\n");
1267 exit(1);
1270 /* Calibrate key color upper limit */
1272 for(i=128,n=0; i <= 0xff; i+=4) {
1273 o->draw_pattern(i | (i << 8) | (i << 16), 0,
1274 (o->xres-200)/2,0,200,o->yres,o->dp_arg);
1276 cal.arg = i;
1277 cal.arg2 = 1;
1278 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1280 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1282 return -1 ;
1285 x[n] = i;
1286 r[n] = (cal.result>>16)&0xff;
1287 g[n] = (cal.result>>8)&0xff;
1288 b[n] = (cal.result)&0xff;
1289 n++;
1292 least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1293 least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1294 least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1296 /* Calibrate key color lower limit */
1298 for(i=128,n=0; i <= 0xff; i+=4) {
1299 o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1300 (o->xres-200)/2,0,200,o->yres, o->dp_arg);
1302 cal.arg = i;
1303 cal.arg2 = 2;
1304 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1306 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1308 return -1 ;
1310 x[n] = i;
1311 r[n] = (cal.result>>16)&0xff;
1312 g[n] = (cal.result>>8)&0xff;
1313 b[n] = (cal.result)&0xff;
1314 n++;
1317 least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1318 least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1319 least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1321 overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1323 return 0;
1327 static int overlay_signalmode(overlay_t *o, int mode) {
1328 if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1329 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed to set signal mix!\n");
1330 return -1;
1332 return 0;
1334 /* End overlay.c */