codecs.conf: add binary expression codec for fourcc MTS2
[mplayer/greg.git] / libvo / vo_dxr3.c
blob240d369f83ffb8b4c6e754b124ce8ed4ed4a496c
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 "fastmemcpy.h"
41 #include "video_out.h"
42 #include "video_out_internal.h"
43 #include "aspect.h"
44 #include "spuenc.h"
45 #include "sub.h"
46 #ifdef CONFIG_X11
47 #include "x11_common.h"
48 #endif
49 #include "libavutil/avstring.h"
51 #define SPU_SUPPORT
53 static const vo_info_t info =
55 "DXR3/H+ video out",
56 "dxr3",
57 "David Holm <dholm@iname.com>",
60 const LIBVO_EXTERN (dxr3)
62 /* Resolutions and positions */
63 static int v_width, v_height;
64 static int s_width, s_height;
65 static int osd_w, osd_h;
66 static int img_format;
68 /* Configuration values
69 * Don't declare these static, they
70 * should be accessible from the gui.
72 int dxr3_prebuf = 0;
73 int dxr3_newsync = 0;
74 int dxr3_overlay = 0;
75 int dxr3_device_num = 0;
76 int dxr3_norm = 0;
78 #define MAX_STR_SIZE 80 /* length for the static strings */
80 /* File descriptors */
81 static int fd_control = -1;
82 static int fd_video = -1;
83 static int fd_spu = -1;
84 static char fdv_name[MAX_STR_SIZE];
85 static char fds_name[MAX_STR_SIZE];
87 #ifdef SPU_SUPPORT
88 /* on screen display/subpics */
89 static char *osdpicbuf;
90 static int osdpicbuf_w;
91 static int osdpicbuf_h;
92 static int disposd;
93 static encodedata *spued;
94 static encodedata *spubuf;
95 #endif
98 /* Static variable used in ioctl's */
99 static int ioval;
100 static int prev_pts;
101 static int pts_offset;
102 static int old_vmode = -1;
105 /* Begin overlay.h */
107 Simple analog overlay API for DXR3/H+ linux driver.
109 Henrik Johansson
113 /* Pattern drawing callback used by the calibration functions.
114 The function is expected to:
115 Clear the entire screen.
116 Fill the screen with color bgcol (0xRRGGBB)
117 Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
120 typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
121 int xpos, int ypos, int width, int height, void *arg);
123 struct coeff {
124 float k,m;
127 typedef struct {
128 int dev;
130 int xres, yres,depth;
131 int xoffset,yoffset,xcorr;
132 int jitter;
133 int stability;
134 int keycolor;
135 struct coeff colcal_upper[3];
136 struct coeff colcal_lower[3];
137 float color_interval;
139 pattern_drawer_cb draw_pattern;
140 void *dp_arg;
141 } overlay_t;
144 static overlay_t *overlay_init(int dev);
145 static int overlay_release(overlay_t *);
147 static int overlay_read_state(overlay_t *o, char *path);
148 static int overlay_write_state(overlay_t *o, char *path);
150 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
151 static int overlay_set_mode(overlay_t *o, int mode);
152 static int overlay_set_attribute(overlay_t *o, int attribute, int val);
153 static int overlay_set_keycolor(overlay_t *o, int color);
154 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
155 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
157 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
158 static void overlay_update_params(overlay_t *o);
159 static int overlay_signalmode(overlay_t *o, int mode);
160 /* End overlay.h */
163 #ifdef CONFIG_X11
164 #define KEY_COLOR 0x80a040
165 static XWindowAttributes xwin_attribs;
166 static overlay_t *overlay_data;
167 #endif
170 /* Functions for working with the em8300's internal clock */
171 /* End of internal clock functions */
173 static int control(uint32_t request, void *data)
175 switch (request) {
176 case VOCTRL_SET_SPU_PALETTE:
177 if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
178 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to load new SPU palette!\n");
179 return VO_ERROR;
181 return VO_TRUE;
182 #ifdef CONFIG_X11
183 case VOCTRL_ONTOP:
184 vo_x11_ontop();
185 return VO_TRUE;
186 case VOCTRL_FULLSCREEN:
187 if (dxr3_overlay) {
188 vo_x11_fullscreen();
189 overlay_signalmode(overlay_data,
190 vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
191 EM8300_OVERLAY_SIGNAL_WITH_VGA);
192 return VO_TRUE;
194 return VO_FALSE;
195 #endif
196 case VOCTRL_RESUME:
197 if (dxr3_newsync) {
198 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
199 pts_offset = vo_pts - (ioval << 1);
200 if (pts_offset < 0) {
201 pts_offset = 0;
205 if (dxr3_prebuf) {
206 ioval = EM8300_PLAYMODE_PLAY;
207 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
208 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set playmode!\n");
211 return VO_TRUE;
212 case VOCTRL_PAUSE:
213 if (dxr3_prebuf) {
214 ioval = EM8300_PLAYMODE_PAUSED;
215 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
216 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set playmode!\n");
219 return VO_TRUE;
220 case VOCTRL_RESET:
221 if (dxr3_prebuf) {
222 close(fd_video);
223 fd_video = open(fdv_name, O_WRONLY);
224 close(fd_spu);
225 fd_spu = open(fds_name, O_WRONLY);
226 fsync(fd_video);
227 fsync(fd_spu);
229 return VO_TRUE;
230 case VOCTRL_QUERY_FORMAT:
232 uint32_t flag = 0;
234 if (*((uint32_t*)data) != IMGFMT_MPEGPES)
235 return 0;
237 flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
238 if (dxr3_prebuf)
239 flag |= VFCAP_TIMER;
240 return flag;
242 case VOCTRL_SET_EQUALIZER:
244 em8300_bcs_t bcs;
245 struct voctrl_set_equalizer_args *args = data;
247 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
248 return VO_FALSE;
249 if (!strcasecmp(args->name, "brightness"))
250 bcs.brightness = (args->value+100)*5;
251 else if (!strcasecmp(args->name, "contrast"))
252 bcs.contrast = (args->value+100)*5;
253 else if (!strcasecmp(args->name, "saturation"))
254 bcs.saturation = (args->value+100)*5;
255 else return VO_FALSE;
257 if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
258 return VO_FALSE;
259 return VO_TRUE;
261 case VOCTRL_GET_EQUALIZER:
263 em8300_bcs_t bcs;
264 struct voctrl_get_equalizer_args *args = data;
266 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
267 return VO_FALSE;
269 if (!strcasecmp(args->name, "brightness"))
270 *args->valueptr = (bcs.brightness/5)-100;
271 else if (!strcasecmp(args->name, "contrast"))
272 *args->valueptr = (bcs.contrast/5)-100;
273 else if (!strcasecmp(args->name, "saturation"))
274 *args->valueptr = (bcs.saturation/5)-100;
275 else return VO_FALSE;
277 return VO_TRUE;
280 return VO_NOTIMPL;
283 void calculate_cvals(unsigned long mask, int *shift, int *prec)
285 /* Calculate shift and precision */
286 (*shift) = 0;
287 (*prec) = 0;
289 while (!(mask & 0x1)) {
290 (*shift)++;
291 mask >>= 1;
294 while (mask & 0x1) {
295 (*prec)++;
296 mask >>= 1;
300 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)
302 int tmp1, tmp2, size;
303 em8300_register_t reg;
305 /* Softzoom turned on, downscale */
306 /* This activates the subpicture processor, you can safely disable this and still send */
307 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
308 /* up in a lockup */
309 ioval = EM8300_SPUMODE_ON;
310 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
311 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set subpicture mode!\n");
312 uninit();
313 return -1;
316 /* Set the playmode to play (just in case another app has set it to something else) */
317 ioval = EM8300_PLAYMODE_PLAY;
318 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
319 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set playmode!\n");
322 /* Start em8300 prebuffering and sync engine */
323 reg.microcode_register = 1;
324 reg.reg = 0;
325 reg.val = MVCOMMAND_SYNC;
326 ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
328 /* Clean buffer by syncing it */
329 ioval = EM8300_SUBDEVICE_VIDEO;
330 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
331 ioval = EM8300_SUBDEVICE_AUDIO;
332 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
334 /* Sync the video device to make sure the buffers are empty
335 * and set the playback speed to normal. Also reset the
336 * em8300 internal clock.
338 fsync(fd_video);
339 ioval = 0x900;
340 ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
342 /* Store some variables statically that we need later in another scope */
343 img_format = format;
344 v_width = width;
345 v_height = height;
347 /* Set monitor_aspect to avoid jitter */
348 monitor_aspect = (float) width / (float) height;
350 if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
351 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to get TV norm!\n");
352 old_vmode = -1;
355 /* adjust TV norm */
356 if (dxr3_norm != 0) {
357 if (dxr3_norm == 5) {
358 ioval = EM8300_VIDEOMODE_NTSC;
359 } else if (dxr3_norm == 4) {
360 ioval = EM8300_VIDEOMODE_PAL60;
361 } else if (dxr3_norm == 3) {
362 ioval = EM8300_VIDEOMODE_PAL;
363 } else if (dxr3_norm == 2) {
364 if (vo_fps > 28) {
365 ioval = EM8300_VIDEOMODE_PAL60;
366 } else {
367 ioval = EM8300_VIDEOMODE_PAL;
370 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Auto-selected TV norm by framerate: ");
371 ioval == EM8300_VIDEOMODE_PAL60 ? mp_msg(MSGT_VO,MSGL_INFO, "PAL-60") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
372 printf(".\n");
373 } else {
374 if (vo_fps > 28) {
375 ioval = EM8300_VIDEOMODE_NTSC;
376 } else {
377 ioval = EM8300_VIDEOMODE_PAL;
380 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Auto-selected TV norm by framerate: ");
381 ioval == EM8300_VIDEOMODE_NTSC ? mp_msg(MSGT_VO,MSGL_INFO, "NTSC") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
382 printf(".\n");
385 if (old_vmode != ioval) {
386 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
387 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to set TV norm!\n");
393 /* libavcodec requires a width and height that is x|16 */
394 aspect_save_orig(width, height);
395 aspect_save_prescale(d_width, d_height);
396 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
397 if (ioval == EM8300_VIDEOMODE_NTSC) {
398 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting up for NTSC.\n");
399 aspect_save_screenres(352, 240);
400 } else {
401 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting up for PAL/SECAM.\n");
402 aspect_save_screenres(352, 288);
404 aspect(&s_width, &s_height, A_ZOOM);
405 s_width -= s_width % 16;
406 s_height -= s_height % 16;
408 /* Try to figure out whether to use widescreen output or not */
409 /* Anamorphic widescreen modes makes this a pain in the ass */
410 tmp1 = abs(d_height - ((d_width / 4) * 3));
411 tmp2 = abs(d_height - (int) (d_width / 2.35));
412 if (tmp1 < tmp2) {
413 ioval = EM8300_ASPECTRATIO_4_3;
414 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting aspect ratio to 4:3.\n");
415 } else {
416 ioval = EM8300_ASPECTRATIO_16_9;
417 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Setting aspect ratio to 16:9.\n");
419 ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
421 #ifdef SPU_SUPPORT
422 #ifdef CONFIG_FREETYPE
423 if (ioval == EM8300_ASPECTRATIO_16_9) {
424 s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
425 } else {
426 s_width *= 0.84;
428 //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
429 #else
430 s_width*=2;
431 s_height*=2;
432 #endif
434 osdpicbuf = calloc( 1,s_width * s_height);
435 if (osdpicbuf == NULL) {
436 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] out of memory\n");
437 return -1;
439 spued = malloc(sizeof(encodedata));
440 if (spued == NULL) {
441 free( osdpicbuf );
442 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] out of memory\n");
443 return -1;
445 spubuf = malloc(sizeof(encodedata));
446 if (spubuf == NULL) {
447 free( osdpicbuf );
448 free( spued );
449 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] out of memory\n");
450 return -1;
452 osd_w = s_width;
453 osd_h = s_height;
454 osdpicbuf_w = s_width;
455 osdpicbuf_h = s_height;
457 spubuf->count=0;
458 pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
460 #endif
462 #ifdef CONFIG_X11
463 if (dxr3_overlay) {
464 XVisualInfo vinfo;
465 XSetWindowAttributes xswa;
466 XSizeHints hint;
467 unsigned long xswamask;
468 Colormap cmap;
469 XColor key_color;
470 Window junkwindow;
471 Screen *scr;
472 int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
473 em8300_overlay_screen_t ovlscr;
474 em8300_attribute_t ovlattr;
476 vo_dx = (vo_screenwidth - d_width) / 2;
477 vo_dy = (vo_screenheight - d_height) / 2;
478 vo_dwidth = d_width;
479 vo_dheight = d_height;
481 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
482 depth = xwin_attribs.depth;
483 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
484 depth = 24;
486 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
487 vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy,
488 d_width, d_height, flags,
489 CopyFromParent, "Viewing Window", title);
490 xswa.background_pixel = KEY_COLOR;
491 xswa.border_pixel = 0;
492 xswamask = CWBackPixel | CWBorderPixel;
493 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa);
496 /* Start setting up overlay */
497 XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
498 overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
499 overlay_read_state(overlay_data, NULL);
501 /* Allocate keycolor */
502 cmap = vo_x11_create_colormap(&vinfo);
503 calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
504 calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
505 calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
507 key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
508 key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
509 key_color.blue = (KEY_COLOR & 0xff) * 256;
510 key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
511 ((key_color.green >> (16 - green_prec)) << green_shift) +
512 ((key_color.blue >> (16 - blue_prec)) << blue_shift));
513 key_color.flags = DoRed | DoGreen | DoBlue;
514 if (!XAllocColor(mDisplay, cmap, &key_color)) {
515 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to allocate keycolor!\n");
516 return -1;
519 acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
520 if (key_color.pixel != KEY_COLOR) {
521 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Unable to allocate exact keycolor, using closest match (0x%lx).\n", key_color.pixel);
524 /* Set keycolor and activate overlay */
525 XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
526 XClearWindow(mDisplay, vo_window);
527 overlay_set_keycolor(overlay_data, key_color.pixel);
528 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
529 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
531 #endif
533 return 0;
536 static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
538 #ifdef SPU_SUPPORT
539 unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
540 int by = 0;
541 register int lx, ly;
542 register int stride = 0;
544 for (ly = 0; ly < h - 1; ly++)
546 for(lx = 0; lx < w; lx++ )
547 if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
548 by+=osdpicbuf_w;
549 stride+=srcstride;
551 pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
552 #endif
555 extern mp_osd_obj_t* vo_osd_list;
557 static void draw_osd(void)
559 #ifdef SPU_SUPPORT
560 static int cleared = 0;
561 int changed = 0;
563 if ((disposd % 15) == 0)
566 mp_osd_obj_t* obj = vo_osd_list;
567 vo_update_osd( osd_w,osd_h );
568 while( obj )
570 if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
571 obj=obj->next;
574 if ( changed )
576 vo_draw_text(osd_w, osd_h, draw_alpha);
577 memset(osdpicbuf, 0, s_width * s_height);
578 cleared=0;
580 else
582 if ( !cleared )
584 spued->count=spubuf->count;
585 fast_memcpy( spued->data,spubuf->data,DATASIZE );
586 cleared=1;
591 /* could stand some check here to see if the subpic hasn't changed
592 * as if it hasn't and we re-send it it will "blink" as the last one
593 * is turned off, and the new one (same one) is turned on
595 /* Subpics are not stable yet =(
596 expect lockups if you enable */
597 write(fd_spu, spued->data, spued->count);
599 disposd++;
600 #endif
604 static int draw_frame(uint8_t * src[])
606 vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
608 #ifdef SPU_SUPPORT
609 if (p->id == 0x20) {
610 write(fd_spu, p->data, p->size);
611 } else
612 #endif
613 write(fd_video, p->data, p->size);
614 return 0;
617 static void flip_page(void)
619 #ifdef CONFIG_X11
620 if (dxr3_overlay) {
621 int event = vo_x11_check_events(mDisplay);
622 if (event & VO_EVENT_RESIZE) {
623 Window junkwindow;
624 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
625 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
626 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
628 if (event & VO_EVENT_EXPOSE) {
629 Window junkwindow;
630 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
631 XClearWindow(mDisplay, vo_window);
632 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
633 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
634 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
637 #endif
639 if (dxr3_newsync) {
640 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
641 ioval <<= 1;
642 if (vo_pts == 0) {
643 ioval = 0;
644 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
645 pts_offset = 0;
646 } else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
647 ioval = (vo_pts + pts_offset) >> 1;
648 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
649 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
650 pts_offset = vo_pts - (ioval << 1);
651 if (pts_offset < 0) {
652 pts_offset = 0;
655 ioval = vo_pts + pts_offset;
656 ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
657 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
658 prev_pts = vo_pts;
659 } else if (dxr3_prebuf) {
660 ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
661 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
665 static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
667 return -1;
670 static void uninit(void)
672 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Uninitializing.\n");
673 #ifdef CONFIG_X11
674 if (dxr3_overlay) {
675 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
676 overlay_release(overlay_data);
678 vo_x11_uninit();
681 #endif
682 if (old_vmode != -1) {
683 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
684 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed restoring TV norm!\n");
688 if (fd_video) {
689 close(fd_video);
691 if (fd_spu) {
692 close(fd_spu);
694 if (fd_control) {
695 close(fd_control);
697 #ifdef SPU_SUPPORT
698 if(osdpicbuf) {
699 free(osdpicbuf);
701 if(spued) {
702 free(spued);
704 #endif
707 static void check_events(void)
711 static int preinit(const char *arg)
713 char devname[MAX_STR_SIZE];
714 int fdflags = O_WRONLY;
716 /* Parse commandline */
717 while (arg) {
718 if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
719 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Enabling prebuffering.\n");
720 dxr3_prebuf = 1;
721 } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
722 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Using new sync engine.\n");
723 dxr3_newsync = 1;
724 } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
725 #ifdef CONFIG_X11
726 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Using overlay.\n");
727 dxr3_overlay = 1;
728 #else
729 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error: Overlay requires compiling with X11 libs/headers installed.\n");
730 #endif
731 } else if (!strncmp("norm=", arg, 5)) {
732 arg += 5;
733 // dxr3_norm is 0 (-> don't change norm) by default
734 // but maybe someone changes this in the future
736 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Will set TV norm to: ");
738 if (*arg == '5') {
739 dxr3_norm = 5;
740 mp_msg(MSGT_VO,MSGL_INFO, "NTSC");
741 } else if (*arg == '4') {
742 dxr3_norm = 4;
743 mp_msg(MSGT_VO,MSGL_INFO, "PAL-60");
744 } else if (*arg == '3') {
745 dxr3_norm = 3;
746 mp_msg(MSGT_VO,MSGL_INFO, "PAL");
747 } else if (*arg == '2') {
748 dxr3_norm = 2;
749 mp_tmsg(MSGT_VO,MSGL_INFO, "auto-adjust to movie framerate (PAL/PAL-60)");
750 } else if (*arg == '1') {
751 dxr3_norm = 1;
752 mp_tmsg(MSGT_VO,MSGL_INFO, "auto-adjust to movie framerate (PAL/NTSC)");
753 } else if (*arg == '0') {
754 dxr3_norm = 0;
755 mp_tmsg(MSGT_VO,MSGL_INFO, "Use current norm.");
756 } else {
757 dxr3_norm = 0;
758 mp_tmsg(MSGT_VO,MSGL_INFO, "Unknown norm supplied. Use current norm.");
761 mp_msg(MSGT_VO,MSGL_INFO, ".\n");
762 } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
763 dxr3_device_num = arg[0];
766 arg = strchr(arg, ':');
767 if (arg) {
768 arg++;
773 /* Open the control interface */
774 sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
775 fd_control = open(devname, fdflags);
776 if (fd_control < 1) {
777 /* Fall back to old naming scheme */
778 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error opening %s for writing, trying /dev/em8300 instead.\n", devname);
779 sprintf(devname, "/dev/em8300");
780 fd_control = open(devname, fdflags);
781 if (fd_control < 1) {
782 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Error opening /dev/em8300 for writing as well!\nBailing out.\n");
783 return -1;
785 } else {
786 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Opened: %s.\n", devname);
789 /* Open the video interface */
790 sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
791 fd_video = open(devname, fdflags);
792 if (fd_video < 0) {
793 /* Fall back to old naming scheme */
794 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_mv instead.\n", devname);
795 sprintf(devname, "/dev/em8300_mv");
796 fd_video = open(devname, fdflags);
797 if (fd_video < 0) {
798 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Error opening /dev/em8300_mv for writing as well!\nBailing out.\n");
799 uninit();
800 return -1;
802 } else {
803 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Opened: %s.\n", devname);
805 strcpy(fdv_name, devname);
807 /* Open the subpicture interface */
808 sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
809 fd_spu = open(devname, fdflags);
810 if (fd_spu < 0) {
811 /* Fall back to old naming scheme */
812 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Error opening %s for writing, trying /dev/em8300_sp instead.\n", devname);
813 sprintf(devname, "/dev/em8300_sp");
814 fd_spu = open(devname, fdflags);
815 if (fd_spu < 0) {
816 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Error opening /dev/em8300_sp for writing as well!\nBailing out.\n");
817 uninit();
818 return -1;
820 } else {
821 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Opened: %s.\n", devname);
823 strcpy(fds_name, devname);
825 #ifdef CONFIG_X11
826 if (dxr3_overlay) {
828 /* Fucked up hack needed to enable overlay.
829 * Will be removed as soon as I figure out
830 * how to make it work like it should
832 Display *dpy;
833 overlay_t *ov;
834 XWindowAttributes attribs;
836 dpy = XOpenDisplay(NULL);
837 if (!dpy) {
838 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to open display during overlay hack setup!\n");
839 return -1;
841 XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
842 ov = overlay_init(fd_control);
843 overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
844 overlay_read_state(ov, NULL);
845 overlay_set_keycolor(ov, KEY_COLOR);
846 overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
847 overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
848 overlay_release(ov);
849 XCloseDisplay(dpy);
850 /* End of fucked up hack */
852 /* Initialize overlay and X11 */
853 overlay_data = overlay_init(fd_control);
854 if (!vo_init()) {
855 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Unable to init X11!\n");
856 return -1;
859 #endif
861 if (dxr3_newsync) {
862 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
863 pts_offset = vo_pts - (ioval << 1);
864 if (pts_offset < 0) {
865 pts_offset = 0;
869 return 0;
872 /* Begin overlay.c */
873 static int update_parameters(overlay_t *o)
875 overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
876 overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
877 overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
878 overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
879 overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
880 return 0;
883 static int overlay_set_attribute(overlay_t *o, int attribute, int value)
885 em8300_attribute_t attr;
887 attr.attribute = attribute;
888 attr.value = value;
889 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
891 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed setting overlay attribute.\n");
892 return -1;
895 return 0;
898 static overlay_t *overlay_init(int dev)
900 overlay_t *o;
902 o = malloc(sizeof(overlay_t));
904 if(!o)
905 return NULL;
907 memset(o,0,sizeof(overlay_t));
909 o->dev = dev;
910 o->xres = 1280; o->yres=1024; o->xcorr=1000;
911 o->color_interval=10;
913 return o;
916 static int overlay_release(overlay_t *o)
918 if(o)
919 free(o);
921 return 0;
923 #define TYPE_INT 1
924 #define TYPE_XINT 2
925 #define TYPE_COEFF 3
926 #define TYPE_FLOAT 4
928 struct lut_entry {
929 char *name;
930 int type;
931 void *ptr;
934 static struct lut_entry *new_lookuptable(overlay_t *o)
936 struct lut_entry m[] = {
937 {"xoffset", TYPE_INT, &o->xoffset},
938 {"yoffset", TYPE_INT, &o->yoffset},
939 {"xcorr", TYPE_INT, &o->xcorr},
940 {"jitter", TYPE_INT, &o->jitter},
941 {"stability", TYPE_INT, &o->stability},
942 {"keycolor", TYPE_XINT, &o->keycolor},
943 {"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
944 {"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
945 {"color_interval", TYPE_FLOAT, &o->color_interval},
946 {0,0,0}
947 },*p;
949 p = malloc(sizeof(m));
950 memcpy(p,m,sizeof(m));
951 return p;
954 static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
955 int i;
957 for(i=0; lut[i].name; i++) {
958 if(!strcmp(name,lut[i].name)) {
959 *ptr = lut[i].ptr;
960 *type = lut[i].type;
961 return 1;
964 return 0;
967 static int overlay_read_state(overlay_t *o, char *p)
969 char *a,*tok;
970 char path[128],fname[128],tmp[128],line[256];
971 FILE *fp;
972 struct lut_entry *lut;
973 void *ptr;
974 int type;
975 int j;
977 if(!p) {
978 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
979 av_strlcat(fname,"/.overlay", sizeof( fname ));
980 } else
981 av_strlcpy(fname, p, sizeof( fname ));
983 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
984 av_strlcat(fname, tmp, sizeof( fname ));
986 if(!(fp=fopen(fname,"r")))
987 return -1;
989 lut = new_lookuptable(o);
991 while(!feof(fp)) {
992 if(!fgets(line,256,fp))
993 break;
994 tok=strtok(line," ");
995 if(lookup_parameter(o,lut,tok,&ptr,&type)) {
996 tok=strtok(NULL," ");
997 switch(type) {
998 case TYPE_INT:
999 sscanf(tok,"%d",(int *)ptr);
1000 break;
1001 case TYPE_XINT:
1002 sscanf(tok,"%x",(int *)ptr);
1003 break;
1004 case TYPE_FLOAT:
1005 sscanf(tok,"%f",(float *)ptr);
1006 break;
1007 case TYPE_COEFF:
1008 for(j=0;j<3;j++) {
1009 sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1010 tok=strtok(NULL," ");
1011 sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1012 tok=strtok(NULL," ");
1014 break;
1020 update_parameters(o);
1022 free(lut);
1023 fclose(fp);
1024 return 0;
1027 static void overlay_update_params(overlay_t *o) {
1028 update_parameters(o);
1031 static int overlay_write_state(overlay_t *o, char *p)
1033 char *a;
1034 char path[128],fname[128],tmp[128];
1035 FILE *fp;
1036 char line[256],*tok;
1037 struct lut_entry *lut;
1038 int i,j;
1040 if(!p) {
1041 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1042 av_strlcat(fname,"/.overlay", sizeof( fname ));
1043 } else
1044 av_strlcpy(fname, p, sizeof( fname ));
1046 if(access(fname, W_OK|X_OK|R_OK)) {
1047 if(mkdir(fname,0766))
1048 return -1;
1051 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1052 av_strlcat(fname, tmp, sizeof( fname ));
1054 if(!(fp=fopen(fname,"w")))
1055 return -1;
1057 lut = new_lookuptable(o);
1059 for(i=0; lut[i].name; i++) {
1060 fprintf(fp,"%s ",lut[i].name);
1061 switch(lut[i].type) {
1062 case TYPE_INT:
1063 fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1064 break;
1065 case TYPE_XINT:
1066 fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1067 break;
1068 case TYPE_FLOAT:
1069 fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1070 break;
1071 case TYPE_COEFF:
1072 for(j=0;j<3;j++)
1073 fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1074 ((struct coeff *)lut[i].ptr)[j].m);
1075 fprintf(fp,"\n");
1076 break;
1080 fclose(fp);
1081 return 0;
1084 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1086 em8300_overlay_screen_t scr;
1088 o->xres = xres;
1089 o->yres = yres;
1090 o->depth = depth;
1092 scr.xsize = xres;
1093 scr.ysize = yres;
1095 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1097 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed setting overlay screen!\nExiting.\n");
1098 return -1;
1100 return 0;
1103 static int overlay_set_mode(overlay_t *o, int mode)
1105 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1106 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed enabling overlay!\nExiting.\n");
1107 return -1;
1109 return 0;
1112 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1114 em8300_overlay_window_t win;
1115 win.xpos = xpos;
1116 win.ypos = ypos;
1117 win.width = width;
1118 win.height = height;
1120 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1122 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed resizing overlay window!\n");
1123 return -1;
1125 return 0;
1128 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1130 em8300_bcs_t bcs;
1131 bcs.brightness = brightness;
1132 bcs.contrast = contrast;
1133 bcs.saturation = saturation;
1135 if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1137 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed setting overlay bcs!\n");
1138 return -1;
1140 return 0;
1143 static int col_interp(float x, struct coeff c)
1145 float y;
1146 y = x*c.k + c.m;
1147 if(y > 255)
1148 y = 255;
1149 if(y < 0)
1150 y = 0;
1151 return rint(y);
1154 static int overlay_set_keycolor(overlay_t *o, int color) {
1155 int r = (color & 0xff0000) >> 16;
1156 int g = (color & 0x00ff00) >> 8;
1157 int b = (color & 0x0000ff);
1158 float ru,gu,bu;
1159 float rl,gl,bl;
1160 int upper,lower;
1162 ru = r+o->color_interval;
1163 gu = g+o->color_interval;
1164 bu = b+o->color_interval;
1166 rl = r-o->color_interval;
1167 gl = g-o->color_interval;
1168 bl = b-o->color_interval;
1170 upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1171 (col_interp(gu, o->colcal_upper[1]) << 8) |
1172 (col_interp(bu, o->colcal_upper[2]));
1174 lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1175 (col_interp(gl, o->colcal_lower[1]) << 8) |
1176 (col_interp(bl, o->colcal_lower[2]));
1178 //printf("0x%06x 0x%06x\n",upper,lower);
1179 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1180 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1181 return 0;
1184 static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1186 float sx=0,sy=0,sxx=0,sxy=0;
1187 float delta,b;
1188 int i;
1190 for(i=0; i < n; i++) {
1191 sx=sx+x[i];
1192 sy=sy+y[i];
1193 sxx=sxx+x[i]*x[i];
1194 sxy=sxy+x[i]*y[i];
1197 delta=sxx*n-sx*sx;
1199 *m=(sxx*sy-sx*sxy)/delta;
1200 *k=(sxy*n-sx*sy)/delta;
1203 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1205 em8300_overlay_calibrate_t cal;
1206 em8300_overlay_window_t win;
1207 int x[256],r[256],g[256],b[256],n;
1208 float k,m;
1210 int i;
1212 o->draw_pattern=pd;
1213 o->dp_arg = arg;
1215 overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1216 overlay_set_screen(o, o->xres, o->yres, o->depth);
1218 /* Calibrate Y-offset */
1220 o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1222 cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1223 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1225 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed getting overlay Y-offset values!\nExiting.\n");
1226 return -1;
1228 o->yoffset = cal.result;
1229 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Yoffset: %d.\n",cal.result);
1231 /* Calibrate X-offset */
1233 o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1235 cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1236 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1238 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed getting overlay X-offset values!\nExiting.\n");
1239 return -1;
1241 o->xoffset = cal.result;
1242 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Xoffset: %d.\n",cal.result);
1244 /* Calibrate X scale correction */
1246 o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1248 cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1249 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1251 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed getting overlay X scale correction!\nExiting.\n");
1252 return -1;
1254 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_DXR3] Xcorrection: %d.\n",cal.result);
1255 o->xcorr = cal.result;
1257 win.xpos = 10;
1258 win.ypos = 10;
1259 win.width = o->xres-20;
1260 win.height = o->yres-20;
1261 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1262 mp_tmsg(MSGT_VO,MSGL_ERR, "[VO_DXR3] Failed resizing overlay window!\n");
1263 exit(1);
1266 /* Calibrate key color upper limit */
1268 for(i=128,n=0; i <= 0xff; i+=4) {
1269 o->draw_pattern(i | (i << 8) | (i << 16), 0,
1270 (o->xres-200)/2,0,200,o->yres,o->dp_arg);
1272 cal.arg = i;
1273 cal.arg2 = 1;
1274 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1276 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1278 return -1 ;
1281 x[n] = i;
1282 r[n] = (cal.result>>16)&0xff;
1283 g[n] = (cal.result>>8)&0xff;
1284 b[n] = (cal.result)&0xff;
1285 n++;
1288 least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1289 least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1290 least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1292 /* Calibrate key color lower limit */
1294 for(i=128,n=0; i <= 0xff; i+=4) {
1295 o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1296 (o->xres-200)/2,0,200,o->yres, o->dp_arg);
1298 cal.arg = i;
1299 cal.arg2 = 2;
1300 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1302 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1304 return -1 ;
1306 x[n] = i;
1307 r[n] = (cal.result>>16)&0xff;
1308 g[n] = (cal.result>>8)&0xff;
1309 b[n] = (cal.result)&0xff;
1310 n++;
1313 least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1314 least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1315 least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1317 overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1319 return 0;
1323 static int overlay_signalmode(overlay_t *o, int mode) {
1324 if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1325 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_DXR3] Failed to set signal mix!\n");
1326 return -1;
1328 return 0;
1330 /* End overlay.c */