Add const where appropriate, also gets rid of a compiler warning.
[mplayer/glamo.git] / libvo / vo_dxr3.c
blob05f55aa4f9a54776f31a2ca8c7cc9bc7ce7579f0
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_GUI
48 #include "gui/interface.h"
49 #endif
50 #ifdef CONFIG_X11
51 #include "x11_common.h"
52 #endif
53 #include "libavutil/avstring.h"
55 #define SPU_SUPPORT
57 static const vo_info_t info =
59 "DXR3/H+ video out",
60 "dxr3",
61 "David Holm <dholm@iname.com>",
64 const LIBVO_EXTERN (dxr3)
66 /* Resolutions and positions */
67 static int v_width, v_height;
68 static int s_width, s_height;
69 static int osd_w, osd_h;
70 static int img_format;
72 /* Configuration values
73 * Don't declare these static, they
74 * should be accessible from the gui.
76 int dxr3_prebuf = 0;
77 int dxr3_newsync = 0;
78 int dxr3_overlay = 0;
79 int dxr3_device_num = 0;
80 int dxr3_norm = 0;
82 #define MAX_STR_SIZE 80 /* length for the static strings */
84 /* File descriptors */
85 static int fd_control = -1;
86 static int fd_video = -1;
87 static int fd_spu = -1;
88 static char fdv_name[MAX_STR_SIZE];
89 static char fds_name[MAX_STR_SIZE];
91 #ifdef SPU_SUPPORT
92 /* on screen display/subpics */
93 static char *osdpicbuf;
94 static int osdpicbuf_w;
95 static int osdpicbuf_h;
96 static int disposd;
97 static encodedata *spued;
98 static encodedata *spubuf;
99 #endif
102 /* Static variable used in ioctl's */
103 static int ioval;
104 static int prev_pts;
105 static int pts_offset;
106 static int old_vmode = -1;
109 /* Begin overlay.h */
111 Simple analog overlay API for DXR3/H+ linux driver.
113 Henrik Johansson
117 /* Pattern drawing callback used by the calibration functions.
118 The function is expected to:
119 Clear the entire screen.
120 Fill the screen with color bgcol (0xRRGGBB)
121 Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
124 typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
125 int xpos, int ypos, int width, int height, void *arg);
127 struct coeff {
128 float k,m;
131 typedef struct {
132 int dev;
134 int xres, yres,depth;
135 int xoffset,yoffset,xcorr;
136 int jitter;
137 int stability;
138 int keycolor;
139 struct coeff colcal_upper[3];
140 struct coeff colcal_lower[3];
141 float color_interval;
143 pattern_drawer_cb draw_pattern;
144 void *dp_arg;
145 } overlay_t;
148 static overlay_t *overlay_init(int dev);
149 static int overlay_release(overlay_t *);
151 static int overlay_read_state(overlay_t *o, char *path);
152 static int overlay_write_state(overlay_t *o, char *path);
154 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
155 static int overlay_set_mode(overlay_t *o, int mode);
156 static int overlay_set_attribute(overlay_t *o, int attribute, int val);
157 static int overlay_set_keycolor(overlay_t *o, int color);
158 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
159 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
161 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
162 static void overlay_update_params(overlay_t *o);
163 static int overlay_signalmode(overlay_t *o, int mode);
164 /* End overlay.h */
167 #ifdef CONFIG_X11
168 #define KEY_COLOR 0x80a040
169 static XWindowAttributes xwin_attribs;
170 static overlay_t *overlay_data;
171 #endif
174 /* Functions for working with the em8300's internal clock */
175 /* End of internal clock functions */
177 static int control(uint32_t request, void *data, ...)
179 switch (request) {
180 case VOCTRL_GUISUPPORT:
181 return VO_TRUE;
182 case VOCTRL_GUI_NOWINDOW:
183 if (dxr3_overlay) {
184 return VO_FALSE;
186 return VO_TRUE;
187 case VOCTRL_SET_SPU_PALETTE:
188 if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
189 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToLoadNewSPUPalette);
190 return VO_ERROR;
192 return VO_TRUE;
193 #ifdef CONFIG_X11
194 case VOCTRL_ONTOP:
195 vo_x11_ontop();
196 return VO_TRUE;
197 case VOCTRL_FULLSCREEN:
198 if (dxr3_overlay) {
199 vo_x11_fullscreen();
200 overlay_signalmode(overlay_data,
201 vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
202 EM8300_OVERLAY_SIGNAL_WITH_VGA);
203 return VO_TRUE;
205 return VO_FALSE;
206 #endif
207 case VOCTRL_RESUME:
208 if (dxr3_newsync) {
209 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
210 pts_offset = vo_pts - (ioval << 1);
211 if (pts_offset < 0) {
212 pts_offset = 0;
216 if (dxr3_prebuf) {
217 ioval = EM8300_PLAYMODE_PLAY;
218 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
219 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
222 return VO_TRUE;
223 case VOCTRL_PAUSE:
224 if (dxr3_prebuf) {
225 ioval = EM8300_PLAYMODE_PAUSED;
226 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
227 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
230 return VO_TRUE;
231 case VOCTRL_RESET:
232 if (dxr3_prebuf) {
233 close(fd_video);
234 fd_video = open(fdv_name, O_WRONLY);
235 close(fd_spu);
236 fd_spu = open(fds_name, O_WRONLY);
237 fsync(fd_video);
238 fsync(fd_spu);
240 return VO_TRUE;
241 case VOCTRL_QUERY_FORMAT:
243 uint32_t flag = 0;
245 if (*((uint32_t*)data) != IMGFMT_MPEGPES)
246 return 0;
248 flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
249 if (dxr3_prebuf)
250 flag |= VFCAP_TIMER;
251 return flag;
253 case VOCTRL_SET_EQUALIZER:
255 va_list ap;
256 int value;
257 em8300_bcs_t bcs;
259 va_start(ap, data);
260 value = va_arg(ap, int);
261 va_end(ap);
263 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
264 return VO_FALSE;
265 if (!strcasecmp(data, "brightness"))
266 bcs.brightness = (value+100)*5;
267 else if (!strcasecmp(data, "contrast"))
268 bcs.contrast = (value+100)*5;
269 else if (!strcasecmp(data, "saturation"))
270 bcs.saturation = (value+100)*5;
271 else return VO_FALSE;
273 if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
274 return VO_FALSE;
275 return VO_TRUE;
277 case VOCTRL_GET_EQUALIZER:
279 va_list ap;
280 int *value;
281 em8300_bcs_t bcs;
283 va_start(ap, data);
284 value = va_arg(ap, int*);
285 va_end(ap);
287 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
288 return VO_FALSE;
290 if (!strcasecmp(data, "brightness"))
291 *value = (bcs.brightness/5)-100;
292 else if (!strcasecmp(data, "contrast"))
293 *value = (bcs.contrast/5)-100;
294 else if (!strcasecmp(data, "saturation"))
295 *value = (bcs.saturation/5)-100;
296 else return VO_FALSE;
298 return VO_TRUE;
301 return VO_NOTIMPL;
304 void calculate_cvals(unsigned long mask, int *shift, int *prec)
306 /* Calculate shift and precision */
307 (*shift) = 0;
308 (*prec) = 0;
310 while (!(mask & 0x1)) {
311 (*shift)++;
312 mask >>= 1;
315 while (mask & 0x1) {
316 (*prec)++;
317 mask >>= 1;
321 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)
323 int tmp1, tmp2, size;
324 em8300_register_t reg;
325 extern float monitor_aspect;
327 /* Softzoom turned on, downscale */
328 /* This activates the subpicture processor, you can safely disable this and still send */
329 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
330 /* up in a lockup */
331 ioval = EM8300_SPUMODE_ON;
332 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
333 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetSubpictureMode);
334 uninit();
335 return -1;
338 /* Set the playmode to play (just in case another app has set it to something else) */
339 ioval = EM8300_PLAYMODE_PLAY;
340 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
341 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
344 /* Start em8300 prebuffering and sync engine */
345 reg.microcode_register = 1;
346 reg.reg = 0;
347 reg.val = MVCOMMAND_SYNC;
348 ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
350 /* Clean buffer by syncing it */
351 ioval = EM8300_SUBDEVICE_VIDEO;
352 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
353 ioval = EM8300_SUBDEVICE_AUDIO;
354 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
356 /* Sync the video device to make sure the buffers are empty
357 * and set the playback speed to normal. Also reset the
358 * em8300 internal clock.
360 fsync(fd_video);
361 ioval = 0x900;
362 ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
364 /* Store some variables statically that we need later in another scope */
365 img_format = format;
366 v_width = width;
367 v_height = height;
369 /* Set monitor_aspect to avoid jitter */
370 monitor_aspect = (float) width / (float) height;
372 if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
373 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToGetTVNorm);
374 old_vmode = -1;
377 /* adjust TV norm */
378 if (dxr3_norm != 0) {
379 if (dxr3_norm == 5) {
380 ioval = EM8300_VIDEOMODE_NTSC;
381 } else if (dxr3_norm == 4) {
382 ioval = EM8300_VIDEOMODE_PAL60;
383 } else if (dxr3_norm == 3) {
384 ioval = EM8300_VIDEOMODE_PAL;
385 } else if (dxr3_norm == 2) {
386 if (vo_fps > 28) {
387 ioval = EM8300_VIDEOMODE_PAL60;
388 } else {
389 ioval = EM8300_VIDEOMODE_PAL;
392 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
393 ioval == EM8300_VIDEOMODE_PAL60 ? mp_msg(MSGT_VO,MSGL_INFO, "PAL-60") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
394 printf(".\n");
395 } else {
396 if (vo_fps > 28) {
397 ioval = EM8300_VIDEOMODE_NTSC;
398 } else {
399 ioval = EM8300_VIDEOMODE_PAL;
402 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
403 ioval == EM8300_VIDEOMODE_NTSC ? mp_msg(MSGT_VO,MSGL_INFO, "NTSC") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
404 printf(".\n");
407 if (old_vmode != ioval) {
408 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
409 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetTVNorm);
415 /* libavcodec requires a width and height that is x|16 */
416 aspect_save_orig(width, height);
417 aspect_save_prescale(d_width, d_height);
418 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
419 if (ioval == EM8300_VIDEOMODE_NTSC) {
420 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForNTSC);
421 aspect_save_screenres(352, 240);
422 } else {
423 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForPALSECAM);
424 aspect_save_screenres(352, 288);
426 aspect(&s_width, &s_height, A_ZOOM);
427 s_width -= s_width % 16;
428 s_height -= s_height % 16;
430 /* Try to figure out whether to use widescreen output or not */
431 /* Anamorphic widescreen modes makes this a pain in the ass */
432 tmp1 = abs(d_height - ((d_width / 4) * 3));
433 tmp2 = abs(d_height - (int) (d_width / 2.35));
434 if (tmp1 < tmp2) {
435 ioval = EM8300_ASPECTRATIO_4_3;
436 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo43);
437 } else {
438 ioval = EM8300_ASPECTRATIO_16_9;
439 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo169);
441 ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
443 #ifdef SPU_SUPPORT
444 #ifdef CONFIG_FREETYPE
445 if (ioval == EM8300_ASPECTRATIO_16_9) {
446 s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
447 } else {
448 s_width *= 0.84;
450 //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
451 #else
452 s_width*=2;
453 s_height*=2;
454 #endif
456 osdpicbuf = calloc( 1,s_width * s_height);
457 if (osdpicbuf == NULL) {
458 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
459 return -1;
461 spued = (encodedata *) malloc(sizeof(encodedata));
462 if (spued == NULL) {
463 free( osdpicbuf );
464 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
465 return -1;
467 spubuf = (encodedata *) malloc(sizeof(encodedata));
468 if (spubuf == NULL) {
469 free( osdpicbuf );
470 free( spued );
471 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
472 return -1;
474 osd_w = s_width;
475 osd_h = s_height;
476 osdpicbuf_w = s_width;
477 osdpicbuf_h = s_height;
479 spubuf->count=0;
480 pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
482 #endif
484 #ifdef CONFIG_X11
485 if (dxr3_overlay) {
486 XVisualInfo vinfo;
487 XSetWindowAttributes xswa;
488 XSizeHints hint;
489 unsigned long xswamask;
490 Colormap cmap;
491 XColor key_color;
492 Window junkwindow;
493 Screen *scr;
494 int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
495 em8300_overlay_screen_t ovlscr;
496 em8300_attribute_t ovlattr;
498 vo_dx = (vo_screenwidth - d_width) / 2;
499 vo_dy = (vo_screenheight - d_height) / 2;
500 vo_dwidth = d_width;
501 vo_dheight = d_height;
502 #ifdef CONFIG_GUI
503 if (use_gui) {
504 guiGetEvent(guiSetShVideo, 0);
505 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
506 XClearWindow(mDisplay, vo_window);
507 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
508 depth = xwin_attribs.depth;
509 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
510 depth = 24;
512 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
513 } else
514 #endif
516 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
517 depth = xwin_attribs.depth;
518 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
519 depth = 24;
521 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
522 vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy,
523 d_width, d_height, flags,
524 CopyFromParent, "Viewing Window", title);
525 xswa.background_pixel = KEY_COLOR;
526 xswa.border_pixel = 0;
527 xswamask = CWBackPixel | CWBorderPixel;
528 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa);
531 /* Start setting up overlay */
532 XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
533 overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
534 overlay_read_state(overlay_data, NULL);
536 /* Allocate keycolor */
537 cmap = vo_x11_create_colormap(&vinfo);
538 calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
539 calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
540 calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
542 key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
543 key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
544 key_color.blue = (KEY_COLOR & 0xff) * 256;
545 key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
546 ((key_color.green >> (16 - green_prec)) << green_shift) +
547 ((key_color.blue >> (16 - blue_prec)) << blue_shift));
548 key_color.flags = DoRed | DoGreen | DoBlue;
549 if (!XAllocColor(mDisplay, cmap, &key_color)) {
550 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToAllocateKeycolor);
551 return -1;
554 acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
555 if (key_color.pixel != KEY_COLOR) {
556 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToAllocateExactKeycolor, key_color.pixel);
559 /* Set keycolor and activate overlay */
560 XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
561 XClearWindow(mDisplay, vo_window);
562 overlay_set_keycolor(overlay_data, key_color.pixel);
563 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
564 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
566 #endif
568 return 0;
571 static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
573 #ifdef SPU_SUPPORT
574 unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
575 int by = 0;
576 register int lx, ly;
577 register int stride = 0;
579 for (ly = 0; ly < h - 1; ly++)
581 for(lx = 0; lx < w; lx++ )
582 if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
583 by+=osdpicbuf_w;
584 stride+=srcstride;
586 pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
587 #endif
590 extern int vo_osd_changed_flag;
591 extern mp_osd_obj_t* vo_osd_list;
593 static void draw_osd(void)
595 #ifdef SPU_SUPPORT
596 static int cleared = 0;
597 int changed = 0;
599 if ((disposd % 15) == 0)
602 mp_osd_obj_t* obj = vo_osd_list;
603 vo_update_osd( osd_w,osd_h );
604 while( obj )
606 if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
607 obj=obj->next;
610 if ( changed )
612 vo_draw_text(osd_w, osd_h, draw_alpha);
613 memset(osdpicbuf, 0, s_width * s_height);
614 cleared=0;
616 else
618 if ( !cleared )
620 spued->count=spubuf->count;
621 fast_memcpy( spued->data,spubuf->data,DATASIZE );
622 cleared=1;
627 /* could stand some check here to see if the subpic hasn't changed
628 * as if it hasn't and we re-send it it will "blink" as the last one
629 * is turned off, and the new one (same one) is turned on
631 /* Subpics are not stable yet =(
632 expect lockups if you enable */
633 #if 1
634 write(fd_spu, spued->data, spued->count);
635 #endif
637 disposd++;
638 #endif
642 static int draw_frame(uint8_t * src[])
644 vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
646 #ifdef SPU_SUPPORT
647 if (p->id == 0x20) {
648 write(fd_spu, p->data, p->size);
649 } else
650 #endif
651 write(fd_video, p->data, p->size);
652 return 0;
655 static void flip_page(void)
657 #ifdef CONFIG_X11
658 if (dxr3_overlay) {
659 int event = vo_x11_check_events(mDisplay);
660 if (event & VO_EVENT_RESIZE) {
661 Window junkwindow;
662 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
663 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
664 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
666 if (event & VO_EVENT_EXPOSE) {
667 Window junkwindow;
668 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
669 XClearWindow(mDisplay, vo_window);
670 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
671 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
672 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
675 #endif
677 if (dxr3_newsync) {
678 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
679 ioval <<= 1;
680 if (vo_pts == 0) {
681 ioval = 0;
682 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
683 pts_offset = 0;
684 } else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
685 ioval = (vo_pts + pts_offset) >> 1;
686 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
687 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
688 pts_offset = vo_pts - (ioval << 1);
689 if (pts_offset < 0) {
690 pts_offset = 0;
693 ioval = vo_pts + pts_offset;
694 ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
695 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
696 prev_pts = vo_pts;
697 } else if (dxr3_prebuf) {
698 ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
699 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
703 static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
705 return -1;
708 static void uninit(void)
710 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Uninitializing);
711 #ifdef CONFIG_X11
712 if (dxr3_overlay) {
713 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
714 overlay_release(overlay_data);
716 #ifdef CONFIG_GUI
717 if (!use_gui) {
718 #endif
719 vo_x11_uninit();
721 #ifdef CONFIG_GUI
723 #endif
725 #endif
726 if (old_vmode != -1) {
727 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
728 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedRestoringTVNorm);
732 if (fd_video) {
733 close(fd_video);
735 if (fd_spu) {
736 close(fd_spu);
738 if (fd_control) {
739 close(fd_control);
741 #ifdef SPU_SUPPORT
742 if(osdpicbuf) {
743 free(osdpicbuf);
745 if(spued) {
746 free(spued);
748 #endif
751 static void check_events(void)
755 static int preinit(const char *arg)
757 char devname[MAX_STR_SIZE];
758 int fdflags = O_WRONLY;
760 /* Parse commandline */
761 while (arg) {
762 if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
763 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_EnablingPrebuffering);
764 dxr3_prebuf = 1;
765 } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
766 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingNewSyncEngine);
767 dxr3_newsync = 1;
768 } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
769 #ifdef CONFIG_X11
770 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingOverlay);
771 dxr3_overlay = 1;
772 #else
773 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorYouNeedToCompileMplayerWithX11);
774 #endif
775 } else if (!strncmp("norm=", arg, 5)) {
776 arg += 5;
777 // dxr3_norm is 0 (-> don't change norm) by default
778 // but maybe someone changes this in the future
780 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_WillSetTVNormTo);
782 if (*arg == '5') {
783 dxr3_norm = 5;
784 mp_msg(MSGT_VO,MSGL_INFO, "NTSC");
785 } else if (*arg == '4') {
786 dxr3_norm = 4;
787 mp_msg(MSGT_VO,MSGL_INFO, "PAL-60");
788 } else if (*arg == '3') {
789 dxr3_norm = 3;
790 mp_msg(MSGT_VO,MSGL_INFO, "PAL");
791 } else if (*arg == '2') {
792 dxr3_norm = 2;
793 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALPAL60);
794 } else if (*arg == '1') {
795 dxr3_norm = 1;
796 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALNTSC);
797 } else if (*arg == '0') {
798 dxr3_norm = 0;
799 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseCurrentNorm);
800 } else {
801 dxr3_norm = 0;
802 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseUnknownNormSuppliedCurrentNorm);
805 mp_msg(MSGT_VO,MSGL_INFO, ".\n");
806 } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
807 dxr3_device_num = arg[0];
810 arg = strchr(arg, ':');
811 if (arg) {
812 arg++;
817 /* Open the control interface */
818 sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
819 fd_control = open(devname, fdflags);
820 if (fd_control < 1) {
821 /* Fall back to old naming scheme */
822 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTrying, devname);
823 sprintf(devname, "/dev/em8300");
824 fd_control = open(devname, fdflags);
825 if (fd_control < 1) {
826 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWell);
827 return -1;
829 } else {
830 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
833 /* Open the video interface */
834 sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
835 fd_video = open(devname, fdflags);
836 if (fd_video < 0) {
837 /* Fall back to old naming scheme */
838 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingMV, devname);
839 sprintf(devname, "/dev/em8300_mv");
840 fd_video = open(devname, fdflags);
841 if (fd_video < 0) {
842 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellMV);
843 uninit();
844 return -1;
846 } else {
847 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
849 strcpy(fdv_name, devname);
851 /* Open the subpicture interface */
852 sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
853 fd_spu = open(devname, fdflags);
854 if (fd_spu < 0) {
855 /* Fall back to old naming scheme */
856 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingSP, devname);
857 sprintf(devname, "/dev/em8300_sp");
858 fd_spu = open(devname, fdflags);
859 if (fd_spu < 0) {
860 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellSP);
861 uninit();
862 return -1;
864 } else {
865 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
867 strcpy(fds_name, devname);
869 #ifdef CONFIG_X11
870 if (dxr3_overlay) {
872 /* Fucked up hack needed to enable overlay.
873 * Will be removed as soon as I figure out
874 * how to make it work like it should
876 Display *dpy;
877 overlay_t *ov;
878 XWindowAttributes attribs;
880 dpy = XOpenDisplay(NULL);
881 if (!dpy) {
882 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToOpenDisplayDuringHackSetup);
883 return -1;
885 XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
886 ov = overlay_init(fd_control);
887 overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
888 overlay_read_state(ov, NULL);
889 overlay_set_keycolor(ov, KEY_COLOR);
890 overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
891 overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
892 overlay_release(ov);
893 XCloseDisplay(dpy);
894 /* End of fucked up hack */
896 /* Initialize overlay and X11 */
897 overlay_data = overlay_init(fd_control);
898 #ifdef CONFIG_GUI
899 if (!use_gui) {
900 #endif
901 if (!vo_init()) {
902 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToInitX11);
903 return -1;
905 #ifdef CONFIG_GUI
907 #endif
909 #endif
911 if (dxr3_newsync) {
912 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
913 pts_offset = vo_pts - (ioval << 1);
914 if (pts_offset < 0) {
915 pts_offset = 0;
919 return 0;
922 /* Begin overlay.c */
923 static int update_parameters(overlay_t *o)
925 overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
926 overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
927 overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
928 overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
929 overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
930 return 0;
933 static int overlay_set_attribute(overlay_t *o, int attribute, int value)
935 em8300_attribute_t attr;
937 attr.attribute = attribute;
938 attr.value = value;
939 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
941 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayAttribute);
942 return -1;
945 return 0;
948 static overlay_t *overlay_init(int dev)
950 overlay_t *o;
952 o = (overlay_t *) malloc(sizeof(overlay_t));
954 if(!o)
955 return NULL;
957 memset(o,0,sizeof(overlay_t));
959 o->dev = dev;
960 o->xres = 1280; o->yres=1024; o->xcorr=1000;
961 o->color_interval=10;
963 return o;
966 static int overlay_release(overlay_t *o)
968 if(o)
969 free(o);
971 return 0;
973 #define TYPE_INT 1
974 #define TYPE_XINT 2
975 #define TYPE_COEFF 3
976 #define TYPE_FLOAT 4
978 struct lut_entry {
979 char *name;
980 int type;
981 void *ptr;
984 static struct lut_entry *new_lookuptable(overlay_t *o)
986 struct lut_entry m[] = {
987 {"xoffset", TYPE_INT, &o->xoffset},
988 {"yoffset", TYPE_INT, &o->yoffset},
989 {"xcorr", TYPE_INT, &o->xcorr},
990 {"jitter", TYPE_INT, &o->jitter},
991 {"stability", TYPE_INT, &o->stability},
992 {"keycolor", TYPE_XINT, &o->keycolor},
993 {"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
994 {"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
995 {"color_interval", TYPE_FLOAT, &o->color_interval},
996 {0,0,0}
997 },*p;
999 p = malloc(sizeof(m));
1000 memcpy(p,m,sizeof(m));
1001 return p;
1004 static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
1005 int i;
1007 for(i=0; lut[i].name; i++) {
1008 if(!strcmp(name,lut[i].name)) {
1009 *ptr = lut[i].ptr;
1010 *type = lut[i].type;
1011 return 1;
1014 return 0;
1017 static int overlay_read_state(overlay_t *o, char *p)
1019 char *a,*tok;
1020 char path[128],fname[128],tmp[128],line[256];
1021 FILE *fp;
1022 struct lut_entry *lut;
1023 void *ptr;
1024 int type;
1025 int j;
1027 if(!p) {
1028 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1029 av_strlcat(fname,"/.overlay", sizeof( fname ));
1030 } else
1031 av_strlcpy(fname, p, sizeof( fname ));
1033 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1034 av_strlcat(fname, tmp, sizeof( fname ));
1036 if(!(fp=fopen(fname,"r")))
1037 return -1;
1039 lut = new_lookuptable(o);
1041 while(!feof(fp)) {
1042 if(!fgets(line,256,fp))
1043 break;
1044 tok=strtok(line," ");
1045 if(lookup_parameter(o,lut,tok,&ptr,&type)) {
1046 tok=strtok(NULL," ");
1047 switch(type) {
1048 case TYPE_INT:
1049 sscanf(tok,"%d",(int *)ptr);
1050 break;
1051 case TYPE_XINT:
1052 sscanf(tok,"%x",(int *)ptr);
1053 break;
1054 case TYPE_FLOAT:
1055 sscanf(tok,"%f",(float *)ptr);
1056 break;
1057 case TYPE_COEFF:
1058 for(j=0;j<3;j++) {
1059 sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1060 tok=strtok(NULL," ");
1061 sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1062 tok=strtok(NULL," ");
1064 break;
1070 update_parameters(o);
1072 free(lut);
1073 fclose(fp);
1074 return 0;
1077 static void overlay_update_params(overlay_t *o) {
1078 update_parameters(o);
1081 static int overlay_write_state(overlay_t *o, char *p)
1083 char *a;
1084 char path[128],fname[128],tmp[128];
1085 FILE *fp;
1086 char line[256],*tok;
1087 struct lut_entry *lut;
1088 int i,j;
1090 if(!p) {
1091 av_strlcpy(fname, getenv("HOME"), sizeof( fname ));
1092 av_strlcat(fname,"/.overlay", sizeof( fname ));
1093 } else
1094 av_strlcpy(fname, p, sizeof( fname ));
1096 if(access(fname, W_OK|X_OK|R_OK)) {
1097 if(mkdir(fname,0766))
1098 return -1;
1101 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1102 av_strlcat(fname, tmp, sizeof( fname ));
1104 if(!(fp=fopen(fname,"w")))
1105 return -1;
1107 lut = new_lookuptable(o);
1109 for(i=0; lut[i].name; i++) {
1110 fprintf(fp,"%s ",lut[i].name);
1111 switch(lut[i].type) {
1112 case TYPE_INT:
1113 fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1114 break;
1115 case TYPE_XINT:
1116 fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1117 break;
1118 case TYPE_FLOAT:
1119 fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1120 break;
1121 case TYPE_COEFF:
1122 for(j=0;j<3;j++)
1123 fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1124 ((struct coeff *)lut[i].ptr)[j].m);
1125 fprintf(fp,"\n");
1126 break;
1130 fclose(fp);
1131 return 0;
1134 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1136 em8300_overlay_screen_t scr;
1138 o->xres = xres;
1139 o->yres = yres;
1140 o->depth = depth;
1142 scr.xsize = xres;
1143 scr.ysize = yres;
1145 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1147 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayScreen);
1148 return -1;
1150 return 0;
1153 static int overlay_set_mode(overlay_t *o, int mode)
1155 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1156 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedEnablingOverlay);
1157 return -1;
1159 return 0;
1162 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1164 em8300_overlay_window_t win;
1165 win.xpos = xpos;
1166 win.ypos = ypos;
1167 win.width = width;
1168 win.height = height;
1170 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1172 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1173 return -1;
1175 return 0;
1178 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1180 em8300_bcs_t bcs;
1181 bcs.brightness = brightness;
1182 bcs.contrast = contrast;
1183 bcs.saturation = saturation;
1185 if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1187 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayBcs);
1188 return -1;
1190 return 0;
1193 static int col_interp(float x, struct coeff c)
1195 float y;
1196 y = x*c.k + c.m;
1197 if(y > 255)
1198 y = 255;
1199 if(y < 0)
1200 y = 0;
1201 return rint(y);
1204 static int overlay_set_keycolor(overlay_t *o, int color) {
1205 int r = (color & 0xff0000) >> 16;
1206 int g = (color & 0x00ff00) >> 8;
1207 int b = (color & 0x0000ff);
1208 float ru,gu,bu;
1209 float rl,gl,bl;
1210 int upper,lower;
1212 ru = r+o->color_interval;
1213 gu = g+o->color_interval;
1214 bu = b+o->color_interval;
1216 rl = r-o->color_interval;
1217 gl = g-o->color_interval;
1218 bl = b-o->color_interval;
1220 upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1221 (col_interp(gu, o->colcal_upper[1]) << 8) |
1222 (col_interp(bu, o->colcal_upper[2]));
1224 lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1225 (col_interp(gl, o->colcal_lower[1]) << 8) |
1226 (col_interp(bl, o->colcal_lower[2]));
1228 //printf("0x%06x 0x%06x\n",upper,lower);
1229 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1230 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1231 return 0;
1234 static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1236 float sx=0,sy=0,sxx=0,sxy=0;
1237 float delta,b;
1238 int i;
1240 for(i=0; i < n; i++) {
1241 sx=sx+x[i];
1242 sy=sy+y[i];
1243 sxx=sxx+x[i]*x[i];
1244 sxy=sxy+x[i]*y[i];
1247 delta=sxx*n-sx*sx;
1249 *m=(sxx*sy-sx*sxy)/delta;
1250 *k=(sxy*n-sx*sy)/delta;
1253 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1255 em8300_overlay_calibrate_t cal;
1256 em8300_overlay_window_t win;
1257 int x[256],r[256],g[256],b[256],n;
1258 float k,m;
1260 int i;
1262 o->draw_pattern=pd;
1263 o->dp_arg = arg;
1265 overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1266 overlay_set_screen(o, o->xres, o->yres, o->depth);
1268 /* Calibrate Y-offset */
1270 o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1272 cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1273 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1275 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayYOffsetValues);
1276 return -1;
1278 o->yoffset = cal.result;
1279 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_YOffset,cal.result);
1281 /* Calibrate X-offset */
1283 o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1285 cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1286 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1288 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXOffsetValues);
1289 return -1;
1291 o->xoffset = cal.result;
1292 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XOffset,cal.result);
1294 /* Calibrate X scale correction */
1296 o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1298 cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1299 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1301 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXScaleCorrection);
1302 return -1;
1304 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XCorrection,cal.result);
1305 o->xcorr = cal.result;
1307 win.xpos = 10;
1308 win.ypos = 10;
1309 win.width = o->xres-20;
1310 win.height = o->yres-20;
1311 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1312 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1313 exit(1);
1316 /* Calibrate key color upper limit */
1318 for(i=128,n=0; i <= 0xff; i+=4) {
1319 o->draw_pattern(i | (i << 8) | (i << 16), 0,
1320 (o->xres-200)/2,0,200,o->yres,o->dp_arg);
1322 cal.arg = i;
1323 cal.arg2 = 1;
1324 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1326 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1328 return -1 ;
1331 x[n] = i;
1332 r[n] = (cal.result>>16)&0xff;
1333 g[n] = (cal.result>>8)&0xff;
1334 b[n] = (cal.result)&0xff;
1335 n++;
1338 least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1339 least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1340 least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1342 /* Calibrate key color lower limit */
1344 for(i=128,n=0; i <= 0xff; i+=4) {
1345 o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1346 (o->xres-200)/2,0,200,o->yres, o->dp_arg);
1348 cal.arg = i;
1349 cal.arg2 = 2;
1350 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1352 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1354 return -1 ;
1356 x[n] = i;
1357 r[n] = (cal.result>>16)&0xff;
1358 g[n] = (cal.result>>8)&0xff;
1359 b[n] = (cal.result)&0xff;
1360 n++;
1363 least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1364 least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1365 least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1367 overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1369 return 0;
1373 static int overlay_signalmode(overlay_t *o, int mode) {
1374 if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1375 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSetSignalMix);
1376 return -1;
1378 return 0;
1380 /* End overlay.c */