~ubuntu-dev/mplayer/ubuntu-feisty

« back to all changes in this revision

Viewing changes to libvo/vo_dxr3.c

  • Committer: Reinhard Tartler
  • Date: 2006-07-08 08:45:33 UTC
  • Revision ID: siretart@tauware.de-20060708084533-dbc155bde7122e78
imported mplayer_0.99+1.0pre7try2+cvs20060117

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * vo_dxr3.c - DXR3/H+ video out
 
3
 *
 
4
 * Copyright (C) 2002-2003 David Holm <david@realityrift.com>
 
5
 *
 
6
 */
 
7
 
 
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.
 
12
 *
 
13
 * 2003-02-19:
 
14
 *  Yet another patch from Tamas Kohegyi to fix subpic placement.
 
15
 *
 
16
 * 2003-01-12:
 
17
 *  Added patch from Tamas Kohegyi to fix subpic placement with freetype.
 
18
 *
 
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.
 
24
 *
 
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.
 
28
 *
 
29
 * 2002-11-03:
 
30
 *  Cleaned up syncing code and renamed setup variables so
 
31
 *   they can be accessed from the GUI.
 
32
 *
 
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.
 
37
 *
 
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.
 
42
 *
 
43
 * 2002-10-28:
 
44
 *  Fixed multicard bug on athlons
 
45
 *
 
46
 * 2002-07-18:
 
47
 *  Disabled spuenc support, this is still not stable enough =(
 
48
 *
 
49
 * 2002-07-05:
 
50
 *  Removed lavc and fame encoder to be compatible with new libvo style.
 
51
 *  Added graphic equalizer support.
 
52
 *
 
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.
 
56
 *
 
57
 * 2002-04-03:
 
58
 *  Carl George added spuenc support
 
59
 *
 
60
 * 2002-03-26:
 
61
 *  XorA added an option parser and support for selecting encoder
 
62
 *  codec. We thank him again.
 
63
 *
 
64
 * 2002-03-25:
 
65
 *  A couple of bugfixes by XorA
 
66
 *
 
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.
 
70
 *
 
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.
 
75
 *
 
76
 * 2002-03-13:
 
77
 *  Preliminary fame support added (it breaks after seeking, why?)
 
78
 *
 
79
 * 2002-02-18:
 
80
 *  Fixed sync problems when pausing video (while using prebuffering)
 
81
 *
 
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
 
85
 *
 
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...)
 
92
 *
 
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.
 
98
 *
 
99
 * 2002-02-03:
 
100
 *  Removal of libmp1e, libavcodec has finally become faster (and it's code is helluva lot cleaner)
 
101
 *
 
102
 * 2002-02-02:
 
103
 *  Cleaned out some old code which might have slowed down writes
 
104
 *
 
105
 * 2002-01-17:
 
106
 *  Testrelease of new sync engine (using previously undocumented feature of em8300).
 
107
 *
 
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)
 
111
 *
 
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.
 
116
 */
 
117
 
 
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>
 
131
 
 
132
#include "config.h"
 
133
#ifdef HAVE_MALLOC_H
 
134
#include <malloc.h>
 
135
#endif
 
136
#include "fastmemcpy.h"
 
137
 
 
138
#include "video_out.h"
 
139
#include "video_out_internal.h"
 
140
#include "aspect.h"
 
141
#include "spuenc.h"
 
142
#include "sub.h"
 
143
#ifdef HAVE_NEW_GUI
 
144
#include "Gui/interface.h"
 
145
#endif
 
146
#ifdef HAVE_X11
 
147
#include "x11_common.h"
 
148
#endif
 
149
 
 
150
#define SPU_SUPPORT
 
151
 
 
152
static vo_info_t info = 
 
153
{
 
154
        "DXR3/H+ video out",
 
155
        "dxr3",
 
156
        "David Holm <dholm@iname.com>",
 
157
        ""
 
158
};
 
159
LIBVO_EXTERN (dxr3)
 
160
 
 
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;
 
166
 
 
167
/* Configuration values
 
168
 * Don't declare these static, they 
 
169
 * should be accessible from the gui.
 
170
 */
 
171
int dxr3_prebuf = 0;
 
172
int dxr3_newsync = 0;
 
173
int dxr3_overlay = 0;
 
174
int dxr3_device_num = 0;
 
175
int dxr3_norm = 0;
 
176
 
 
177
#define MAX_STR_SIZE 80 /* length for the static strings  */
 
178
 
 
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];
 
185
 
 
186
#ifdef SPU_SUPPORT
 
187
/* on screen display/subpics */
 
188
static char *osdpicbuf;
 
189
static int osdpicbuf_w;
 
190
static int osdpicbuf_h;
 
191
static int disposd;
 
192
static encodedata *spued;
 
193
static encodedata *spubuf;
 
194
#endif
 
195
 
 
196
 
 
197
/* Static variable used in ioctl's */
 
198
static int ioval;
 
199
static int prev_pts;
 
200
static int pts_offset;
 
201
static int old_vmode = -1;
 
202
 
 
203
 
 
204
/* Begin overlay.h */
 
205
/*
 
206
  Simple analog overlay API for DXR3/H+ linux driver.
 
207
 
 
208
  Henrik Johansson
 
209
*/
 
210
 
 
211
 
 
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)
 
217
*/
 
218
 
 
219
typedef int (*pattern_drawer_cb)(int fgcol, int bgcol,
 
220
                             int xpos, int ypos, int width, int height, void *arg);
 
221
 
 
222
struct coeff {
 
223
    float k,m;
 
224
};
 
225
 
 
226
typedef struct {
 
227
    int dev;
 
228
 
 
229
    int xres, yres,depth;
 
230
    int xoffset,yoffset,xcorr;
 
231
    int jitter;
 
232
    int stability;
 
233
    int keycolor;
 
234
    struct coeff colcal_upper[3];
 
235
    struct coeff colcal_lower[3];
 
236
    float color_interval;
 
237
 
 
238
    pattern_drawer_cb draw_pattern;
 
239
    void *dp_arg;
 
240
} overlay_t;
 
241
 
 
242
 
 
243
static overlay_t *overlay_init(int dev);
 
244
static int overlay_release(overlay_t *);
 
245
 
 
246
static int overlay_read_state(overlay_t *o, char *path);
 
247
static int overlay_write_state(overlay_t *o, char *path);
 
248
 
 
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);
 
255
 
 
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);
 
259
/* End overlay.h */
 
260
 
 
261
 
 
262
#ifdef HAVE_X11
 
263
#define KEY_COLOR 0x80a040
 
264
static XWindowAttributes xwin_attribs;
 
265
static overlay_t *overlay_data;
 
266
#endif
 
267
 
 
268
 
 
269
/* Functions for working with the em8300's internal clock */
 
270
/* End of internal clock functions */
 
271
 
 
272
static int control(uint32_t request, void *data, ...)
 
273
{
 
274
        switch (request) {
 
275
        case VOCTRL_GUISUPPORT:
 
276
                return VO_TRUE;
 
277
        case VOCTRL_GUI_NOWINDOW:
 
278
                if (dxr3_overlay) {
 
279
                        return VO_FALSE;
 
280
                }
 
281
                return VO_TRUE;
 
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");
 
285
                        return VO_ERROR;
 
286
                }
 
287
                return VO_TRUE;
 
288
#ifdef HAVE_X11
 
289
        case VOCTRL_ONTOP:
 
290
                vo_x11_ontop();
 
291
                return VO_TRUE;
 
292
        case VOCTRL_FULLSCREEN:
 
293
                if (dxr3_overlay) {
 
294
                        vo_x11_fullscreen();
 
295
                        overlay_signalmode(overlay_data,
 
296
                          vo_fs ? EM8300_OVERLAY_SIGNAL_ONLY :
 
297
                            EM8300_OVERLAY_SIGNAL_WITH_VGA);
 
298
                        return VO_TRUE;
 
299
                }
 
300
                return VO_FALSE;
 
301
#endif
 
302
        case VOCTRL_RESUME:
 
303
                if (dxr3_newsync) {
 
304
                        ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
 
305
                        pts_offset = vo_pts - (ioval << 1);
 
306
                        if (pts_offset < 0) {
 
307
                                pts_offset = 0;
 
308
                        }
 
309
                }
 
310
                
 
311
                if (dxr3_prebuf) {
 
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");
 
315
                        }
 
316
                }
 
317
                return VO_TRUE;
 
318
        case VOCTRL_PAUSE:
 
319
                if (dxr3_prebuf) {
 
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");
 
323
                        }
 
324
                }
 
325
                return VO_TRUE;
 
326
        case VOCTRL_RESET:
 
327
                if (dxr3_prebuf) {
 
328
                        close(fd_video);
 
329
                        fd_video = open(fdv_name, O_WRONLY);
 
330
                        close(fd_spu);
 
331
                        fd_spu = open(fds_name, O_WRONLY);
 
332
                        fsync(fd_video);
 
333
                        fsync(fd_spu);
 
334
                }
 
335
                return VO_TRUE;
 
336
        case VOCTRL_QUERY_FORMAT:
 
337
            {
 
338
                uint32_t flag = 0;
 
339
 
 
340
                if (*((uint32_t*)data) != IMGFMT_MPEGPES)
 
341
                    return 0;
 
342
 
 
343
                flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SPU;
 
344
                if (dxr3_prebuf)
 
345
                    flag |= VFCAP_TIMER;
 
346
                return flag;
 
347
            }
 
348
        case VOCTRL_SET_EQUALIZER:
 
349
            {
 
350
                va_list ap;
 
351
                int value;
 
352
                em8300_bcs_t bcs;
 
353
                
 
354
                va_start(ap, data);
 
355
                value = va_arg(ap, int);
 
356
                va_end(ap);
 
357
 
 
358
                if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
 
359
                    return VO_FALSE;
 
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;
 
367
        
 
368
                if (ioctl(fd_control, EM8300_IOCTL_SETBCS, &bcs) < 0)
 
369
                    return VO_FALSE;
 
370
                return VO_TRUE;
 
371
            }
 
372
        case VOCTRL_GET_EQUALIZER:
 
373
            {
 
374
                va_list ap;
 
375
                int *value;
 
376
                em8300_bcs_t bcs;
 
377
                
 
378
                va_start(ap, data);
 
379
                value = va_arg(ap, int*);
 
380
                va_end(ap);
 
381
 
 
382
                if (ioctl(fd_control, EM8300_IOCTL_GETBCS, &bcs) < 0)
 
383
                    return VO_FALSE;
 
384
                
 
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;
 
392
        
 
393
                return VO_TRUE;
 
394
            }
 
395
        }
 
396
        return VO_NOTIMPL;
 
397
}
 
398
 
 
399
void calculate_cvals(unsigned long mask, int *shift, int *prec)
 
400
{
 
401
        /* Calculate shift and precision */
 
402
        (*shift) = 0;
 
403
        (*prec) = 0;
 
404
        
 
405
        while (!(mask & 0x1)) {
 
406
                (*shift)++;
 
407
                mask >>= 1;
 
408
        }
 
409
        
 
410
        while (mask & 0x1) {
 
411
                (*prec)++;
 
412
                mask >>= 1;
 
413
        }
 
414
}
 
415
 
 
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)
 
417
{
 
418
        int tmp1, tmp2, size;
 
419
        em8300_register_t reg;
 
420
        extern float monitor_aspect;
 
421
 
 
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 */
 
425
        /* up in a lockup */
 
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");
 
429
                uninit();
 
430
                return -1;
 
431
        }
 
432
 
 
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");
 
437
        }
 
438
        
 
439
        /* Start em8300 prebuffering and sync engine */
 
440
        reg.microcode_register = 1;
 
441
        reg.reg = 0;
 
442
        reg.val = MVCOMMAND_SYNC;
 
443
        ioctl(fd_control, EM8300_IOCTL_WRITEREG, &reg);
 
444
 
 
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);
 
450
 
 
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.
 
454
         */
 
455
        fsync(fd_video);
 
456
        ioval = 0x900;
 
457
        ioctl(fd_control, EM8300_IOCTL_SCR_SETSPEED, &ioval);
 
458
 
 
459
        /* Store some variables statically that we need later in another scope */
 
460
        img_format = format;
 
461
        v_width = width;
 
462
        v_height = height;
 
463
 
 
464
        /* Set monitor_aspect to avoid jitter */
 
465
        monitor_aspect = (float) width / (float) height;
 
466
 
 
467
        if (ioctl(fd_control, EM8300_IOCTL_GET_VIDEOMODE, &old_vmode) < 0) {
 
468
                printf("VO: [dxr3] Unable to get TV norm!\n");
 
469
                old_vmode = -1;
 
470
        }
 
471
        
 
472
        /* adjust TV norm */
 
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) {
 
481
                        if (vo_fps > 28) {
 
482
                            ioval = EM8300_VIDEOMODE_PAL60;
 
483
                        } else {
 
484
                            ioval = EM8300_VIDEOMODE_PAL;
 
485
                        }
 
486
                        
 
487
                        printf("VO: [dxr3] Auto-selected TV norm by frame rate: ");
 
488
                        ioval == EM8300_VIDEOMODE_PAL60 ? printf("PAL-60") : printf("PAL");
 
489
                        printf(".\n"); 
 
490
                } else {
 
491
                        if (vo_fps > 28) {
 
492
                            ioval = EM8300_VIDEOMODE_NTSC;
 
493
                        } else {
 
494
                            ioval = EM8300_VIDEOMODE_PAL;
 
495
                        }
 
496
 
 
497
                        printf("VO: [dxr3] Auto-selected TV norm by frame rate: ");
 
498
                        ioval == EM8300_VIDEOMODE_NTSC ? printf("NTSC") : printf("PAL");
 
499
                        printf(".\n"); 
 
500
            }
 
501
        
 
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");
 
505
                }
 
506
                }
 
507
        }
 
508
        
 
509
        
 
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);
 
517
        } else {
 
518
                printf("VO: [dxr3] Setting up for PAL/SECAM.\n");
 
519
                aspect_save_screenres(352, 288);
 
520
        }
 
521
        aspect(&s_width, &s_height, A_ZOOM);
 
522
        s_width -= s_width % 16;
 
523
        s_height -= s_height % 16;
 
524
        
 
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));
 
529
        if (tmp1 < tmp2) {
 
530
                ioval = EM8300_ASPECTRATIO_4_3;
 
531
                printf("VO: [dxr3] Setting aspect ratio to 4:3.\n");
 
532
        } else {
 
533
                ioval = EM8300_ASPECTRATIO_16_9;
 
534
                printf("VO: [dxr3] Setting aspect ratio to 16:9.\n");
 
535
        }
 
536
        ioctl(fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &ioval);
 
537
 
 
538
#ifdef SPU_SUPPORT
 
539
#ifdef HAVE_FREETYPE
 
540
        if (ioval == EM8300_ASPECTRATIO_16_9) {
 
541
                s_width *= d_height*1.78/s_height*(d_width*1.0/d_height)/2.35;
 
542
        } else {
 
543
                s_width *= 0.84;
 
544
        }
 
545
        //printf("VO: [dxr3] sw/sh:dw/dh ->%i,%i,%i,%i\n",s_width,s_height,d_width,d_height);
 
546
#else
 
547
        s_width*=2;
 
548
        s_height*=2;
 
549
#endif
 
550
 
 
551
        osdpicbuf = calloc( 1,s_width * s_height);
 
552
        if (osdpicbuf == NULL) {
 
553
                printf("VO: [dxr3] Out of memory.\n");
 
554
                return -1;
 
555
        }
 
556
        spued = (encodedata *) malloc(sizeof(encodedata));
 
557
        if (spued == NULL) {
 
558
                free( osdpicbuf );
 
559
                printf("VO: [dxr3] Out of memory.\n");
 
560
                return -1;
 
561
        }
 
562
        spubuf = (encodedata *) malloc(sizeof(encodedata));
 
563
        if (spubuf == NULL) {
 
564
                free( osdpicbuf );
 
565
                free( spued );
 
566
                printf("VO: [dxr3] Out of memory.\n");
 
567
                return -1;
 
568
        }
 
569
        osd_w = s_width;
 
570
        osd_h = s_height;
 
571
        osdpicbuf_w = s_width;
 
572
        osdpicbuf_h = s_height;
 
573
        
 
574
        spubuf->count=0;
 
575
        pixbuf_encode_rle( 0,0,osdpicbuf_w,osdpicbuf_h - 1,osdpicbuf,osdpicbuf_w,spubuf );
 
576
 
 
577
#endif
 
578
 
 
579
#ifdef HAVE_X11
 
580
        if (dxr3_overlay) {
 
581
                XVisualInfo vinfo;
 
582
                XSetWindowAttributes xswa;
 
583
                XSizeHints hint;
 
584
                unsigned long xswamask;
 
585
                Colormap cmap;
 
586
                XColor key_color;
 
587
                Window junkwindow;
 
588
                Screen *scr;
 
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;
 
592
 
 
593
                vo_dx = (vo_screenwidth - d_width) / 2;
 
594
                vo_dy = (vo_screenheight - d_height) / 2;
 
595
                vo_dwidth = d_width;
 
596
                vo_dheight = d_height;
 
597
#ifdef HAVE_NEW_GUI
 
598
                if (use_gui) {
 
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) {
 
605
                                depth = 24;
 
606
                        }
 
607
                        XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
 
608
                } else
 
609
#endif
 
610
                {
 
611
                        XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &xwin_attribs);
 
612
                        depth = xwin_attribs.depth;
 
613
                        if (depth != 15 && depth != 16 && depth != 24 && depth != 32) {
 
614
                                depth = 24;
 
615
                        }
 
616
                        XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
 
617
                        xswa.background_pixel = KEY_COLOR;
 
618
                        xswa.border_pixel = 0;
 
619
                        xswamask = CWBackPixel | CWBorderPixel;
 
620
                        hint.y = vo_dy;
 
621
                        hint.x = vo_dx;
 
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);
 
633
                }
 
634
                
 
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);
 
639
 
 
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);
 
645
                
 
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");
 
655
                        return -1;
 
656
                }
 
657
                
 
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);        
 
661
                }
 
662
                
 
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);
 
669
        }
 
670
 
 
671
        if (vo_ontop) vo_x11_setlayer(mDisplay, vo_window, vo_ontop);
 
672
 
 
673
#endif
 
674
 
 
675
        return 0;
 
676
}
 
677
 
 
678
static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
 
679
{
 
680
#ifdef SPU_SUPPORT
 
681
        unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
 
682
        int by = 0;
 
683
        register int lx, ly;
 
684
        register int stride = 0;
 
685
        
 
686
        for (ly = 0; ly < h - 1; ly++) 
 
687
         {
 
688
          for(lx = 0; lx < w; lx++ )
 
689
           if ( ( srca[stride + lx] )&&( src[stride + lx] >= 128 ) ) buf[by + lx] = 3;
 
690
          by+=osdpicbuf_w;
 
691
          stride+=srcstride;
 
692
        }
 
693
        pixbuf_encode_rle(x, y, osdpicbuf_w, osdpicbuf_h - 1, osdpicbuf, osdpicbuf_w, spued);
 
694
#endif
 
695
}
 
696
 
 
697
extern int vo_osd_changed_flag;
 
698
extern mp_osd_obj_t* vo_osd_list;
 
699
 
 
700
static void draw_osd(void)
 
701
{
 
702
#ifdef SPU_SUPPORT
 
703
 static int cleared = 0;
 
704
        int changed = 0;
 
705
 
 
706
        if ((disposd % 15) == 0) 
 
707
        {
 
708
                {
 
709
                 mp_osd_obj_t* obj = vo_osd_list;
 
710
                 vo_update_osd( osd_w,osd_h );
 
711
                 while( obj )
 
712
                  {
 
713
                   if ( obj->flags & OSDFLAG_VISIBLE ) { changed=1; break; }
 
714
                   obj=obj->next;
 
715
                  }
 
716
                }
 
717
                if ( changed )
 
718
                 {
 
719
                  vo_draw_text(osd_w, osd_h, draw_alpha);
 
720
                  memset(osdpicbuf, 0, s_width * s_height);
 
721
                  cleared=0;
 
722
                 }
 
723
                  else
 
724
                   {
 
725
                    if ( !cleared )
 
726
                     {
 
727
                      spued->count=spubuf->count;
 
728
                      memcpy( spued->data,spubuf->data,DATASIZE );
 
729
                      cleared=1;
 
730
                     }
 
731
                   }
 
732
 
 
733
 
 
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
 
737
                 */
 
738
/*              Subpics are not stable yet =(
 
739
                expect lockups if you enable */
 
740
#if 1
 
741
                write(fd_spu, spued->data, spued->count);
 
742
#endif
 
743
        }
 
744
        disposd++;
 
745
#endif
 
746
}
 
747
 
 
748
 
 
749
static int draw_frame(uint8_t * src[])
 
750
{
 
751
        vo_mpegpes_t *p = (vo_mpegpes_t *) src[0];
 
752
 
 
753
#ifdef SPU_SUPPORT
 
754
        if (p->id == 0x20) {
 
755
                write(fd_spu, p->data, p->size);
 
756
        } else
 
757
#endif
 
758
                write(fd_video, p->data, p->size);
 
759
        return 0;
 
760
}
 
761
 
 
762
static void flip_page(void)
 
763
{
 
764
#ifdef HAVE_X11
 
765
        if (dxr3_overlay) {
 
766
                int event = vo_x11_check_events(mDisplay);
 
767
                if (event & VO_EVENT_RESIZE) {
 
768
                        Window junkwindow;
 
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);
 
772
                }
 
773
                if (event & VO_EVENT_EXPOSE) {
 
774
                        Window junkwindow;
 
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);
 
780
                }
 
781
        }
 
782
#endif
 
783
 
 
784
        if (dxr3_newsync) {
 
785
                ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
 
786
                ioval <<= 1;
 
787
                if (vo_pts == 0) {
 
788
                        ioval = 0;
 
789
                        ioctl(fd_control, EM8300_IOCTL_SCR_SET, &ioval);
 
790
                        pts_offset = 0;
 
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) {
 
797
                                pts_offset = 0;
 
798
                        }
 
799
                }
 
800
                ioval = vo_pts + pts_offset;
 
801
                ioctl(fd_video, EM8300_IOCTL_SPU_SETPTS, &ioval);
 
802
                ioctl(fd_video, EM8300_IOCTL_VIDEO_SETPTS, &ioval);
 
803
                prev_pts = vo_pts;
 
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);
 
807
        }
 
808
}
 
809
 
 
810
static int draw_slice(uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0)
 
811
{
 
812
        return -1;
 
813
}
 
814
 
 
815
static void uninit(void)
 
816
{
 
817
        printf("VO: [dxr3] Uninitializing.\n");
 
818
#ifdef HAVE_X11
 
819
        if (dxr3_overlay) {
 
820
                overlay_set_mode(overlay_data, EM8300_OVERLAY_MODE_OFF);
 
821
                overlay_release(overlay_data);
 
822
                
 
823
#ifdef HAVE_NEW_GUI
 
824
                if (!use_gui) {
 
825
#endif
 
826
                        vo_x11_uninit();
 
827
 
 
828
#ifdef HAVE_NEW_GUI
 
829
                }
 
830
#endif
 
831
        }
 
832
#endif
 
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");
 
836
                }
 
837
        }
 
838
        
 
839
        if (fd_video) {
 
840
                close(fd_video);
 
841
        }
 
842
        if (fd_spu) {
 
843
                close(fd_spu);
 
844
        }
 
845
        if (fd_control) {
 
846
                close(fd_control);
 
847
        }
 
848
#ifdef SPU_SUPPORT
 
849
        if(osdpicbuf) {
 
850
                free(osdpicbuf);
 
851
        }
 
852
        if(spued) {
 
853
                free(spued);
 
854
        }
 
855
#endif
 
856
}
 
857
 
 
858
static void check_events(void)
 
859
{
 
860
}
 
861
 
 
862
static int preinit(const char *arg)
 
863
{
 
864
        char devname[MAX_STR_SIZE];
 
865
        int fdflags = O_WRONLY;
 
866
 
 
867
        /* Parse commandline */
 
868
        while (arg) {
 
869
                if (!strncmp("prebuf", arg, 6) && !dxr3_prebuf) {
 
870
                        printf("VO: [dxr3] Enabling prebuffering.\n");
 
871
                        dxr3_prebuf = 1;
 
872
                } else if (!strncmp("sync", arg, 4) && !dxr3_newsync) {
 
873
                        printf("VO: [dxr3] Using new sync engine.\n");
 
874
                        dxr3_newsync = 1;
 
875
                } else if (!strncmp("overlay", arg, 7) && !dxr3_overlay) {
 
876
#ifdef HAVE_X11
 
877
                        printf("VO: [dxr3] Using overlay.\n");
 
878
                        dxr3_overlay = 1;
 
879
#else
 
880
                        printf("VO: [dxr3] Error: You need to compile mplayer with x11 libraries and headers installed to use overlay.\n");
 
881
#endif
 
882
                } else if (!strncmp("norm=", arg, 5)) {
 
883
                        arg += 5;
 
884
                        // dxr3_norm is 0 (-> don't change norm) by default
 
885
                        // but maybe someone changes this in the future
 
886
 
 
887
                        printf("VO: [dxr3] Will set TV norm to: ");
 
888
                        
 
889
                        if (*arg == '5') {
 
890
                            dxr3_norm = 5;
 
891
                            printf("NTSC");
 
892
                        } else if (*arg == '4') {
 
893
                            dxr3_norm = 4;
 
894
                            printf("PAL-60");
 
895
                        } else if (*arg == '3') {
 
896
                            dxr3_norm = 3;
 
897
                            printf("PAL");
 
898
                        } else if (*arg == '2') {
 
899
                            dxr3_norm = 2;
 
900
                            printf("Auto-adjust to movie frame rate (PAL/PAL-60)");
 
901
                        } else if (*arg == '1') {
 
902
                            dxr3_norm = 1;
 
903
                            printf("Auto-adjust to movie frame rate (PAL/NTSC)");
 
904
                        } else if (*arg == '0') {
 
905
                            dxr3_norm = 0;
 
906
                            printf("Use current norm");
 
907
                        } else {
 
908
                            dxr3_norm = 0;
 
909
                            printf("Unknown norm supplied. Use current norm");
 
910
                        }
 
911
                        
 
912
                        printf(".\n");
 
913
                } else if (arg[0] == '0' || arg[0] == '1' || arg[0] == '2' || arg[0] == '3') {
 
914
                        dxr3_device_num = arg[0];
 
915
                }
 
916
                
 
917
                arg = strchr(arg, ':');
 
918
                if (arg) {
 
919
                        arg++;
 
920
                }
 
921
        }
 
922
        
 
923
 
 
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");
 
934
                        return -1;
 
935
                }
 
936
        } else {
 
937
                printf("VO: [dxr3] Opened %s.\n", devname);
 
938
        }
 
939
 
 
940
        /* Open the video interface */
 
941
        sprintf(devname, "/dev/em8300_mv-%d", dxr3_device_num);
 
942
        fd_video = open(devname, fdflags);
 
943
        if (fd_video < 0) {
 
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);
 
948
                if (fd_video < 0) {
 
949
                        printf("VO: [dxr3] Error opening /dev/em8300_mv for writing as well!\nBailing.\n");
 
950
                        uninit();
 
951
                        return -1;
 
952
                }
 
953
        } else {
 
954
                printf("VO: [dxr3] Opened %s.\n", devname);
 
955
        }
 
956
        strcpy(fdv_name, devname);
 
957
        
 
958
        /* Open the subpicture interface */
 
959
        sprintf(devname, "/dev/em8300_sp-%d", dxr3_device_num);
 
960
        fd_spu = open(devname, fdflags);
 
961
        if (fd_spu < 0) {
 
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);
 
966
                if (fd_spu < 0) {
 
967
                        printf("VO: [dxr3] Error opening /dev/em8300_sp for writing as well!\nBailing.\n");
 
968
                        uninit();
 
969
                        return -1;
 
970
                }
 
971
        } else {
 
972
                printf("VO: [dxr3] Opened %s.\n", devname);
 
973
        }
 
974
        strcpy(fds_name, devname);
 
975
        
 
976
#ifdef HAVE_X11
 
977
        if (dxr3_overlay) {
 
978
        
 
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
 
982
                 */
 
983
                Display *dpy;
 
984
                overlay_t *ov;
 
985
                XWindowAttributes attribs;
 
986
                
 
987
                dpy = XOpenDisplay(NULL);
 
988
                if (!dpy) {
 
989
                        printf("VO: [dxr3] Unable to open display during overlay hack setup!\n");
 
990
                        return -1;
 
991
                }
 
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);
 
999
                overlay_release(ov);
 
1000
                XCloseDisplay(dpy);
 
1001
                /* End of fucked up hack */
 
1002
                
 
1003
                /* Initialize overlay and X11 */
 
1004
                overlay_data = overlay_init(fd_control);
 
1005
#ifdef HAVE_NEW_GUI
 
1006
                if (!use_gui) {
 
1007
#endif
 
1008
                        if (!vo_init()) {
 
1009
                                printf("VO: [dxr3] Unable to init x11!\n");
 
1010
                                return -1;
 
1011
                        }
 
1012
#ifdef HAVE_NEW_GUI
 
1013
                }
 
1014
#endif
 
1015
        }
 
1016
#endif
 
1017
 
 
1018
        if (dxr3_newsync) {
 
1019
                ioctl(fd_control, EM8300_IOCTL_SCR_GET, &ioval);
 
1020
                pts_offset = vo_pts - (ioval << 1);
 
1021
                if (pts_offset < 0) {
 
1022
                        pts_offset = 0;
 
1023
                }
 
1024
        }
 
1025
 
 
1026
        return 0;
 
1027
}
 
1028
 
 
1029
/* Begin overlay.c */
 
1030
static int update_parameters(overlay_t *o)
 
1031
{
 
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);
 
1037
    return 0;
 
1038
}
 
1039
 
 
1040
static int overlay_set_attribute(overlay_t *o, int attribute, int value)
 
1041
{
 
1042
    em8300_attribute_t attr;
 
1043
    
 
1044
    attr.attribute = attribute;
 
1045
    attr.value = value;
 
1046
    if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)==-1)
 
1047
        {
 
1048
             printf("VO: [dxr3] Failed setting overlay attribute.\n");
 
1049
             return -1;
 
1050
        }
 
1051
 
 
1052
    return 0;
 
1053
}
 
1054
 
 
1055
static overlay_t *overlay_init(int dev)
 
1056
{
 
1057
    overlay_t *o;
 
1058
 
 
1059
    o = (overlay_t *) malloc(sizeof(overlay_t));
 
1060
 
 
1061
    if(!o)
 
1062
        return NULL;
 
1063
 
 
1064
    memset(o,0,sizeof(overlay_t));
 
1065
 
 
1066
    o->dev = dev;
 
1067
    o->xres = 1280; o->yres=1024; o->xcorr=1000;
 
1068
    o->color_interval=10;
 
1069
 
 
1070
    return o;
 
1071
}
 
1072
 
 
1073
static int overlay_release(overlay_t *o)
 
1074
{
 
1075
    if(o)
 
1076
        free(o);
 
1077
 
 
1078
    return 0;
 
1079
}
 
1080
#define TYPE_INT 1
 
1081
#define TYPE_XINT 2
 
1082
#define TYPE_COEFF 3
 
1083
#define TYPE_FLOAT 4
 
1084
 
 
1085
struct lut_entry {
 
1086
    char *name;
 
1087
    int type;
 
1088
    void *ptr;
 
1089
};
 
1090
 
 
1091
static struct lut_entry *new_lookuptable(overlay_t *o)
 
1092
{
 
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},
 
1103
        {0,0,0}
 
1104
    },*p;
 
1105
 
 
1106
    p = malloc(sizeof(m));
 
1107
    memcpy(p,m,sizeof(m));
 
1108
    return p;
 
1109
}
 
1110
 
 
1111
static int lookup_parameter(overlay_t *o, struct lut_entry *lut, char *name, void **ptr, int *type) {
 
1112
    int i;
 
1113
 
 
1114
    for(i=0; lut[i].name; i++) {
 
1115
        if(!strcmp(name,lut[i].name)) {
 
1116
            *ptr = lut[i].ptr;
 
1117
            *type = lut[i].type;
 
1118
            return 1;
 
1119
        }
 
1120
    }
 
1121
    return 0;
 
1122
}
 
1123
 
 
1124
static int overlay_read_state(overlay_t *o, char *p)
 
1125
{
 
1126
    char *a,*tok;
 
1127
    char path[128],fname[128],tmp[128],line[256];
 
1128
    FILE *fp;
 
1129
    struct lut_entry *lut;
 
1130
    void *ptr;
 
1131
    int type;
 
1132
    int j;
 
1133
        
 
1134
    if(!p) {
 
1135
        strlcpy(fname, getenv("HOME"), sizeof( fname ));
 
1136
        strlcat(fname,"/.overlay", sizeof( fname ));        
 
1137
    } else
 
1138
        strlcpy(fname, p, sizeof( fname ));
 
1139
    
 
1140
    sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
 
1141
    strlcat(fname, tmp, sizeof( fname ));
 
1142
 
 
1143
    if(!(fp=fopen(fname,"r")))
 
1144
        return -1;
 
1145
 
 
1146
    lut = new_lookuptable(o);
 
1147
    
 
1148
    while(!feof(fp)) {
 
1149
        if(!fgets(line,256,fp))
 
1150
            break;
 
1151
        tok=strtok(line," ");
 
1152
        if(lookup_parameter(o,lut,tok,&ptr,&type)) {
 
1153
            tok=strtok(NULL," ");
 
1154
            switch(type) {
 
1155
            case TYPE_INT:
 
1156
                sscanf(tok,"%d",(int *)ptr);
 
1157
                break;
 
1158
            case TYPE_XINT:
 
1159
                sscanf(tok,"%x",(int *)ptr);
 
1160
                break;
 
1161
            case TYPE_FLOAT:
 
1162
                sscanf(tok,"%f",(float *)ptr);
 
1163
                break;
 
1164
            case TYPE_COEFF:
 
1165
                for(j=0;j<3;j++) {
 
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," ");
 
1170
                }
 
1171
                break;      
 
1172
            }
 
1173
            
 
1174
        }       
 
1175
    }
 
1176
 
 
1177
    update_parameters(o);
 
1178
    
 
1179
    free(lut);
 
1180
    fclose(fp);
 
1181
    return 0;
 
1182
}
 
1183
 
 
1184
static void overlay_update_params(overlay_t *o) {
 
1185
    update_parameters(o);
 
1186
}
 
1187
 
 
1188
static int overlay_write_state(overlay_t *o, char *p)   
 
1189
{
 
1190
    char *a;
 
1191
    char path[128],fname[128],tmp[128];
 
1192
    FILE *fp;
 
1193
    char line[256],*tok;
 
1194
    struct lut_entry *lut;
 
1195
    int i,j;
 
1196
        
 
1197
    if(!p) {
 
1198
        strlcpy(fname, getenv("HOME"), sizeof( fname ));
 
1199
        strlcat(fname,"/.overlay", sizeof( fname ));        
 
1200
    } else
 
1201
        strlcpy(fname, p, sizeof( fname ));
 
1202
 
 
1203
    if(access(fname, W_OK|X_OK|R_OK)) {
 
1204
        if(mkdir(fname,0766))
 
1205
            return -1;
 
1206
    }   
 
1207
    
 
1208
    sprintf(tmp,"/res_%dx%dx%d",o->xres,o->yres,o->depth);
 
1209
    strlcat(fname, tmp, sizeof( fname ));
 
1210
    
 
1211
    if(!(fp=fopen(fname,"w")))
 
1212
        return -1;
 
1213
    
 
1214
    lut = new_lookuptable(o);
 
1215
 
 
1216
    for(i=0; lut[i].name; i++) {        
 
1217
        fprintf(fp,"%s ",lut[i].name);
 
1218
        switch(lut[i].type) {
 
1219
        case TYPE_INT:
 
1220
            fprintf(fp,"%d\n",*(int *)lut[i].ptr);
 
1221
            break;
 
1222
        case TYPE_XINT:
 
1223
            fprintf(fp,"%06x\n",*(int *)lut[i].ptr);
 
1224
            break;
 
1225
        case TYPE_FLOAT:
 
1226
            fprintf(fp,"%f\n",*(float *)lut[i].ptr);
 
1227
            break;
 
1228
        case TYPE_COEFF:
 
1229
            for(j=0;j<3;j++) 
 
1230
                fprintf(fp,"%f %f ",((struct coeff *)lut[i].ptr)[j].k,
 
1231
                        ((struct coeff *)lut[i].ptr)[j].m);
 
1232
            fprintf(fp,"\n");
 
1233
            break;          
 
1234
        }
 
1235
    }
 
1236
 
 
1237
    fclose(fp);
 
1238
    return 0;
 
1239
}
 
1240
 
 
1241
static int overlay_set_screen(overlay_t *o, int xres, int yres, int depth)
 
1242
{
 
1243
   em8300_overlay_screen_t scr;
 
1244
 
 
1245
   o->xres = xres;
 
1246
   o->yres = yres;
 
1247
   o->depth = depth;
 
1248
 
 
1249
   scr.xsize = xres;
 
1250
   scr.ysize = yres;
 
1251
   
 
1252
   if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)==-1)
 
1253
        {
 
1254
            printf("VO: [dxr3] Failed setting overlay screen!\nExiting.\n");
 
1255
            return -1;
 
1256
        }
 
1257
   return 0;
 
1258
}
 
1259
 
 
1260
static int overlay_set_mode(overlay_t *o, int mode)
 
1261
{
 
1262
    if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETMODE, &mode)==-1) {
 
1263
        printf("VO: [dxr3] Failed enabling overlay!\nExiting.\n");
 
1264
        return -1;
 
1265
    }
 
1266
    return 0;
 
1267
}
 
1268
 
 
1269
static int overlay_set_window(overlay_t *o, int xpos,int ypos,int width,int height)
 
1270
{
 
1271
    em8300_overlay_window_t win;
 
1272
    win.xpos = xpos;
 
1273
    win.ypos = ypos;
 
1274
    win.width = width;
 
1275
    win.height = height;
 
1276
 
 
1277
    if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_SETWINDOW, &win)==-1)
 
1278
        {
 
1279
            printf("VO: [dxr3] Failed resizing overlay window!\n");
 
1280
            return -1;
 
1281
        }
 
1282
    return 0;
 
1283
}
 
1284
 
 
1285
static int overlay_set_bcs(overlay_t *o, int brightness, int contrast, int saturation)
 
1286
{
 
1287
    em8300_bcs_t bcs;
 
1288
    bcs.brightness = brightness;
 
1289
    bcs.contrast = contrast;
 
1290
    bcs.saturation = saturation;
 
1291
 
 
1292
    if (ioctl(o->dev, EM8300_IOCTL_GETBCS, &bcs)==-1)
 
1293
        {
 
1294
            printf("VO: [dxr3] Failed setting overlay bcs!\n");
 
1295
            return -1;
 
1296
        }
 
1297
    return 0;
 
1298
}
 
1299
 
 
1300
static int col_interp(float x, struct coeff c)
 
1301
{
 
1302
    float y;
 
1303
    y = x*c.k + c.m;
 
1304
    if(y > 255)
 
1305
        y = 255;
 
1306
    if(y < 0)
 
1307
        y = 0;
 
1308
    return rint(y);
 
1309
}
 
1310
 
 
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);
 
1315
    float ru,gu,bu;
 
1316
    float rl,gl,bl;
 
1317
    int upper,lower;
 
1318
 
 
1319
    ru = r+o->color_interval;
 
1320
    gu = g+o->color_interval;
 
1321
    bu = b+o->color_interval;
 
1322
 
 
1323
    rl = r-o->color_interval;
 
1324
    gl = g-o->color_interval;
 
1325
    bl = b-o->color_interval;
 
1326
    
 
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]));
 
1330
 
 
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]));
 
1334
 
 
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);
 
1338
    return 0;
 
1339
}
 
1340
 
 
1341
static void least_sq_fit(int *x, int *y, int n, float *k, float *m)
 
1342
{
 
1343
    float sx=0,sy=0,sxx=0,sxy=0;
 
1344
    float delta,b;
 
1345
    int i;
 
1346
 
 
1347
    for(i=0; i < n; i++) {
 
1348
        sx=sx+x[i];
 
1349
        sy=sy+y[i];
 
1350
        sxx=sxx+x[i]*x[i];
 
1351
        sxy=sxy+x[i]*y[i];
 
1352
    }
 
1353
 
 
1354
    delta=sxx*n-sx*sx;
 
1355
 
 
1356
    *m=(sxx*sy-sx*sxy)/delta;
 
1357
    *k=(sxy*n-sx*sy)/delta;
 
1358
}
 
1359
 
 
1360
static int overlay_autocalibrate(overlay_t *o, pattern_drawer_cb pd, void *arg)
 
1361
{
 
1362
    em8300_overlay_calibrate_t cal;
 
1363
    em8300_overlay_window_t win;
 
1364
    int x[256],r[256],g[256],b[256],n;
 
1365
    float k,m;
 
1366
 
 
1367
    int i;
 
1368
 
 
1369
    o->draw_pattern=pd;
 
1370
    o->dp_arg = arg;
 
1371
 
 
1372
    overlay_set_mode(o, EM8300_OVERLAY_MODE_OVERLAY);
 
1373
    overlay_set_screen(o, o->xres, o->yres, o->depth);
 
1374
 
 
1375
    /* Calibrate Y-offset */
 
1376
 
 
1377
    o->draw_pattern(0x0000ff, 0, 0, 0, 355, 1, o->dp_arg);
 
1378
 
 
1379
    cal.cal_mode = EM8300_OVERLAY_CALMODE_YOFFSET;
 
1380
    if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
 
1381
        {
 
1382
            printf("VO: [dxr3] Failed getting overlay Y-offset values!\nExiting.\n");
 
1383
            return -1;
 
1384
        }
 
1385
    o->yoffset = cal.result;
 
1386
    printf("Yoffset: %d\n",cal.result);
 
1387
 
 
1388
    /* Calibrate X-offset */
 
1389
 
 
1390
    o->draw_pattern(0x0000ff, 0, 0, 0, 2, 288, o->dp_arg);
 
1391
 
 
1392
    cal.cal_mode = EM8300_OVERLAY_CALMODE_XOFFSET;
 
1393
    if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
 
1394
        {
 
1395
            printf("VO: [dxr3] Failed getting overlay X-offset values!\nExiting.\n");
 
1396
            return -1;
 
1397
        }
 
1398
    o->xoffset = cal.result;
 
1399
    printf("Xoffset: %d\n",cal.result);
 
1400
 
 
1401
    /* Calibrate X scale correction */
 
1402
 
 
1403
    o->draw_pattern(0x0000ff, 0, 355, 0, 2, 288, o->dp_arg);
 
1404
 
 
1405
    cal.cal_mode = EM8300_OVERLAY_CALMODE_XCORRECTION;
 
1406
    if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
 
1407
        {
 
1408
            printf("VO: [dxr3] Failed getting overlay X-scale correction!\nExiting.\n");
 
1409
            return -1;
 
1410
        }
 
1411
    printf("Xcorrection: %d\n",cal.result);
 
1412
    o->xcorr = cal.result;
 
1413
 
 
1414
    win.xpos = 10;
 
1415
    win.ypos = 10;
 
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");
 
1420
        exit(1);
 
1421
    }
 
1422
 
 
1423
    /* Calibrate key color upper limit */
 
1424
 
 
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);
 
1428
 
 
1429
        cal.arg = i;
 
1430
        cal.arg2 = 1;
 
1431
        cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
 
1432
 
 
1433
        if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
 
1434
            {
 
1435
                return -1 ;
 
1436
            }
 
1437
 
 
1438
        x[n] = i;
 
1439
        r[n] = (cal.result>>16)&0xff;
 
1440
        g[n] = (cal.result>>8)&0xff;
 
1441
        b[n] = (cal.result)&0xff;
 
1442
        n++;
 
1443
    }
 
1444
 
 
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);
 
1448
 
 
1449
    /* Calibrate key color lower limit */
 
1450
 
 
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);
 
1454
 
 
1455
        cal.arg = i;
 
1456
        cal.arg2 = 2;
 
1457
        cal.cal_mode = EM8300_OVERLAY_CALMODE_COLOR;
 
1458
 
 
1459
        if (ioctl(o->dev, EM8300_IOCTL_OVERLAY_CALIBRATE, &cal))
 
1460
            {
 
1461
                return -1 ;
 
1462
            }
 
1463
        x[n] = i;
 
1464
        r[n] = (cal.result>>16)&0xff;
 
1465
        g[n] = (cal.result>>8)&0xff;
 
1466
        b[n] = (cal.result)&0xff;
 
1467
        n++;
 
1468
    }
 
1469
 
 
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);
 
1473
 
 
1474
    overlay_set_mode(o, EM8300_OVERLAY_MODE_OFF);
 
1475
 
 
1476
    return 0;
 
1477
}
 
1478
 
 
1479
 
 
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");
 
1483
            return -1;
 
1484
        }
 
1485
        return 0;
 
1486
}
 
1487
/* End overlay.c */