typo fixes
[mplayer/greg.git] / libvo / vo_dxr3.c
blobb588b5bf715cde12188c111f80247d226b6a94c5
1 /*
2 * vo_dxr3.c - DXR3/H+ video out
4 * Copyright (C) 2002-2003 David Holm <david@realityrift.com>
6 */
8 /* ChangeLog added 2002-01-10
9 * 2003-11-28:
10 * Added a patch from Anders Rune Jensen to support the latest em8300 CVS
11 * changes.
13 * 2003-02-19:
14 * Yet another patch from Tamas Kohegyi to fix subpic placement.
16 * 2003-01-12:
17 * Added patch from Tamas Kohegyi to fix subpic placement with freetype.
19 * 2003-01-02:
20 * Added patch from Jens Axboe that makes vo_dxr3 return to previous TV norm
21 * after quiting.
22 * Added patch from Thomas Jarosch that fixed alot of textual ouput
23 * errors.
25 * 2002-12-24: (Hohoho)
26 * Added patch from Thomas Jarosch <tomj@simonv.com> which adds support
27 * for setting the TV norm by movie framerate.
29 * 2002-11-03:
30 * Cleaned up syncing code and renamed setup variables so
31 * they can be accessed from the GUI.
33 * 2002-11-02:
34 * Added native overlay support, activate with :overlay
35 * you have to run dxr3view to modify settings (or manually
36 * edit the files in ~/.overlay.
38 * 2002-10-29:
39 * Added new sync-engine, activate with :sync option.
40 * Greatly improved commandline parser.
41 * Replaced :noprebuf with :prebuf and made noprebuf the default.
43 * 2002-10-28:
44 * Fixed multicard bug on athlons
46 * 2002-07-18:
47 * Disabled spuenc support, this is still not stable enough =(
49 * 2002-07-05:
50 * Removed lavc and fame encoder to be compatible with new libvo style.
51 * Added graphic equalizer support.
53 * 2002-04-15:
54 * The spuenc code isn't 100% stable yet, therefore I'm disabling
55 * it due to the upcoming stable release.
57 * 2002-04-03:
58 * Carl George added spuenc support
60 * 2002-03-26:
61 * XorA added an option parser and support for selecting encoder
62 * codec. We thank him again.
64 * 2002-03-25:
65 * A couple of bugfixes by XorA
67 * 2002-03-23:
68 * Thanks to Marcel Hild <hild@b4mad.net> the jitter-bug experienced
69 * with some videos have been fixed, many thanks goes to him.
71 * 2002-03-16:
72 * Fixed problems with fame, it gives a better picture than avcodec,
73 * but is slightly slower. Most notably the wobbling effect is gone
74 * with fame.
76 * 2002-03-13:
77 * Preliminary fame support added (it breaks after seeking, why?)
79 * 2002-02-18:
80 * Fixed sync problems when pausing video (while using prebuffering)
82 * 2002-02-16:
83 * Fixed bug which would case invalid output when using :noprebuf
84 * Removed equalization code, it caused problems on slow systems
86 * 2002-02-13:
87 * Using the swscaler instead of the old hand coded shit. (Checkout man mplayer and search for sws ;).
88 * Using aspect function to setup a proper mpeg1, no more hassling with odd resolutions or GOP-sizes,
89 * this would only create jitter on some vids!
90 * The swscaler sometimes exits with sig8 on mpegs, I don't know why yet (just use -vc mpegpes in this
91 * case, and report to me if you have any avi's etc which does this...)
93 * 2002-02-09:
94 * Thanks to the new control() method I have finally been able to enable the em8300 prebuffering.
95 * This should speed up playback on all systems, the vout cpu usage should rocket since I will be hogging
96 * the pci bus. Not to worry though, since frames are prebuffered it should be able to take a few blows
97 * if you start doing other stuff simultaneously.
99 * 2002-02-03:
100 * Removal of libmp1e, libavcodec has finally become faster (and it's code is helluva lot cleaner)
102 * 2002-02-02:
103 * Cleaned out some old code which might have slowed down writes
105 * 2002-01-17:
106 * Testrelease of new sync engine (using previously undocumented feature of em8300).
108 * 2002-01-15:
109 * Preliminary subpic support with -vc mpegpes and dvd's
110 * Device interfaces tries the new naming scheme by default (even though most users probably still use the old one)
112 * 2002-01-10:
113 * I rehauled the entire codebase. I have now changed to
114 * Kernighan & Ritchie codingstyle, please mail me if you
115 * find any inconcistencies.
118 #include <linux/em8300.h>
119 #include <sys/ioctl.h>
120 #include <sys/stat.h>
121 #include <sys/types.h>
122 #include <sys/select.h>
123 #include <unistd.h>
124 #include <stdio.h>
125 #include <stdlib.h>
126 #include <string.h>
127 #include <fcntl.h>
128 #include <stdio.h>
129 #include <time.h>
130 #include <math.h>
132 #include "config.h"
133 #include "mp_msg.h"
134 #include "help_mp.h"
135 #ifdef HAVE_MALLOC_H
136 #include <malloc.h>
137 #endif
138 #include "fastmemcpy.h"
140 #include "video_out.h"
141 #include "video_out_internal.h"
142 #include "aspect.h"
143 #include "spuenc.h"
144 #include "sub.h"
145 #ifdef HAVE_NEW_GUI
146 #include "Gui/interface.h"
147 #endif
148 #ifdef HAVE_X11
149 #include "x11_common.h"
150 #endif
152 #define SPU_SUPPORT
154 static vo_info_t info =
156 "DXR3/H+ video out",
157 "dxr3",
158 "David Holm <dholm@iname.com>",
161 LIBVO_EXTERN (dxr3)
163 /* Resolutions and positions */
164 static int v_width, v_height;
165 static int s_width, s_height;
166 static int osd_w, osd_h;
167 static int img_format;
169 /* Configuration values
170 * Don't declare these static, they
171 * should be accessible from the gui.
173 int dxr3_prebuf = 0;
174 int dxr3_newsync = 0;
175 int dxr3_overlay = 0;
176 int dxr3_device_num = 0;
177 int dxr3_norm = 0;
179 #define MAX_STR_SIZE 80 /* length for the static strings */
181 /* File descriptors */
182 static int fd_control = -1;
183 static int fd_video = -1;
184 static int fd_spu = -1;
185 static char fdv_name[MAX_STR_SIZE];
186 static char fds_name[MAX_STR_SIZE];
188 #ifdef SPU_SUPPORT
189 /* on screen display/subpics */
190 static char *osdpicbuf;
191 static int osdpicbuf_w;
192 static int osdpicbuf_h;
193 static int disposd;
194 static encodedata *spued;
195 static encodedata *spubuf;
196 #endif
199 /* Static variable used in ioctl's */
200 static int ioval;
201 static int prev_pts;
202 static int pts_offset;
203 static int old_vmode = -1;
206 /* Begin overlay.h */
208 Simple analog overlay API for DXR3/H+ linux driver.
210 Henrik Johansson
214 /* Pattern drawing callback used by the calibration functions.
215 The function is expected to:
216 Clear the entire screen.
217 Fill the screen with color bgcol (0xRRGGBB)
218 Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
221 typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
222 int xpos, int ypos, int width, int height, void *arg);
224 struct coeff {
225 float k,m;
228 typedef struct {
229 int dev;
231 int xres, yres,depth;
232 int xoffset,yoffset,xcorr;
233 int jitter;
234 int stability;
235 int keycolor;
236 struct coeff colcal_upper[3];
237 struct coeff colcal_lower[3];
238 float color_interval;
240 pattern_drawer_cb draw_pattern;
241 void *dp_arg;
242 } overlay_t;
245 static overlay_t *overlay_init(int dev);
246 static int overlay_release(overlay_t *);
248 static int overlay_read_state(overlay_t *o, char *path);
249 static int overlay_write_state(overlay_t *o, char *path);
251 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
252 static int overlay_set_mode(overlay_t *o, int mode);
253 static int overlay_set_attribute(overlay_t *o, int attribute, int val);
254 static int overlay_set_keycolor(overlay_t *o, int color);
255 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
256 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
258 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
259 static void overlay_update_params(overlay_t *o);
260 static int overlay_signalmode(overlay_t *o, int mode);
261 /* End overlay.h */
264 #ifdef HAVE_X11
265 #define KEY_COLOR 0x80a040
266 static XWindowAttributes xwin_attribs;
267 static overlay_t *overlay_data;
268 #endif
271 /* Functions for working with the em8300's internal clock */
272 /* End of internal clock functions */
274 static int control(uint32_t request, void *data, ...)
276 switch (request) {
277 case VOCTRL_GUISUPPORT:
278 return VO_TRUE;
279 case VOCTRL_GUI_NOWINDOW:
280 if (dxr3_overlay) {
281 return VO_FALSE;
283 return VO_TRUE;
284 case VOCTRL_SET_SPU_PALETTE:
285 if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
286 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToLoadNewSPUPalette);
287 return VO_ERROR;
289 return VO_TRUE;
290 #ifdef HAVE_X11
291 case VOCTRL_ONTOP:
292 vo_x11_ontop();
293 return VO_TRUE;
294 case VOCTRL_FULLSCREEN:
295 if (dxr3_overlay) {
296 vo_x11_fullscreen();
297 overlay_signalmode(overlay_data,
298 vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
299 EM8300_OVERLAY_SIGNAL_WITH_VGA);
300 return VO_TRUE;
302 return VO_FALSE;
303 #endif
304 case VOCTRL_RESUME:
305 if (dxr3_newsync) {
306 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
307 pts_offset = vo_pts - (ioval << 1);
308 if (pts_offset < 0) {
309 pts_offset = 0;
313 if (dxr3_prebuf) {
314 ioval = EM8300_PLAYMODE_PLAY;
315 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
316 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
319 return VO_TRUE;
320 case VOCTRL_PAUSE:
321 if (dxr3_prebuf) {
322 ioval = EM8300_PLAYMODE_PAUSED;
323 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
324 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
327 return VO_TRUE;
328 case VOCTRL_RESET:
329 if (dxr3_prebuf) {
330 close(fd_video);
331 fd_video = open(fdv_name, O_WRONLY);
332 close(fd_spu);
333 fd_spu = open(fds_name, O_WRONLY);
334 fsync(fd_video);
335 fsync(fd_spu);
337 return VO_TRUE;
338 case VOCTRL_QUERY_FORMAT:
340 uint32_t flag = 0;
342 if (*((uint32_t*)data) != IMGFMT_MPEGPES)
343 return 0;
345 flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
346 if (dxr3_prebuf)
347 flag |= VFCAP_TIMER;
348 return flag;
350 case VOCTRL_SET_EQUALIZER:
352 va_list ap;
353 int value;
354 em8300_bcs_t bcs;
356 va_start(ap, data);
357 value = va_arg(ap, int);
358 va_end(ap);
360 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
361 return VO_FALSE;
362 if (!strcasecmp(data, "brightness"))
363 bcs.brightness = (value+100)*5;
364 else if (!strcasecmp(data, "contrast"))
365 bcs.contrast = (value+100)*5;
366 else if (!strcasecmp(data, "saturation"))
367 bcs.saturation = (value+100)*5;
368 else return VO_FALSE;
370 if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
371 return VO_FALSE;
372 return VO_TRUE;
374 case VOCTRL_GET_EQUALIZER:
376 va_list ap;
377 int *value;
378 em8300_bcs_t bcs;
380 va_start(ap, data);
381 value = va_arg(ap, int*);
382 va_end(ap);
384 if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
385 return VO_FALSE;
387 if (!strcasecmp(data, "brightness"))
388 *value = (bcs.brightness/5)-100;
389 else if (!strcasecmp(data, "contrast"))
390 *value = (bcs.contrast/5)-100;
391 else if (!strcasecmp(data, "saturation"))
392 *value = (bcs.saturation/5)-100;
393 else return VO_FALSE;
395 return VO_TRUE;
398 return VO_NOTIMPL;
401 void calculate_cvals(unsigned long mask, int *shift, int *prec)
403 /* Calculate shift and precision */
404 (*shift) = 0;
405 (*prec) = 0;
407 while (!(mask & 0x1)) {
408 (*shift)++;
409 mask >>= 1;
412 while (mask & 0x1) {
413 (*prec)++;
414 mask >>= 1;
418 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)
420 int tmp1, tmp2, size;
421 em8300_register_t reg;
422 extern float monitor_aspect;
424 /* Softzoom turned on, downscale */
425 /* This activates the subpicture processor, you can safely disable this and still send */
426 /* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
427 /* up in a lockup */
428 ioval = EM8300_SPUMODE_ON;
429 if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
430 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetSubpictureMode);
431 uninit();
432 return -1;
435 /* Set the playmode to play (just in case another app has set it to something else) */
436 ioval = EM8300_PLAYMODE_PLAY;
437 if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
438 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetPlaymode);
441 /* Start em8300 prebuffering and sync engine */
442 reg.microcode_register = 1;
443 reg.reg = 0;
444 reg.val = MVCOMMAND_SYNC;
445 ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
447 /* Clean buffer by syncing it */
448 ioval = EM8300_SUBDEVICE_VIDEO;
449 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
450 ioval = EM8300_SUBDEVICE_AUDIO;
451 ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
453 /* Sync the video device to make sure the buffers are empty
454 * and set the playback speed to normal. Also reset the
455 * em8300 internal clock.
457 fsync(fd_video);
458 ioval = 0x900;
459 ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
461 /* Store some variables statically that we need later in another scope */
462 img_format = format;
463 v_width = width;
464 v_height = height;
466 /* Set monitor_aspect to avoid jitter */
467 monitor_aspect = (float) width / (float) height;
469 if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
470 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToGetTVNorm);
471 old_vmode = -1;
474 /* adjust TV norm */
475 if (dxr3_norm != 0) {
476 if (dxr3_norm == 5) {
477 ioval = EM8300_VIDEOMODE_NTSC;
478 } else if (dxr3_norm == 4) {
479 ioval = EM8300_VIDEOMODE_PAL60;
480 } else if (dxr3_norm == 3) {
481 ioval = EM8300_VIDEOMODE_PAL;
482 } else if (dxr3_norm == 2) {
483 if (vo_fps > 28) {
484 ioval = EM8300_VIDEOMODE_PAL60;
485 } else {
486 ioval = EM8300_VIDEOMODE_PAL;
489 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
490 ioval == EM8300_VIDEOMODE_PAL60 ? mp_msg(MSGT_VO,MSGL_INFO, "PAL-60") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
491 printf(".\n");
492 } else {
493 if (vo_fps > 28) {
494 ioval = EM8300_VIDEOMODE_NTSC;
495 } else {
496 ioval = EM8300_VIDEOMODE_PAL;
499 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoSelectedTVNormByFrameRate);
500 ioval == EM8300_VIDEOMODE_NTSC ? mp_msg(MSGT_VO,MSGL_INFO, "NTSC") : mp_msg(MSGT_VO,MSGL_INFO, "PAL");
501 printf(".\n");
504 if (old_vmode != ioval) {
505 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
506 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToSetTVNorm);
512 /* libavcodec requires a width and height that is x|16 */
513 aspect_save_orig(width, height);
514 aspect_save_prescale(d_width, d_height);
515 ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
516 if (ioval == EM8300_VIDEOMODE_NTSC) {
517 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForNTSC);
518 aspect_save_screenres(352, 240);
519 } else {
520 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingUpForPALSECAM);
521 aspect_save_screenres(352, 288);
523 aspect(&s_width, &s_height, A_ZOOM);
524 s_width -= s_width % 16;
525 s_height -= s_height % 16;
527 /* Try to figure out whether to use widescreen output or not */
528 /* Anamorphic widescreen modes makes this a pain in the ass */
529 tmp1 = abs(d_height - ((d_width / 4) * 3));
530 tmp2 = abs(d_height - (int) (d_width / 2.35));
531 if (tmp1 < tmp2) {
532 ioval = EM8300_ASPECTRATIO_4_3;
533 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo43);
534 } else {
535 ioval = EM8300_ASPECTRATIO_16_9;
536 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_SettingAspectRatioTo169);
538 ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
540 #ifdef SPU_SUPPORT
541 #ifdef HAVE_FREETYPE
542 if (ioval == EM8300_ASPECTRATIO_16_9) {
543 s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
544 } else {
545 s_width *= 0.84;
547 //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
548 #else
549 s_width*=2;
550 s_height*=2;
551 #endif
553 osdpicbuf = calloc( 1,s_width * s_height);
554 if (osdpicbuf == NULL) {
555 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
556 return -1;
558 spued = (encodedata *) malloc(sizeof(encodedata));
559 if (spued == NULL) {
560 free( osdpicbuf );
561 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
562 return -1;
564 spubuf = (encodedata *) malloc(sizeof(encodedata));
565 if (spubuf == NULL) {
566 free( osdpicbuf );
567 free( spued );
568 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_OutOfMemory);
569 return -1;
571 osd_w = s_width;
572 osd_h = s_height;
573 osdpicbuf_w = s_width;
574 osdpicbuf_h = s_height;
576 spubuf->count=0;
577 pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
579 #endif
581 #ifdef HAVE_X11
582 if (dxr3_overlay) {
583 XVisualInfo vinfo;
584 XSetWindowAttributes xswa;
585 XSizeHints hint;
586 unsigned long xswamask;
587 Colormap cmap;
588 XColor key_color;
589 Window junkwindow;
590 Screen *scr;
591 int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
592 em8300_overlay_screen_t ovlscr;
593 em8300_attribute_t ovlattr;
595 vo_dx = (vo_screenwidth - d_width) / 2;
596 vo_dy = (vo_screenheight - d_height) / 2;
597 vo_dwidth = d_width;
598 vo_dheight = d_height;
599 #ifdef HAVE_NEW_GUI
600 if (use_gui) {
601 guiGetEvent(guiSetShVideo, 0);
602 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
603 XClearWindow(mDisplay, vo_window);
604 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
605 depth = xwin_attribs.depth;
606 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
607 depth = 24;
609 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
610 } else
611 #endif
613 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
614 depth = xwin_attribs.depth;
615 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
616 depth = 24;
618 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
619 xswa.background_pixel = KEY_COLOR;
620 xswa.border_pixel = 0;
621 xswamask = CWBackPixel | CWBorderPixel;
622 hint.y = vo_dy;
623 hint.x = vo_dx;
624 hint.base_width = hint.width = vo_dwidth;
625 hint.base_height = hint.height = vo_dheight;
626 hint.flags = PPosition | PSize;
627 vo_window = XCreateWindow(mDisplay, mRootWin, hint.x, hint.y, hint.width, hint.height, 0, depth, CopyFromParent, vinfo.visual, xswamask, &xswa);
628 vo_x11_classhint(mDisplay, vo_window, "Viewing Window");
629 vo_hidecursor(mDisplay, vo_window);
630 vo_x11_selectinput_witherr(mDisplay, vo_window, StructureNotifyMask | KeyPressMask | PropertyChangeMask);
631 XSetStandardProperties(mDisplay, vo_window, "DXR3 Overlay", "DXR3 Overlay", None, NULL, 0, &hint);
632 XSetWMNormalHints(mDisplay, vo_window, &hint);
633 XMapWindow(mDisplay, vo_window);
634 XSync(mDisplay, False);
637 /* Start setting up overlay */
638 XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
639 overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
640 overlay_read_state(overlay_data, NULL);
642 /* Allocate keycolor */
643 cmap = vo_x11_create_colormap(&vinfo);
644 calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
645 calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
646 calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
648 key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
649 key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
650 key_color.blue = (KEY_COLOR & 0xff) * 256;
651 key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
652 ((key_color.green >> (16 - green_prec)) << green_shift) +
653 ((key_color.blue >> (16 - blue_prec)) << blue_shift));
654 key_color.flags = DoRed | DoGreen | DoBlue;
655 if (!XAllocColor(mDisplay, cmap, &key_color)) {
656 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToAllocateKeycolor);
657 return -1;
660 acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
661 if (key_color.pixel != KEY_COLOR) {
662 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_UnableToAllocateExactKeycolor, key_color.pixel);
665 /* Set keycolor and activate overlay */
666 XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
667 XClearWindow(mDisplay, vo_window);
668 overlay_set_keycolor(overlay_data, key_color.pixel);
669 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
670 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
673 if (vo_ontop) vo_x11_setlayer(mDisplay, vo_window, vo_ontop);
675 #endif
677 return 0;
680 static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
682 #ifdef SPU_SUPPORT
683 unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
684 int by = 0;
685 register int lx, ly;
686 register int stride = 0;
688 for (ly = 0; ly < h - 1; ly++)
690 for(lx = 0; lx < w; lx++ )
691 if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
692 by+=osdpicbuf_w;
693 stride+=srcstride;
695 pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
696 #endif
699 extern int vo_osd_changed_flag;
700 extern mp_osd_obj_t* vo_osd_list;
702 static void draw_osd(void)
704 #ifdef SPU_SUPPORT
705 static int cleared = 0;
706 int changed = 0;
708 if ((disposd % 15) == 0)
711 mp_osd_obj_t* obj = vo_osd_list;
712 vo_update_osd( osd_w,osd_h );
713 while( obj )
715 if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
716 obj=obj->next;
719 if ( changed )
721 vo_draw_text(osd_w, osd_h, draw_alpha);
722 memset(osdpicbuf, 0, s_width * s_height);
723 cleared=0;
725 else
727 if ( !cleared )
729 spued->count=spubuf->count;
730 memcpy( spued->data,spubuf->data,DATASIZE );
731 cleared=1;
736 /* could stand some check here to see if the subpic hasn't changed
737 * as if it hasn't and we re-send it it will "blink" as the last one
738 * is turned off, and the new one (same one) is turned on
740 /* Subpics are not stable yet =(
741 expect lockups if you enable */
742 #if 1
743 write(fd_spu, spued->data, spued->count);
744 #endif
746 disposd++;
747 #endif
751 static int draw_frame(uint8_t * src[])
753 vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
755 #ifdef SPU_SUPPORT
756 if (p->id == 0x20) {
757 write(fd_spu, p->data, p->size);
758 } else
759 #endif
760 write(fd_video, p->data, p->size);
761 return 0;
764 static void flip_page(void)
766 #ifdef HAVE_X11
767 if (dxr3_overlay) {
768 int event = vo_x11_check_events(mDisplay);
769 if (event & VO_EVENT_RESIZE) {
770 Window junkwindow;
771 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
772 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
773 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
775 if (event & VO_EVENT_EXPOSE) {
776 Window junkwindow;
777 XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
778 XClearWindow(mDisplay, vo_window);
779 XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
780 XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
781 overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
784 #endif
786 if (dxr3_newsync) {
787 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
788 ioval <<= 1;
789 if (vo_pts == 0) {
790 ioval = 0;
791 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
792 pts_offset = 0;
793 } else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
794 ioval = (vo_pts + pts_offset) >> 1;
795 ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
796 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
797 pts_offset = vo_pts - (ioval << 1);
798 if (pts_offset < 0) {
799 pts_offset = 0;
802 ioval = vo_pts + pts_offset;
803 ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
804 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
805 prev_pts = vo_pts;
806 } else if (dxr3_prebuf) {
807 ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
808 ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
812 static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
814 return -1;
817 static void uninit(void)
819 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Uninitializing);
820 #ifdef HAVE_X11
821 if (dxr3_overlay) {
822 overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
823 overlay_release(overlay_data);
825 #ifdef HAVE_NEW_GUI
826 if (!use_gui) {
827 #endif
828 vo_x11_uninit();
830 #ifdef HAVE_NEW_GUI
832 #endif
834 #endif
835 if (old_vmode != -1) {
836 if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
837 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedRestoringTVNorm);
841 if (fd_video) {
842 close(fd_video);
844 if (fd_spu) {
845 close(fd_spu);
847 if (fd_control) {
848 close(fd_control);
850 #ifdef SPU_SUPPORT
851 if(osdpicbuf) {
852 free(osdpicbuf);
854 if(spued) {
855 free(spued);
857 #endif
860 static void check_events(void)
864 static int preinit(const char *arg)
866 char devname[MAX_STR_SIZE];
867 int fdflags = O_WRONLY;
869 /* Parse commandline */
870 while (arg) {
871 if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
872 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_EnablingPrebuffering);
873 dxr3_prebuf = 1;
874 } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
875 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingNewSyncEngine);
876 dxr3_newsync = 1;
877 } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
878 #ifdef HAVE_X11
879 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UsingOverlay);
880 dxr3_overlay = 1;
881 #else
882 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorYouNeedToCompileMplayerWithX11);
883 #endif
884 } else if (!strncmp("norm=", arg, 5)) {
885 arg += 5;
886 // dxr3_norm is 0 (-> don't change norm) by default
887 // but maybe someone changes this in the future
889 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_WillSetTVNormTo);
891 if (*arg == '5') {
892 dxr3_norm = 5;
893 mp_msg(MSGT_VO,MSGL_INFO, "NTSC");
894 } else if (*arg == '4') {
895 dxr3_norm = 4;
896 mp_msg(MSGT_VO,MSGL_INFO, "PAL-60");
897 } else if (*arg == '3') {
898 dxr3_norm = 3;
899 mp_msg(MSGT_VO,MSGL_INFO, "PAL");
900 } else if (*arg == '2') {
901 dxr3_norm = 2;
902 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALPAL60);
903 } else if (*arg == '1') {
904 dxr3_norm = 1;
905 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_AutoAdjustToMovieFrameRatePALNTSC);
906 } else if (*arg == '0') {
907 dxr3_norm = 0;
908 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseCurrentNorm);
909 } else {
910 dxr3_norm = 0;
911 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_UseUnknownNormSuppliedCurrentNorm);
914 mp_msg(MSGT_VO,MSGL_INFO, ".\n");
915 } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
916 dxr3_device_num = arg[0];
919 arg = strchr(arg, ':');
920 if (arg) {
921 arg++;
926 /* Open the control interface */
927 sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
928 fd_control = open(devname, fdflags);
929 if (fd_control < 1) {
930 /* Fall back to old naming scheme */
931 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTrying, devname);
932 sprintf(devname, "/dev/em8300");
933 fd_control = open(devname, fdflags);
934 if (fd_control < 1) {
935 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWell);
936 return -1;
938 } else {
939 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
942 /* Open the video interface */
943 sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
944 fd_video = open(devname, fdflags);
945 if (fd_video < 0) {
946 /* Fall back to old naming scheme */
947 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingMV, devname);
948 sprintf(devname, "/dev/em8300_mv");
949 fd_video = open(devname, fdflags);
950 if (fd_video < 0) {
951 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellMV);
952 uninit();
953 return -1;
955 } else {
956 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
958 strcpy(fdv_name, devname);
960 /* Open the subpicture interface */
961 sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
962 fd_spu = open(devname, fdflags);
963 if (fd_spu < 0) {
964 /* Fall back to old naming scheme */
965 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingTryingSP, devname);
966 sprintf(devname, "/dev/em8300_sp");
967 fd_spu = open(devname, fdflags);
968 if (fd_spu < 0) {
969 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_ErrorOpeningForWritingAsWellSP);
970 uninit();
971 return -1;
973 } else {
974 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_Opened, devname);
976 strcpy(fds_name, devname);
978 #ifdef HAVE_X11
979 if (dxr3_overlay) {
981 /* Fucked up hack needed to enable overlay.
982 * Will be removed as soon as I figure out
983 * how to make it work like it should
985 Display *dpy;
986 overlay_t *ov;
987 XWindowAttributes attribs;
989 dpy = XOpenDisplay(NULL);
990 if (!dpy) {
991 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToOpenDisplayDuringHackSetup);
992 return -1;
994 XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
995 ov = overlay_init(fd_control);
996 overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
997 overlay_read_state(ov, NULL);
998 overlay_set_keycolor(ov, KEY_COLOR);
999 overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
1000 overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
1001 overlay_release(ov);
1002 XCloseDisplay(dpy);
1003 /* End of fucked up hack */
1005 /* Initialize overlay and X11 */
1006 overlay_data = overlay_init(fd_control);
1007 #ifdef HAVE_NEW_GUI
1008 if (!use_gui) {
1009 #endif
1010 if (!vo_init()) {
1011 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_UnableToInitX11);
1012 return -1;
1014 #ifdef HAVE_NEW_GUI
1016 #endif
1018 #endif
1020 if (dxr3_newsync) {
1021 ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
1022 pts_offset = vo_pts - (ioval << 1);
1023 if (pts_offset < 0) {
1024 pts_offset = 0;
1028 return 0;
1031 /* Begin overlay.c */
1032 static int update_parameters(overlay_t *o)
1034 overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
1035 overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
1036 overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
1037 overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
1038 overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
1039 return 0;
1042 static int overlay_set_attribute(overlay_t *o, int attribute, int value)
1044 em8300_attribute_t attr;
1046 attr.attribute = attribute;
1047 attr.value = value;
1048 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
1050 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayAttribute);
1051 return -1;
1054 return 0;
1057 static overlay_t *overlay_init(int dev)
1059 overlay_t *o;
1061 o = (overlay_t *) malloc(sizeof(overlay_t));
1063 if(!o)
1064 return NULL;
1066 memset(o,0,sizeof(overlay_t));
1068 o->dev = dev;
1069 o->xres = 1280; o->yres=1024; o->xcorr=1000;
1070 o->color_interval=10;
1072 return o;
1075 static int overlay_release(overlay_t *o)
1077 if(o)
1078 free(o);
1080 return 0;
1082 #define TYPE_INT 1
1083 #define TYPE_XINT 2
1084 #define TYPE_COEFF 3
1085 #define TYPE_FLOAT 4
1087 struct lut_entry {
1088 char *name;
1089 int type;
1090 void *ptr;
1093 static struct lut_entry *new_lookuptable(overlay_t *o)
1095 struct lut_entry m[] = {
1096 {"xoffset", TYPE_INT, &o->xoffset},
1097 {"yoffset", TYPE_INT, &o->yoffset},
1098 {"xcorr", TYPE_INT, &o->xcorr},
1099 {"jitter", TYPE_INT, &o->jitter},
1100 {"stability", TYPE_INT, &o->stability},
1101 {"keycolor", TYPE_XINT, &o->keycolor},
1102 {"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
1103 {"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
1104 {"color_interval", TYPE_FLOAT, &o->color_interval},
1105 {0,0,0}
1106 },*p;
1108 p = malloc(sizeof(m));
1109 memcpy(p,m,sizeof(m));
1110 return p;
1113 static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
1114 int i;
1116 for(i=0; lut[i].name; i++) {
1117 if(!strcmp(name,lut[i].name)) {
1118 *ptr = lut[i].ptr;
1119 *type = lut[i].type;
1120 return 1;
1123 return 0;
1126 static int overlay_read_state(overlay_t *o, char *p)
1128 char *a,*tok;
1129 char path[128],fname[128],tmp[128],line[256];
1130 FILE *fp;
1131 struct lut_entry *lut;
1132 void *ptr;
1133 int type;
1134 int j;
1136 if(!p) {
1137 strlcpy(fname, getenv("HOME"), sizeof( fname ));
1138 strlcat(fname,"/.overlay", sizeof( fname ));
1139 } else
1140 strlcpy(fname, p, sizeof( fname ));
1142 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1143 strlcat(fname, tmp, sizeof( fname ));
1145 if(!(fp=fopen(fname,"r")))
1146 return -1;
1148 lut = new_lookuptable(o);
1150 while(!feof(fp)) {
1151 if(!fgets(line,256,fp))
1152 break;
1153 tok=strtok(line," ");
1154 if(lookup_parameter(o,lut,tok,&ptr,&type)) {
1155 tok=strtok(NULL," ");
1156 switch(type) {
1157 case TYPE_INT:
1158 sscanf(tok,"%d",(int *)ptr);
1159 break;
1160 case TYPE_XINT:
1161 sscanf(tok,"%x",(int *)ptr);
1162 break;
1163 case TYPE_FLOAT:
1164 sscanf(tok,"%f",(float *)ptr);
1165 break;
1166 case TYPE_COEFF:
1167 for(j=0;j<3;j++) {
1168 sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1169 tok=strtok(NULL," ");
1170 sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1171 tok=strtok(NULL," ");
1173 break;
1179 update_parameters(o);
1181 free(lut);
1182 fclose(fp);
1183 return 0;
1186 static void overlay_update_params(overlay_t *o) {
1187 update_parameters(o);
1190 static int overlay_write_state(overlay_t *o, char *p)
1192 char *a;
1193 char path[128],fname[128],tmp[128];
1194 FILE *fp;
1195 char line[256],*tok;
1196 struct lut_entry *lut;
1197 int i,j;
1199 if(!p) {
1200 strlcpy(fname, getenv("HOME"), sizeof( fname ));
1201 strlcat(fname,"/.overlay", sizeof( fname ));
1202 } else
1203 strlcpy(fname, p, sizeof( fname ));
1205 if(access(fname, W_OK|X_OK|R_OK)) {
1206 if(mkdir(fname,0766))
1207 return -1;
1210 sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1211 strlcat(fname, tmp, sizeof( fname ));
1213 if(!(fp=fopen(fname,"w")))
1214 return -1;
1216 lut = new_lookuptable(o);
1218 for(i=0; lut[i].name; i++) {
1219 fprintf(fp,"%s ",lut[i].name);
1220 switch(lut[i].type) {
1221 case TYPE_INT:
1222 fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1223 break;
1224 case TYPE_XINT:
1225 fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1226 break;
1227 case TYPE_FLOAT:
1228 fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1229 break;
1230 case TYPE_COEFF:
1231 for(j=0;j<3;j++)
1232 fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1233 ((struct coeff *)lut[i].ptr)[j].m);
1234 fprintf(fp,"\n");
1235 break;
1239 fclose(fp);
1240 return 0;
1243 static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1245 em8300_overlay_screen_t scr;
1247 o->xres = xres;
1248 o->yres = yres;
1249 o->depth = depth;
1251 scr.xsize = xres;
1252 scr.ysize = yres;
1254 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1256 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayScreen);
1257 return -1;
1259 return 0;
1262 static int overlay_set_mode(overlay_t *o, int mode)
1264 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1265 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedEnablingOverlay);
1266 return -1;
1268 return 0;
1271 static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1273 em8300_overlay_window_t win;
1274 win.xpos = xpos;
1275 win.ypos = ypos;
1276 win.width = width;
1277 win.height = height;
1279 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1281 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1282 return -1;
1284 return 0;
1287 static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1289 em8300_bcs_t bcs;
1290 bcs.brightness = brightness;
1291 bcs.contrast = contrast;
1292 bcs.saturation = saturation;
1294 if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1296 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSettingOverlayBcs);
1297 return -1;
1299 return 0;
1302 static int col_interp(float x, struct coeff c)
1304 float y;
1305 y = x*c.k + c.m;
1306 if(y > 255)
1307 y = 255;
1308 if(y < 0)
1309 y = 0;
1310 return rint(y);
1313 static int overlay_set_keycolor(overlay_t *o, int color) {
1314 int r = (color & 0xff0000) >> 16;
1315 int g = (color & 0x00ff00) >> 8;
1316 int b = (color & 0x0000ff);
1317 float ru,gu,bu;
1318 float rl,gl,bl;
1319 int upper,lower;
1321 ru = r+o->color_interval;
1322 gu = g+o->color_interval;
1323 bu = b+o->color_interval;
1325 rl = r-o->color_interval;
1326 gl = g-o->color_interval;
1327 bl = b-o->color_interval;
1329 upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1330 (col_interp(gu, o->colcal_upper[1]) << 8) |
1331 (col_interp(bu, o->colcal_upper[2]));
1333 lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1334 (col_interp(gl, o->colcal_lower[1]) << 8) |
1335 (col_interp(bl, o->colcal_lower[2]));
1337 //printf("0x%06x 0x%06x\n",upper,lower);
1338 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1339 overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1340 return 0;
1343 static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1345 float sx=0,sy=0,sxx=0,sxy=0;
1346 float delta,b;
1347 int i;
1349 for(i=0; i < n; i++) {
1350 sx=sx+x[i];
1351 sy=sy+y[i];
1352 sxx=sxx+x[i]*x[i];
1353 sxy=sxy+x[i]*y[i];
1356 delta=sxx*n-sx*sx;
1358 *m=(sxx*sy-sx*sxy)/delta;
1359 *k=(sxy*n-sx*sy)/delta;
1362 static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1364 em8300_overlay_calibrate_t cal;
1365 em8300_overlay_window_t win;
1366 int x[256],r[256],g[256],b[256],n;
1367 float k,m;
1369 int i;
1371 o->draw_pattern=pd;
1372 o->dp_arg = arg;
1374 overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1375 overlay_set_screen(o, o->xres, o->yres, o->depth);
1377 /* Calibrate Y-offset */
1379 o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1381 cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1382 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1384 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayYOffsetValues);
1385 return -1;
1387 o->yoffset = cal.result;
1388 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_YOffset,cal.result);
1390 /* Calibrate X-offset */
1392 o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1394 cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1395 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1397 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXOffsetValues);
1398 return -1;
1400 o->xoffset = cal.result;
1401 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XOffset,cal.result);
1403 /* Calibrate X scale correction */
1405 o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1407 cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1408 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1410 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedGettingOverlayXScaleCorrection);
1411 return -1;
1413 mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_DXR3_XCorrection,cal.result);
1414 o->xcorr = cal.result;
1416 win.xpos = 10;
1417 win.ypos = 10;
1418 win.width = o->xres-20;
1419 win.height = o->yres-20;
1420 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1421 mp_msg(MSGT_VO,MSGL_ERR, MSGTR_LIBVO_DXR3_FailedResizingOverlayWindow);
1422 exit(1);
1425 /* Calibrate key color upper limit */
1427 for(i=128,n=0; i <= 0xff; i+=4) {
1428 o->draw_pattern(i | (i << 8) | (i << 16), 0,
1429 (o->xres-200)/2,0,200,o->yres,o->dp_arg);
1431 cal.arg = i;
1432 cal.arg2 = 1;
1433 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1435 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1437 return -1 ;
1440 x[n] = i;
1441 r[n] = (cal.result>>16)&0xff;
1442 g[n] = (cal.result>>8)&0xff;
1443 b[n] = (cal.result)&0xff;
1444 n++;
1447 least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1448 least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1449 least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1451 /* Calibrate key color lower limit */
1453 for(i=128,n=0; i <= 0xff; i+=4) {
1454 o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1455 (o->xres-200)/2,0,200,o->yres, o->dp_arg);
1457 cal.arg = i;
1458 cal.arg2 = 2;
1459 cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1461 if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1463 return -1 ;
1465 x[n] = i;
1466 r[n] = (cal.result>>16)&0xff;
1467 g[n] = (cal.result>>8)&0xff;
1468 b[n] = (cal.result)&0xff;
1469 n++;
1472 least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1473 least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1474 least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1476 overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1478 return 0;
1482 static int overlay_signalmode(overlay_t *o, int mode) {
1483 if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1484 mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_DXR3_FailedSetSignalMix);
1485 return -1;
1487 return 0;
1489 /* End overlay.c */