2
* vo_dxr3.c - DXR3/H+ video out
4
* Copyright (C) 2002-2003 David Holm <david@realityrift.com>
8
/* ChangeLog added 2002-01-10
10
* Added a patch from Anders Rune Jensen to support the latest em8300 CVS
14
* Yet another patch from Tamas Kohegyi to fix subpic placement.
17
* Added patch from Tamas Kohegyi to fix subpic placement with freetype.
20
* Added patch from Jens Axboe that makes vo_dxr3 return to previous TV norm
22
* Added patch from Thomas Jarosch that fixed alot of textual ouput
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.
30
* Cleaned up syncing code and renamed setup variables so
31
* they can be accessed from the GUI.
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.
39
* Added new sync-engine, activate with :sync option.
40
* Greatly improved commandline parser.
41
* Replaced :noprebuf with :prebuf and made noprebuf the default.
44
* Fixed multicard bug on athlons
47
* Disabled spuenc support, this is still not stable enough =(
50
* Removed lavc and fame encoder to be compatible with new libvo style.
51
* Added graphic equalizer support.
54
* The spuenc code isn't 100% stable yet, therefore I'm disabling
55
* it due to the upcoming stable release.
58
* Carl George added spuenc support
61
* XorA added an option parser and support for selecting encoder
62
* codec. We thank him again.
65
* A couple of bugfixes by XorA
68
* Thanks to Marcel Hild <hild@b4mad.net> the jitter-bug experienced
69
* with some videos have been fixed, many thanks goes to him.
72
* Fixed problems with fame, it gives a better picture than avcodec,
73
* but is slightly slower. Most notably the wobbling effect is gone
77
* Preliminary fame support added (it breaks after seeking, why?)
80
* Fixed sync problems when pausing video (while using prebuffering)
83
* Fixed bug which would case invalid output when using :noprebuf
84
* Removed equalization code, it caused problems on slow systems
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...)
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.
100
* Removal of libmp1e, libavcodec has finally become faster (and it's code is helluva lot cleaner)
103
* Cleaned out some old code which might have slowed down writes
106
* Testrelease of new sync engine (using previously undocumented feature of em8300).
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)
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>
136
#include "fastmemcpy.h"
138
#include "video_out.h"
139
#include "video_out_internal.h"
144
#include "Gui/interface.h"
147
#include "x11_common.h"
152
static vo_info_t info =
156
"David Holm <dholm@iname.com>",
161
/* Resolutions and positions */
162
static int v_width, v_height;
163
static int s_width, s_height;
164
static int osd_w, osd_h;
165
static int img_format;
167
/* Configuration values
168
* Don't declare these static, they
169
* should be accessible from the gui.
172
int dxr3_newsync = 0;
173
int dxr3_overlay = 0;
174
int dxr3_device_num = 0;
177
#define MAX_STR_SIZE 80 /* length for the static strings */
179
/* File descriptors */
180
static int fd_control = -1;
181
static int fd_video = -1;
182
static int fd_spu = -1;
183
static char fdv_name[MAX_STR_SIZE];
184
static char fds_name[MAX_STR_SIZE];
187
/* on screen display/subpics */
188
static char *osdpicbuf;
189
static int osdpicbuf_w;
190
static int osdpicbuf_h;
192
static encodedata *spued;
193
static encodedata *spubuf;
197
/* Static variable used in ioctl's */
200
static int pts_offset;
201
static int old_vmode = -1;
204
/* Begin overlay.h */
206
Simple analog overlay API for DXR3/H+ linux driver.
212
/* Pattern drawing callback used by the calibration functions.
213
The function is expected to:
214
Clear the entire screen.
215
Fill the screen with color bgcol (0xRRGGBB)
216
Draw a rectangle at (xpos,ypos) of size (width,height) in fgcol (0xRRGGBB)
219
typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
220
int xpos, int ypos, int width, int height, void *arg);
229
int xres, yres,depth;
230
int xoffset,yoffset,xcorr;
234
struct coeff colcal_upper[3];
235
struct coeff colcal_lower[3];
236
float color_interval;
238
pattern_drawer_cb draw_pattern;
243
static overlay_t *overlay_init(int dev);
244
static int overlay_release(overlay_t *);
246
static int overlay_read_state(overlay_t *o, char *path);
247
static int overlay_write_state(overlay_t *o, char *path);
249
static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth);
250
static int overlay_set_mode(overlay_t *o, int mode);
251
static int overlay_set_attribute(overlay_t *o, int attribute, int val);
252
static int overlay_set_keycolor(overlay_t *o, int color);
253
static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height);
254
static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation);
256
static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg);
257
static void overlay_update_params(overlay_t *o);
258
static int overlay_signalmode(overlay_t *o, int mode);
263
#define KEY_COLOR 0x80a040
264
static XWindowAttributes xwin_attribs;
265
static overlay_t *overlay_data;
269
/* Functions for working with the em8300's internal clock */
270
/* End of internal clock functions */
272
static int control(uint32_t request, void *data, ...)
275
case VOCTRL_GUISUPPORT:
277
case VOCTRL_GUI_NOWINDOW:
282
case VOCTRL_SET_SPU_PALETTE:
283
if (ioctl(fd_spu, EM8300_IOCTL_SPU_SETPALETTE, data) < 0) {
284
printf("VO: [dxr3] Unable to load new SPU palette!\n");
292
case VOCTRL_FULLSCREEN:
295
overlay_signalmode(overlay_data,
296
vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
297
EM8300_OVERLAY_SIGNAL_WITH_VGA);
304
ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
305
pts_offset = vo_pts - (ioval << 1);
306
if (pts_offset < 0) {
312
ioval = EM8300_PLAYMODE_PLAY;
313
if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
314
printf("VO: [dxr3] Unable to set playmode!\n");
320
ioval = EM8300_PLAYMODE_PAUSED;
321
if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
322
printf("VO: [dxr3] Unable to set playmode!\n");
329
fd_video = open(fdv_name, O_WRONLY);
331
fd_spu = open(fds_name, O_WRONLY);
336
case VOCTRL_QUERY_FORMAT:
340
if (*((uint32_t*)data) != IMGFMT_MPEGPES)
343
flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
348
case VOCTRL_SET_EQUALIZER:
355
value = va_arg(ap, int);
358
if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
360
if (!strcasecmp(data, "brightness"))
361
bcs.brightness = (value+100)*5;
362
else if (!strcasecmp(data, "contrast"))
363
bcs.contrast = (value+100)*5;
364
else if (!strcasecmp(data, "saturation"))
365
bcs.saturation = (value+100)*5;
366
else return VO_FALSE;
368
if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
372
case VOCTRL_GET_EQUALIZER:
379
value = va_arg(ap, int*);
382
if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
385
if (!strcasecmp(data, "brightness"))
386
*value = (bcs.brightness/5)-100;
387
else if (!strcasecmp(data, "contrast"))
388
*value = (bcs.contrast/5)-100;
389
else if (!strcasecmp(data, "saturation"))
390
*value = (bcs.saturation/5)-100;
391
else return VO_FALSE;
399
void calculate_cvals(unsigned long mask, int *shift, int *prec)
401
/* Calculate shift and precision */
405
while (!(mask & 0x1)) {
416
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)
418
int tmp1, tmp2, size;
419
em8300_register_t reg;
420
extern float monitor_aspect;
422
/* Softzoom turned on, downscale */
423
/* This activates the subpicture processor, you can safely disable this and still send */
424
/* broken subpics to the em8300, if it's enabled and you send broken subpics you will end */
426
ioval = EM8300_SPUMODE_ON;
427
if (ioctl(fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval) < 0) {
428
printf("VO: [dxr3] Unable to set subpicture mode!\n");
433
/* Set the playmode to play (just in case another app has set it to something else) */
434
ioval = EM8300_PLAYMODE_PLAY;
435
if (ioctl(fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval) < 0) {
436
printf("VO: [dxr3] Unable to set playmode!\n");
439
/* Start em8300 prebuffering and sync engine */
440
reg.microcode_register = 1;
442
reg.val = MVCOMMAND_SYNC;
443
ioctl(fd_control, EM8300_IOCTL_WRITEREG, ®);
445
/* Clean buffer by syncing it */
446
ioval = EM8300_SUBDEVICE_VIDEO;
447
ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
448
ioval = EM8300_SUBDEVICE_AUDIO;
449
ioctl(fd_control, EM8300_IOCTL_FLUSH, &ioval);
451
/* Sync the video device to make sure the buffers are empty
452
* and set the playback speed to normal. Also reset the
453
* em8300 internal clock.
457
ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
459
/* Store some variables statically that we need later in another scope */
464
/* Set monitor_aspect to avoid jitter */
465
monitor_aspect = (float) width / (float) height;
467
if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
468
printf("VO: [dxr3] Unable to get TV norm!\n");
473
if (dxr3_norm != 0) {
474
if (dxr3_norm == 5) {
475
ioval = EM8300_VIDEOMODE_NTSC;
476
} else if (dxr3_norm == 4) {
477
ioval = EM8300_VIDEOMODE_PAL60;
478
} else if (dxr3_norm == 3) {
479
ioval = EM8300_VIDEOMODE_PAL;
480
} else if (dxr3_norm == 2) {
482
ioval = EM8300_VIDEOMODE_PAL60;
484
ioval = EM8300_VIDEOMODE_PAL;
487
printf("VO: [dxr3] Auto-selected TV norm by frame rate: ");
488
ioval == EM8300_VIDEOMODE_PAL60 ? printf("PAL-60") : printf("PAL");
492
ioval = EM8300_VIDEOMODE_NTSC;
494
ioval = EM8300_VIDEOMODE_PAL;
497
printf("VO: [dxr3] Auto-selected TV norm by frame rate: ");
498
ioval == EM8300_VIDEOMODE_NTSC ? printf("NTSC") : printf("PAL");
502
if (old_vmode != ioval) {
503
if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &ioval) < 0) {
504
printf("VO: [dxr3] Unable to set TV norm!\n");
510
/* libavcodec requires a width and height that is x|16 */
511
aspect_save_orig(width, height);
512
aspect_save_prescale(d_width, d_height);
513
ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &ioval);
514
if (ioval == EM8300_VIDEOMODE_NTSC) {
515
printf("VO: [dxr3] Setting up for NTSC.\n");
516
aspect_save_screenres(352, 240);
518
printf("VO: [dxr3] Setting up for PAL/SECAM.\n");
519
aspect_save_screenres(352, 288);
521
aspect(&s_width, &s_height, A_ZOOM);
522
s_width -= s_width % 16;
523
s_height -= s_height % 16;
525
/* Try to figure out whether to use widescreen output or not */
526
/* Anamorphic widescreen modes makes this a pain in the ass */
527
tmp1 = abs(d_height - ((d_width / 4) * 3));
528
tmp2 = abs(d_height - (int) (d_width / 2.35));
530
ioval = EM8300_ASPECTRATIO_4_3;
531
printf("VO: [dxr3] Setting aspect ratio to 4:3.\n");
533
ioval = EM8300_ASPECTRATIO_16_9;
534
printf("VO: [dxr3] Setting aspect ratio to 16:9.\n");
536
ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
540
if (ioval == EM8300_ASPECTRATIO_16_9) {
541
s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
545
//printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
551
osdpicbuf = calloc( 1,s_width * s_height);
552
if (osdpicbuf == NULL) {
553
printf("VO: [dxr3] Out of memory.\n");
556
spued = (encodedata *) malloc(sizeof(encodedata));
559
printf("VO: [dxr3] Out of memory.\n");
562
spubuf = (encodedata *) malloc(sizeof(encodedata));
563
if (spubuf == NULL) {
566
printf("VO: [dxr3] Out of memory.\n");
571
osdpicbuf_w = s_width;
572
osdpicbuf_h = s_height;
575
pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
582
XSetWindowAttributes xswa;
584
unsigned long xswamask;
589
int depth, red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec, acq_color;
590
em8300_overlay_screen_t ovlscr;
591
em8300_attribute_t ovlattr;
593
vo_dx = (vo_screenwidth - d_width) / 2;
594
vo_dy = (vo_screenheight - d_height) / 2;
596
vo_dheight = d_height;
599
guiGetEvent(guiSetShVideo, 0);
600
XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
601
XClearWindow(mDisplay, vo_window);
602
XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
603
depth = xwin_attribs.depth;
604
if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
607
XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
611
XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
612
depth = xwin_attribs.depth;
613
if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
616
XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
617
xswa.background_pixel = KEY_COLOR;
618
xswa.border_pixel = 0;
619
xswamask = CWBackPixel | CWBorderPixel;
622
hint.base_width = hint.width = vo_dwidth;
623
hint.base_height = hint.height = vo_dheight;
624
hint.flags = PPosition | PSize;
625
vo_window = XCreateWindow(mDisplay, mRootWin, hint.x, hint.y, hint.width, hint.height, 0, depth, CopyFromParent, vinfo.visual, xswamask, &xswa);
626
vo_x11_classhint(mDisplay, vo_window, "Viewing Window");
627
vo_hidecursor(mDisplay, vo_window);
628
vo_x11_selectinput_witherr(mDisplay, vo_window, StructureNotifyMask | KeyPressMask | PropertyChangeMask);
629
XSetStandardProperties(mDisplay, vo_window, "DXR3 Overlay", "DXR3 Overlay", None, NULL, 0, &hint);
630
XSetWMNormalHints(mDisplay, vo_window, &hint);
631
XMapWindow(mDisplay, vo_window);
632
XSync(mDisplay, False);
635
/* Start setting up overlay */
636
XGetWindowAttributes(mDisplay, mRootWin, &xwin_attribs);
637
overlay_set_screen(overlay_data, xwin_attribs.width, xwin_attribs.height, xwin_attribs.depth);
638
overlay_read_state(overlay_data, NULL);
640
/* Allocate keycolor */
641
cmap = vo_x11_create_colormap(&vinfo);
642
calculate_cvals(vinfo.red_mask, &red_shift, &red_prec);
643
calculate_cvals(vinfo.green_mask, &green_shift, &green_prec);
644
calculate_cvals(vinfo.blue_mask, &blue_shift, &blue_prec);
646
key_color.red = ((KEY_COLOR >> 16) & 0xff) * 256;
647
key_color.green = ((KEY_COLOR >> 8) & 0xff) * 256;
648
key_color.blue = (KEY_COLOR & 0xff) * 256;
649
key_color.pixel = (((key_color.red >> (16 - red_prec)) << red_shift) +
650
((key_color.green >> (16 - green_prec)) << green_shift) +
651
((key_color.blue >> (16 - blue_prec)) << blue_shift));
652
key_color.flags = DoRed | DoGreen | DoBlue;
653
if (!XAllocColor(mDisplay, cmap, &key_color)) {
654
printf("VO: [dxr3] Unable to allocate keycolor!\n");
658
acq_color = ((key_color.red / 256) << 16) | ((key_color.green / 256) << 8) | key_color.blue;
659
if (key_color.pixel != KEY_COLOR) {
660
printf("VO: [dxr3] Unable to allocate exact keycolor, using closest match (0x%lx).\n", key_color.pixel);
663
/* Set keycolor and activate overlay */
664
XSetWindowBackground(mDisplay, vo_window, key_color.pixel);
665
XClearWindow(mDisplay, vo_window);
666
overlay_set_keycolor(overlay_data, key_color.pixel);
667
overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OVERLAY);
668
overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_RECTANGLE);
671
if (vo_ontop) vo_x11_setlayer(mDisplay, vo_window, vo_ontop);
678
static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
681
unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
684
register int stride = 0;
686
for (ly = 0; ly < h - 1; ly++)
688
for(lx = 0; lx < w; lx++ )
689
if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
693
pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
697
extern int vo_osd_changed_flag;
698
extern mp_osd_obj_t* vo_osd_list;
700
static void draw_osd(void)
703
static int cleared = 0;
706
if ((disposd % 15) == 0)
709
mp_osd_obj_t* obj = vo_osd_list;
710
vo_update_osd( osd_w,osd_h );
713
if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
719
vo_draw_text(osd_w, osd_h, draw_alpha);
720
memset(osdpicbuf, 0, s_width * s_height);
727
spued->count=spubuf->count;
728
memcpy( spued->data,spubuf->data,DATASIZE );
734
/* could stand some check here to see if the subpic hasn't changed
735
* as if it hasn't and we re-send it it will "blink" as the last one
736
* is turned off, and the new one (same one) is turned on
738
/* Subpics are not stable yet =(
739
expect lockups if you enable */
741
write(fd_spu, spued->data, spued->count);
749
static int draw_frame(uint8_t * src[])
751
vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
755
write(fd_spu, p->data, p->size);
758
write(fd_video, p->data, p->size);
762
static void flip_page(void)
766
int event = vo_x11_check_events(mDisplay);
767
if (event & VO_EVENT_RESIZE) {
769
XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
770
XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
771
overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
773
if (event & VO_EVENT_EXPOSE) {
775
XSetWindowBackground(mDisplay, vo_window, KEY_COLOR);
776
XClearWindow(mDisplay, vo_window);
777
XGetWindowAttributes(mDisplay, vo_window, &xwin_attribs);
778
XTranslateCoordinates(mDisplay, vo_window, mRootWin, -xwin_attribs.border_width, -xwin_attribs.border_width, &xwin_attribs.x, &xwin_attribs.y, &junkwindow);
779
overlay_set_window(overlay_data, xwin_attribs.x, xwin_attribs.y, xwin_attribs.width, xwin_attribs.height);
785
ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
789
ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
791
} else if ((vo_pts - pts_offset) < (ioval - 7200) || (vo_pts - pts_offset) > (ioval + 7200)) {
792
ioval = (vo_pts + pts_offset) >> 1;
793
ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
794
ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
795
pts_offset = vo_pts - (ioval << 1);
796
if (pts_offset < 0) {
800
ioval = vo_pts + pts_offset;
801
ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
802
ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
804
} else if (dxr3_prebuf) {
805
ioctl(fd_spu, EM8300_IOCTL_SPU_SETPTS, &vo_pts);
806
ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts);
810
static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
815
static void uninit(void)
817
printf("VO: [dxr3] Uninitializing.\n");
820
overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
821
overlay_release(overlay_data);
833
if (old_vmode != -1) {
834
if (ioctl(fd_control, EM8300_IOCTL_SET_VIDEOMODE, &old_vmode) < 0) {
835
printf("VO: [dxr3] Failed restoring TV norm!\n");
858
static void check_events(void)
862
static int preinit(const char *arg)
864
char devname[MAX_STR_SIZE];
865
int fdflags = O_WRONLY;
867
/* Parse commandline */
869
if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
870
printf("VO: [dxr3] Enabling prebuffering.\n");
872
} else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
873
printf("VO: [dxr3] Using new sync engine.\n");
875
} else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
877
printf("VO: [dxr3] Using overlay.\n");
880
printf("VO: [dxr3] Error: You need to compile mplayer with x11 libraries and headers installed to use overlay.\n");
882
} else if (!strncmp("norm=", arg, 5)) {
884
// dxr3_norm is 0 (-> don't change norm) by default
885
// but maybe someone changes this in the future
887
printf("VO: [dxr3] Will set TV norm to: ");
892
} else if (*arg == '4') {
895
} else if (*arg == '3') {
898
} else if (*arg == '2') {
900
printf("Auto-adjust to movie frame rate (PAL/PAL-60)");
901
} else if (*arg == '1') {
903
printf("Auto-adjust to movie frame rate (PAL/NTSC)");
904
} else if (*arg == '0') {
906
printf("Use current norm");
909
printf("Unknown norm supplied. Use current norm");
913
} else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
914
dxr3_device_num = arg[0];
917
arg = strchr(arg, ':');
924
/* Open the control interface */
925
sprintf(devname, "/dev/em8300-%d", dxr3_device_num);
926
fd_control = open(devname, fdflags);
927
if (fd_control < 1) {
928
/* Fall back to old naming scheme */
929
printf("VO: [dxr3] Error opening %s for writing, trying /dev/em8300 instead.\n", devname);
930
sprintf(devname, "/dev/em8300");
931
fd_control = open(devname, fdflags);
932
if (fd_control < 1) {
933
printf("VO: [dxr3] Error opening /dev/em8300 for writing as well!\nBailing.\n");
937
printf("VO: [dxr3] Opened %s.\n", devname);
940
/* Open the video interface */
941
sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
942
fd_video = open(devname, fdflags);
944
/* Fall back to old naming scheme */
945
printf("VO: [dxr3] Error opening %s for writing, trying /dev/em8300_mv instead.\n", devname);
946
sprintf(devname, "/dev/em8300_mv");
947
fd_video = open(devname, fdflags);
949
printf("VO: [dxr3] Error opening /dev/em8300_mv for writing as well!\nBailing.\n");
954
printf("VO: [dxr3] Opened %s.\n", devname);
956
strcpy(fdv_name, devname);
958
/* Open the subpicture interface */
959
sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
960
fd_spu = open(devname, fdflags);
962
/* Fall back to old naming scheme */
963
printf("VO: [dxr3] Error opening %s for writing, trying /dev/em8300_sp instead.\n", devname);
964
sprintf(devname, "/dev/em8300_sp");
965
fd_spu = open(devname, fdflags);
967
printf("VO: [dxr3] Error opening /dev/em8300_sp for writing as well!\nBailing.\n");
972
printf("VO: [dxr3] Opened %s.\n", devname);
974
strcpy(fds_name, devname);
979
/* Fucked up hack needed to enable overlay.
980
* Will be removed as soon as I figure out
981
* how to make it work like it should
985
XWindowAttributes attribs;
987
dpy = XOpenDisplay(NULL);
989
printf("VO: [dxr3] Unable to open display during overlay hack setup!\n");
992
XGetWindowAttributes(dpy, RootWindow(dpy, DefaultScreen(dpy)), &attribs);
993
ov = overlay_init(fd_control);
994
overlay_set_screen(ov, attribs.width, attribs.height, PlanesOfScreen(ScreenOfDisplay(dpy, 0)));
995
overlay_read_state(ov, NULL);
996
overlay_set_keycolor(ov, KEY_COLOR);
997
overlay_set_mode(ov, EM8300_OVERLAY_MODE_OVERLAY);
998
overlay_set_mode(ov, EM8300_OVERLAY_MODE_RECTANGLE);
1001
/* End of fucked up hack */
1003
/* Initialize overlay and X11 */
1004
overlay_data = overlay_init(fd_control);
1009
printf("VO: [dxr3] Unable to init x11!\n");
1019
ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
1020
pts_offset = vo_pts - (ioval << 1);
1021
if (pts_offset < 0) {
1029
/* Begin overlay.c */
1030
static int update_parameters(overlay_t *o)
1032
overlay_set_attribute(o, EM9010_ATTRIBUTE_XOFFSET, o->xoffset);
1033
overlay_set_attribute(o, EM9010_ATTRIBUTE_YOFFSET, o->yoffset);
1034
overlay_set_attribute(o, EM9010_ATTRIBUTE_XCORR, o->xcorr);
1035
overlay_set_attribute(o, EM9010_ATTRIBUTE_STABILITY, o->stability);
1036
overlay_set_attribute(o, EM9010_ATTRIBUTE_JITTER, o->jitter);
1040
static int overlay_set_attribute(overlay_t *o, int attribute, int value)
1042
em8300_attribute_t attr;
1044
attr.attribute = attribute;
1046
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
1048
printf("VO: [dxr3] Failed setting overlay attribute.\n");
1055
static overlay_t *overlay_init(int dev)
1059
o = (overlay_t *) malloc(sizeof(overlay_t));
1064
memset(o,0,sizeof(overlay_t));
1067
o->xres = 1280; o->yres=1024; o->xcorr=1000;
1068
o->color_interval=10;
1073
static int overlay_release(overlay_t *o)
1082
#define TYPE_COEFF 3
1083
#define TYPE_FLOAT 4
1091
static struct lut_entry *new_lookuptable(overlay_t *o)
1093
struct lut_entry m[] = {
1094
{"xoffset", TYPE_INT, &o->xoffset},
1095
{"yoffset", TYPE_INT, &o->yoffset},
1096
{"xcorr", TYPE_INT, &o->xcorr},
1097
{"jitter", TYPE_INT, &o->jitter},
1098
{"stability", TYPE_INT, &o->stability},
1099
{"keycolor", TYPE_XINT, &o->keycolor},
1100
{"colcal_upper", TYPE_COEFF, &o->colcal_upper[0]},
1101
{"colcal_lower", TYPE_COEFF, &o->colcal_lower[0]},
1102
{"color_interval", TYPE_FLOAT, &o->color_interval},
1106
p = malloc(sizeof(m));
1107
memcpy(p,m,sizeof(m));
1111
static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
1114
for(i=0; lut[i].name; i++) {
1115
if(!strcmp(name,lut[i].name)) {
1117
*type = lut[i].type;
1124
static int overlay_read_state(overlay_t *o, char *p)
1127
char path[128],fname[128],tmp[128],line[256];
1129
struct lut_entry *lut;
1135
strlcpy(fname, getenv("HOME"), sizeof( fname ));
1136
strlcat(fname,"/.overlay", sizeof( fname ));
1138
strlcpy(fname, p, sizeof( fname ));
1140
sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1141
strlcat(fname, tmp, sizeof( fname ));
1143
if(!(fp=fopen(fname,"r")))
1146
lut = new_lookuptable(o);
1149
if(!fgets(line,256,fp))
1151
tok=strtok(line," ");
1152
if(lookup_parameter(o,lut,tok,&ptr,&type)) {
1153
tok=strtok(NULL," ");
1156
sscanf(tok,"%d",(int *)ptr);
1159
sscanf(tok,"%x",(int *)ptr);
1162
sscanf(tok,"%f",(float *)ptr);
1166
sscanf(tok,"%f",&((struct coeff *)ptr)[j].k);
1167
tok=strtok(NULL," ");
1168
sscanf(tok,"%f",&((struct coeff *)ptr)[j].m);
1169
tok=strtok(NULL," ");
1177
update_parameters(o);
1184
static void overlay_update_params(overlay_t *o) {
1185
update_parameters(o);
1188
static int overlay_write_state(overlay_t *o, char *p)
1191
char path[128],fname[128],tmp[128];
1193
char line[256],*tok;
1194
struct lut_entry *lut;
1198
strlcpy(fname, getenv("HOME"), sizeof( fname ));
1199
strlcat(fname,"/.overlay", sizeof( fname ));
1201
strlcpy(fname, p, sizeof( fname ));
1203
if(access(fname, W_OK|X_OK|R_OK)) {
1204
if(mkdir(fname,0766))
1208
sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
1209
strlcat(fname, tmp, sizeof( fname ));
1211
if(!(fp=fopen(fname,"w")))
1214
lut = new_lookuptable(o);
1216
for(i=0; lut[i].name; i++) {
1217
fprintf(fp,"%s ",lut[i].name);
1218
switch(lut[i].type) {
1220
fprintf(fp,"%d\n",*(int *)lut[i].ptr);
1223
fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
1226
fprintf(fp,"%f\n",*(float *)lut[i].ptr);
1230
fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
1231
((struct coeff *)lut[i].ptr)[j].m);
1241
static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
1243
em8300_overlay_screen_t scr;
1252
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
1254
printf("VO: [dxr3] Failed setting overlay screen!\nExiting.\n");
1260
static int overlay_set_mode(overlay_t *o, int mode)
1262
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
1263
printf("VO: [dxr3] Failed enabling overlay!\nExiting.\n");
1269
static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
1271
em8300_overlay_window_t win;
1275
win.height = height;
1277
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
1279
printf("VO: [dxr3] Failed resizing overlay window!\n");
1285
static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
1288
bcs.brightness = brightness;
1289
bcs.contrast = contrast;
1290
bcs.saturation = saturation;
1292
if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
1294
printf("VO: [dxr3] Failed setting overlay bcs!\n");
1300
static int col_interp(float x, struct coeff c)
1311
static int overlay_set_keycolor(overlay_t *o, int color) {
1312
int r = (color & 0xff0000) >> 16;
1313
int g = (color & 0x00ff00) >> 8;
1314
int b = (color & 0x0000ff);
1319
ru = r+o->color_interval;
1320
gu = g+o->color_interval;
1321
bu = b+o->color_interval;
1323
rl = r-o->color_interval;
1324
gl = g-o->color_interval;
1325
bl = b-o->color_interval;
1327
upper = (col_interp(ru, o->colcal_upper[0]) << 16) |
1328
(col_interp(gu, o->colcal_upper[1]) << 8) |
1329
(col_interp(bu, o->colcal_upper[2]));
1331
lower = (col_interp(rl, o->colcal_lower[0]) << 16) |
1332
(col_interp(gl, o->colcal_lower[1]) << 8) |
1333
(col_interp(bl, o->colcal_lower[2]));
1335
//printf("0x%06x 0x%06x\n",upper,lower);
1336
overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_UPPER,upper);
1337
overlay_set_attribute(o,EM9010_ATTRIBUTE_KEYCOLOR_LOWER,lower);
1341
static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
1343
float sx=0,sy=0,sxx=0,sxy=0;
1347
for(i=0; i < n; i++) {
1356
*m=(sxx*sy-sx*sxy)/delta;
1357
*k=(sxy*n-sx*sy)/delta;
1360
static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
1362
em8300_overlay_calibrate_t cal;
1363
em8300_overlay_window_t win;
1364
int x[256],r[256],g[256],b[256],n;
1372
overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
1373
overlay_set_screen(o, o->xres, o->yres, o->depth);
1375
/* Calibrate Y-offset */
1377
o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
1379
cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
1380
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1382
printf("VO: [dxr3] Failed getting overlay Y-offset values!\nExiting.\n");
1385
o->yoffset = cal.result;
1386
printf("Yoffset: %d\n",cal.result);
1388
/* Calibrate X-offset */
1390
o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
1392
cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
1393
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1395
printf("VO: [dxr3] Failed getting overlay X-offset values!\nExiting.\n");
1398
o->xoffset = cal.result;
1399
printf("Xoffset: %d\n",cal.result);
1401
/* Calibrate X scale correction */
1403
o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
1405
cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
1406
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1408
printf("VO: [dxr3] Failed getting overlay X-scale correction!\nExiting.\n");
1411
printf("Xcorrection: %d\n",cal.result);
1412
o->xcorr = cal.result;
1416
win.width = o->xres-20;
1417
win.height = o->yres-20;
1418
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1) {
1419
printf("VO: [dxr3] Failed resizing overlay window!\n");
1423
/* Calibrate key color upper limit */
1425
for(i=128,n=0; i <= 0xff; i+=4) {
1426
o->draw_pattern(i | (i << 8) | (i << 16), 0,
1427
(o->xres-200)/2,0,200,o->yres,o->dp_arg);
1431
cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1433
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1439
r[n] = (cal.result>>16)&0xff;
1440
g[n] = (cal.result>>8)&0xff;
1441
b[n] = (cal.result)&0xff;
1445
least_sq_fit(x,r,n,&o->colcal_upper[0].k,&o->colcal_upper[0].m);
1446
least_sq_fit(x,g,n,&o->colcal_upper[1].k,&o->colcal_upper[1].m);
1447
least_sq_fit(x,b,n,&o->colcal_upper[2].k,&o->colcal_upper[2].m);
1449
/* Calibrate key color lower limit */
1451
for(i=128,n=0; i <= 0xff; i+=4) {
1452
o->draw_pattern(i | (i << 8) | (i << 16), 0xffffff,
1453
(o->xres-200)/2,0,200,o->yres, o->dp_arg);
1457
cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
1459
if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
1464
r[n] = (cal.result>>16)&0xff;
1465
g[n] = (cal.result>>8)&0xff;
1466
b[n] = (cal.result)&0xff;
1470
least_sq_fit(x,r,n,&o->colcal_lower[0].k,&o->colcal_lower[0].m);
1471
least_sq_fit(x,g,n,&o->colcal_lower[1].k,&o->colcal_lower[1].m);
1472
least_sq_fit(x,b,n,&o->colcal_lower[2].k,&o->colcal_lower[2].m);
1474
overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
1480
static int overlay_signalmode(overlay_t *o, int mode) {
1481
if(ioctl(o->dev, EM8300_IOCTL_OVERLAY_SIGNALMODE, &mode) ==-1) {
1482
printf("VO: [dxr3] Failed set signal mix!\n");