1 /*
2 * Copyright (C) 2000-2018 the xine project
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * video_out_vidix.c
21 *
22 * xine video_out driver to vidix library by Miguel Freitas 30/05/2002
23 *
24 * based on video_out_xv.c, video_out_syncfb.c and video_out_pgx64.c
25 *
26 * some vidix specific code from mplayer (file vosub_vidix.c)
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <inttypes.h>
37 #include <unistd.h>
38
39 #ifdef HAVE_X11
40 #include <X11/Xlib.h>
41 #endif
42
43 #ifdef HAVE_FB
44 #include <fcntl.h>
45 #include <sys/ioctl.h>
46 #include <linux/fb.h>
47 #include <errno.h>
48 #endif
49
50 #include "xine.h"
51 #include "vidixlib.h"
52 #include "fourcc.h"
53
54 #define LOG_MODULE "video_out_vidix"
55 #define LOG_VERBOSE
56 /*
57 #define LOG
58 */
59
60 #include <xine/video_out.h>
61 #include <xine/xine_internal.h>
62 #include <xine/xineutils.h>
63 #include <xine/vo_scale.h>
64
65 #ifdef HAVE_X11
66 #include "x11osd.h"
67 #endif
68
69 #define NUM_FRAMES 3
70
71 typedef struct vidix_driver_s vidix_driver_t;
72
73
74 typedef struct vidix_property_s {
75 int value;
76 int min;
77 int max;
78
79 cfg_entry_t *entry;
80
81 vidix_driver_t *this;
82 } vidix_property_t;
83
84
85 typedef struct vidix_frame_s {
86 vo_frame_t vo_frame;
87 int width, height, format;
88 double ratio;
89 } vidix_frame_t;
90
91
92 struct vidix_driver_s {
93
94 vo_driver_t vo_driver;
95
96 config_values_t *config;
97
98 char *vidix_name;
99 VDL_HANDLE vidix_handler;
100 uint8_t *vidix_mem;
101 vidix_capability_t vidix_cap;
102 vidix_playback_t vidix_play;
103 vidix_grkey_t vidix_grkey;
104 vidix_video_eq_t vidix_eq;
105 vidix_yuv_t dstrides;
106 int vidix_started;
107 int next_frame;
108 int got_frame_data;
109
110 uint32_t colourkey;
111 int use_doublebuffer;
112
113 int supports_yv12;
114
115 pthread_mutex_t mutex;
116
117 vidix_property_t props[VO_NUM_PROPERTIES];
118 uint32_t capabilities;
119
120 int visual_type;
121
122 /* X11 related stuff */
123 #ifdef HAVE_X11
124 Display *display;
125 int screen;
126 Drawable drawable;
127 GC gc;
128 x11osd *xoverlay;
129 int ovl_changed;
130 #endif
131
132 /* fb related stuff */
133 int fb_width;
134 int fb_height;
135
136 int depth;
137
138 vo_scale_t sc;
139
140 int delivered_format;
141
142 xine_t *xine;
143
144 alphablend_t alphablend_extra_data;
145 };
146
147 typedef struct vidix_class_s {
148 video_driver_class_t driver_class;
149
150 VDL_HANDLE vidix_handler;
151 vidix_capability_t vidix_cap;
152
153 xine_t *xine;
154 } vidix_class_t;
155
156
free_framedata(vidix_frame_t * frame)157 static void free_framedata(vidix_frame_t* frame)
158 {
159 if(frame->vo_frame.base[0]) {
160 free(frame->vo_frame.base[0]);
161 frame->vo_frame.base[0] = NULL;
162 }
163
164 if(frame->vo_frame.base[1]) {
165 free(frame->vo_frame.base[1]);
166 frame->vo_frame.base[1] = NULL;
167 }
168
169 if(frame->vo_frame.base[2]) {
170 free(frame->vo_frame.base[2]);
171 frame->vo_frame.base[2] = NULL;
172 }
173 }
174
write_frame_YUV420P2(vidix_driver_t * this,vidix_frame_t * frame)175 static void write_frame_YUV420P2(vidix_driver_t* this, vidix_frame_t* frame)
176 {
177 uint8_t* y = frame->vo_frame.base[0] + this->sc.displayed_xoffset +
178 this->sc.displayed_yoffset*frame->vo_frame.pitches[0];
179 uint8_t* cb = frame->vo_frame.base[1] + this->sc.displayed_xoffset/2 +
180 this->sc.displayed_yoffset*frame->vo_frame.pitches[1]/2;
181 uint8_t* cr = frame->vo_frame.base[2]+this->sc.displayed_xoffset/2 +
182 this->sc.displayed_yoffset*frame->vo_frame.pitches[2]/2;
183 uint8_t* dst8 = (this->vidix_mem +
184 this->vidix_play.offsets[this->next_frame] +
185 this->vidix_play.offset.y);
186 int h, w;
187
188 for(h = 0; h < this->sc.displayed_height; h++) {
189 xine_fast_memcpy(dst8, y, this->sc.displayed_width);
190 y += frame->vo_frame.pitches[0];
191 dst8 += this->dstrides.y;
192 }
193
194 dst8 = (this->vidix_mem + this->vidix_play.offsets[this->next_frame] +
195 this->vidix_play.offset.v);
196
197 for(h = 0; h < (this->sc.displayed_height / 2); h++) {
198 for(w = 0; w < (this->sc.displayed_height / 2); w++) {
199 dst8[2*w+0] = cb[w];
200 dst8[2*w+1] = cr[w];
201 }
202 cb += frame->vo_frame.pitches[2];
203 cr += frame->vo_frame.pitches[1];
204 dst8 += this->dstrides.y;
205 }
206 }
207
write_frame_sfb(vidix_driver_t * this,vidix_frame_t * frame)208 static void write_frame_sfb(vidix_driver_t* this, vidix_frame_t* frame)
209 {
210 uint8_t *base = this->vidix_mem+this->vidix_play.offsets[this->next_frame];
211
212 switch(frame->format) {
213 case XINE_IMGFMT_YUY2:
214 yuy2_to_yuy2(
215 /* src */
216 frame->vo_frame.base[0]+this->sc.displayed_xoffset*2+
217 this->sc.displayed_yoffset*frame->vo_frame.pitches[0],
218 frame->vo_frame.pitches[0],
219 /* dst */
220 base+this->vidix_play.offset.y, this->dstrides.y,
221 /* width x height */
222 this->sc.displayed_width, this->sc.displayed_height);
223 break;
224
225 case XINE_IMGFMT_YV12: {
226 uint8_t* y = frame->vo_frame.base[0] + this->sc.displayed_xoffset +
227 this->sc.displayed_yoffset*frame->vo_frame.pitches[0];
228 uint8_t* cb = frame->vo_frame.base[1] + this->sc.displayed_xoffset/2 +
229 this->sc.displayed_yoffset*frame->vo_frame.pitches[1]/2;
230 uint8_t* cr = frame->vo_frame.base[2] + this->sc.displayed_xoffset/2 +
231 this->sc.displayed_yoffset*frame->vo_frame.pitches[2]/2;
232
233 if(this->supports_yv12) {
234 if(this->vidix_play.flags & VID_PLAY_INTERLEAVED_UV)
235 write_frame_YUV420P2(this, frame);
236 else
237 yv12_to_yv12(
238 /* Y */
239 y, frame->vo_frame.pitches[0],
240 base+this->vidix_play.offset.y, this->dstrides.y,
241 /* U */
242 cr, frame->vo_frame.pitches[2],
243 base+this->vidix_play.offset.u, this->dstrides.u/2,
244 /* V */
245 cb, frame->vo_frame.pitches[1],
246 base+this->vidix_play.offset.v, this->dstrides.v/2,
247 /* width x height */
248 this->sc.displayed_width, this->sc.displayed_height);
249 } else
250 yv12_to_yuy2(
251 /* src */
252 y, frame->vo_frame.pitches[0],
253 cb, frame->vo_frame.pitches[1],
254 cr, frame->vo_frame.pitches[2],
255 /* dst */
256 base+this->vidix_play.offset.y, this->dstrides.y,
257 /* width x height */
258 this->sc.displayed_width, this->sc.displayed_height,
259 /* progressive */
260 frame->vo_frame.progressive_frame);
261 break;
262 }
263
264 default:
265 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
266 "video_out_vidix: error. (unknown frame format %04x)\n", frame->format);
267 break;
268 }
269 }
270
271
vidix_clean_output_area(vidix_driver_t * this)272 static void vidix_clean_output_area(vidix_driver_t *this) {
273
274 if(this->visual_type == XINE_VISUAL_TYPE_X11) {
275 #ifdef HAVE_X11
276 int i;
277
278 XLockDisplay(this->display);
279
280 XSetForeground(this->display, this->gc, BlackPixel(this->display, this->screen));
281
282 for( i = 0; i < 4; i++ ) {
283 if( this->sc.border[i].w && this->sc.border[i].h ) {
284 XFillRectangle(this->display, this->drawable, this->gc,
285 this->sc.border[i].x, this->sc.border[i].y,
286 this->sc.border[i].w, this->sc.border[i].h);
287 }
288 }
289
290 XSetForeground(this->display, this->gc, this->colourkey);
291 XFillRectangle(this->display, this->drawable, this->gc, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height);
292
293 if (this->xoverlay) {
294 x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height);
295 this->ovl_changed = 1;
296 }
297
298 XFlush(this->display);
299
300 XUnlockDisplay(this->display);
301 #endif
302 }
303 }
304
305
vidix_update_colourkey(vidix_driver_t * this)306 static void vidix_update_colourkey(vidix_driver_t *this) {
307 switch(this->depth) {
308 case 15:
309 this->colourkey = ((this->vidix_grkey.ckey.red & 0xF8) << 7) |
310 ((this->vidix_grkey.ckey.green & 0xF8) << 2) |
311 ((this->vidix_grkey.ckey.blue & 0xF8) >> 3);
312 break;
313 case 16:
314 this->colourkey = ((this->vidix_grkey.ckey.red & 0xF8) << 8) |
315 ((this->vidix_grkey.ckey.green & 0xFC) << 3) |
316 ((this->vidix_grkey.ckey.blue & 0xF8) >> 3);
317 break;
318 case 24:
319 case 32:
320 this->colourkey = ((this->vidix_grkey.ckey.red & 0xFF) << 16) |
321 ((this->vidix_grkey.ckey.green & 0xFF) << 8) |
322 ((this->vidix_grkey.ckey.blue & 0xFF));
323 break;
324 default:
325 break;
326 }
327
328 vidix_clean_output_area(this);
329
330 vdlSetGrKeys(this->vidix_handler, &this->vidix_grkey);
331 }
332
333
vidix_get_capabilities(vo_driver_t * this_gen)334 static uint32_t vidix_get_capabilities (vo_driver_t *this_gen) {
335
336 vidix_driver_t *this = (vidix_driver_t *) this_gen;
337
338 return this->capabilities;
339 }
340
341 #ifdef HAVE_FB
vidixfb_frame_output_cb(void * user_data,int video_width,int video_height,double video_pixel_aspect,int * dest_x,int * dest_y,int * dest_width,int * dest_height,double * dest_pixel_aspect,int * win_x,int * win_y)342 static void vidixfb_frame_output_cb(void *user_data, int video_width, int video_height, double video_pixel_aspect, int *dest_x, int *dest_y, int *dest_width, int *dest_height, double *dest_pixel_aspect, int *win_x, int *win_y) {
343 vidix_driver_t *this = (vidix_driver_t *) user_data;
344
345 (void)video_width;
346 (void)video_height;
347 (void)video_pixel_aspect;
348 *dest_x = 0;
349 *dest_y = 0;
350 *dest_width = this->fb_width;
351 *dest_height = this->fb_height;
352 *dest_pixel_aspect = 1.0;
353 *win_x = 0;
354 *win_y = 0;
355 }
356 #endif
357
vidix_frame_field(vo_frame_t * vo_img,int which_field)358 static void vidix_frame_field (vo_frame_t *vo_img, int which_field) {
359 /* not needed for vidix */
360 (void)vo_img;
361 (void)which_field;
362 }
363
vidix_frame_dispose(vo_frame_t * vo_img)364 static void vidix_frame_dispose (vo_frame_t *vo_img) {
365
366 vidix_frame_t *frame = (vidix_frame_t *) vo_img ;
367
368 free_framedata(frame);
369 free (frame);
370 }
371
vidix_alloc_frame(vo_driver_t * this_gen)372 static vo_frame_t *vidix_alloc_frame (vo_driver_t *this_gen) {
373 /* vidix_driver_t *this = (vidix_driver_t *) this_gen; */
374 vidix_frame_t *frame ;
375
376 (void)this_gen;
377 frame = (vidix_frame_t *) calloc(1, sizeof(vidix_frame_t));
378 if (!frame)
379 return NULL;
380
381 pthread_mutex_init (&frame->vo_frame.mutex, NULL);
382
383 frame->vo_frame.base[0] = NULL;
384 frame->vo_frame.base[1] = NULL;
385 frame->vo_frame.base[2] = NULL;
386
387 /*
388 * supply required functions
389 */
390
391 frame->vo_frame.proc_slice = NULL;
392 frame->vo_frame.proc_frame = NULL;
393 frame->vo_frame.field = vidix_frame_field;
394 frame->vo_frame.dispose = vidix_frame_dispose;
395
396 return (vo_frame_t *) frame;
397 }
398
399
vidix_compute_ideal_size(vidix_driver_t * this)400 static void vidix_compute_ideal_size (vidix_driver_t *this) {
401
402 _x_vo_scale_compute_ideal_size( &this->sc );
403
404 }
405
406 /*
407 * Configure vidix device
408 */
409
vidix_config_playback(vidix_driver_t * this)410 static void vidix_config_playback (vidix_driver_t *this) {
411
412 uint32_t apitch;
413 int err;
414 unsigned int i;
415
416 _x_vo_scale_compute_output_size( &this->sc );
417
418 /* We require that the displayed xoffset and width are even.
419 * To prevent displaying more than we're supposed to we round the
420 * xoffset up and the width down */
421 this->sc.displayed_xoffset = (this->sc.displayed_xoffset+1) & ~1;
422 this->sc.displayed_width = this->sc.displayed_width & ~1;
423
424 /* For yv12 source displayed yoffset and height need to be even too */
425 if(this->delivered_format == XINE_IMGFMT_YV12) {
426 this->sc.displayed_yoffset = (this->sc.displayed_yoffset+1) & ~1;
427 this->sc.displayed_height = this->sc.displayed_height & ~1;
428 }
429
430 if( this->vidix_started > 0 ) {
431 lprintf("video_out_vidix: overlay off\n");
432 vdlPlaybackOff(this->vidix_handler);
433 }
434
435 memset(&this->vidix_play,0,sizeof(vidix_playback_t));
436
437 if(this->delivered_format == XINE_IMGFMT_YV12 && this->supports_yv12)
438 this->vidix_play.fourcc = IMGFMT_YV12;
439 else
440 this->vidix_play.fourcc = IMGFMT_YUY2;
441
442 this->vidix_play.capability = this->vidix_cap.flags; /* every ;) */
443 this->vidix_play.blend_factor = 0; /* for now */
444 this->vidix_play.src.x = 0;
445 this->vidix_play.src.y = 0;
446 this->vidix_play.src.w = this->sc.displayed_width;
447 this->vidix_play.src.h = this->sc.displayed_height;
448 this->vidix_play.dest.x = this->sc.gui_win_x+this->sc.output_xoffset;
449 this->vidix_play.dest.y = this->sc.gui_win_y+this->sc.output_yoffset;
450 this->vidix_play.dest.w = this->sc.output_width;
451 this->vidix_play.dest.h = this->sc.output_height;
452 this->vidix_play.num_frames= this->use_doublebuffer ? NUM_FRAMES : 1;
453 this->vidix_play.src.pitch.y = this->vidix_play.src.pitch.u = this->vidix_play.src.pitch.v = 0;
454
455 if((err=vdlConfigPlayback(this->vidix_handler,&this->vidix_play))!=0)
456 {
457 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
458 "video_out_vidix: Can't configure playback: %s\n",strerror(err));
459 this->vidix_started = -1;
460 return;
461 }
462
463 lprintf("video_out_vidix: dga_addr = %p frame_size = %u frames = %u\n",
464 this->vidix_play.dga_addr, this->vidix_play.frame_size,
465 this->vidix_play.num_frames );
466
467 lprintf("video_out_vidix: offsets[0..2] = %u %u %u\n",
468 this->vidix_play.offsets[0], this->vidix_play.offsets[1],
469 this->vidix_play.offsets[2] );
470
471 lprintf("video_out_vidix: offset.y/u/v = %u/%u/%u\n",
472 this->vidix_play.offset.y, this->vidix_play.offset.u,
473 this->vidix_play.offset.v );
474
475 lprintf("video_out_vidix: src.x/y/w/h = %u/%u/%u/%u\n",
476 this->vidix_play.src.x, this->vidix_play.src.y,
477 this->vidix_play.src.w, this->vidix_play.src.h );
478
479 lprintf("video_out_vidix: dest.x/y/w/h = %u/%u/%u/%u\n",
480 this->vidix_play.dest.x, this->vidix_play.dest.y,
481 this->vidix_play.dest.w, this->vidix_play.dest.h );
482
483 lprintf("video_out_vidix: dest.pitch.y/u/v = %u/%u/%u\n",
484 this->vidix_play.dest.pitch.y, this->vidix_play.dest.pitch.u,
485 this->vidix_play.dest.pitch.v );
486
487 this->vidix_mem = this->vidix_play.dga_addr;
488
489 this->next_frame = 0;
490
491 /* clear every frame with correct address and frame_size */
492 for (i = 0; i < this->vidix_play.num_frames; i++)
493 memset(this->vidix_mem + this->vidix_play.offsets[i], 0x80,
494 this->vidix_play.frame_size);
495
496 switch(this->vidix_play.fourcc) {
497 case IMGFMT_YV12:
498 apitch = this->vidix_play.dest.pitch.y-1;
499 this->dstrides.y = (this->sc.displayed_width + apitch) & ~apitch;
500 apitch = this->vidix_play.dest.pitch.v-1;
501 this->dstrides.v = (this->sc.displayed_width + apitch) & ~apitch;
502 apitch = this->vidix_play.dest.pitch.u-1;
503 this->dstrides.u = (this->sc.displayed_width + apitch) & ~apitch;
504 break;
505 case IMGFMT_YUY2:
506 apitch = this->vidix_play.dest.pitch.y-1;
507 this->dstrides.y = (this->sc.displayed_width*2 + apitch) & ~apitch;
508 break;
509 default:
510 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
511 "video_out_vidix: error. (unknown frame format: %04x)\n", this->delivered_format);
512 }
513
514 lprintf("video_out_vidix: overlay on\n");
515 vdlPlaybackOn(this->vidix_handler);
516 this->vidix_started = 1;
517 }
518
vidix_update_frame_format(vo_driver_t * this_gen,vo_frame_t * frame_gen,uint32_t width,uint32_t height,double ratio,int format,int flags)519 static void vidix_update_frame_format (vo_driver_t *this_gen,
520 vo_frame_t *frame_gen,
521 uint32_t width, uint32_t height,
522 double ratio, int format, int flags) {
523 vidix_driver_t *this = (vidix_driver_t *) this_gen;
524 vidix_frame_t *frame = (vidix_frame_t *) frame_gen;
525
526 (void)flags;
527 if ((frame->width != (int)width)
528 || (frame->height != (int)height)
529 || (frame->format != format)) {
530
531 /*
532 * (re-) allocate image
533 */
534
535 free_framedata(frame);
536
537 frame->width = width;
538 frame->height = height;
539 frame->format = format;
540
541 switch(format) {
542 case XINE_IMGFMT_YV12:
543 frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
544 frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
545 frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
546 frame->vo_frame.base[0] = malloc(frame->vo_frame.pitches[0] * height);
547 frame->vo_frame.base[1] = malloc(frame->vo_frame.pitches[1] * ((height+1)/2));
548 frame->vo_frame.base[2] = malloc(frame->vo_frame.pitches[2] * ((height+1)/2));
549 break;
550 case XINE_IMGFMT_YUY2:
551 frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
552 frame->vo_frame.base[0] = malloc(frame->vo_frame.pitches[0] * height);
553 frame->vo_frame.base[1] = NULL;
554 frame->vo_frame.base[2] = NULL;
555 break;
556 default:
557 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
558 "video_out_vidix: error. (unknown frame format: %04x)\n", format);
559 }
560
561 if((format == XINE_IMGFMT_YV12 && (frame->vo_frame.base[0] == NULL || frame->vo_frame.base[1] == NULL || frame->vo_frame.base[2] == NULL))
562 || (format == XINE_IMGFMT_YUY2 && frame->vo_frame.base[0] == NULL)) {
563 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
564 "video_out_vidix: error. (framedata allocation failed: out of memory)\n");
565
566 free_framedata(frame);
567 }
568 }
569
570 frame->ratio = ratio;
571 }
572
vidix_overlay_begin(vo_driver_t * this_gen,vo_frame_t * frame_gen,int changed)573 static void vidix_overlay_begin (vo_driver_t *this_gen,
574 vo_frame_t *frame_gen, int changed) {
575 vidix_driver_t *this = (vidix_driver_t *) this_gen;
576
577 #ifdef HAVE_X11
578 this->ovl_changed += changed;
579
580 if( this->ovl_changed && this->xoverlay ) {
581 XLockDisplay (this->display);
582 x11osd_clear(this->xoverlay);
583 XUnlockDisplay (this->display);
584 }
585 #endif
586
587 this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
588 this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
589 }
590
vidix_overlay_end(vo_driver_t * this_gen,vo_frame_t * vo_img)591 static void vidix_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) {
592 #ifdef HAVE_X11
593 vidix_driver_t *this = (vidix_driver_t *) this_gen;
594
595 (void)vo_img;
596 if( this->ovl_changed && this->xoverlay ) {
597 XLockDisplay (this->display);
598 x11osd_expose(this->xoverlay);
599 XUnlockDisplay (this->display);
600 }
601
602 this->ovl_changed = 0;
603 #endif
604 }
605
606 /*
607 *
608 */
vidix_overlay_blend(vo_driver_t * this_gen,vo_frame_t * frame_gen,vo_overlay_t * overlay)609 static void vidix_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) {
610
611 vidix_frame_t *frame = (vidix_frame_t *) frame_gen;
612 vidix_driver_t *this = (vidix_driver_t *) this_gen;
613
614 if (overlay->rle) {
615 if( overlay->unscaled ) {
616 #ifdef HAVE_X11
617 if( this->ovl_changed && this->xoverlay ) {
618 XLockDisplay (this->display);
619 x11osd_blend(this->xoverlay, overlay);
620 XUnlockDisplay (this->display);
621 }
622 #endif
623 } else {
624 if( frame->format == XINE_IMGFMT_YV12 )
625 _x_blend_yuv( frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data);
626 else
627 _x_blend_yuy2( frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0], &this->alphablend_extra_data);
628 }
629 }
630 }
631
632
vidix_redraw_needed(vo_driver_t * this_gen)633 static int vidix_redraw_needed (vo_driver_t *this_gen) {
634 vidix_driver_t *this = (vidix_driver_t *) this_gen;
635 int ret = 0;
636
637 if(_x_vo_scale_redraw_needed(&this->sc)) {
638 if(this->got_frame_data) {
639 vidix_config_playback(this);
640 vidix_clean_output_area(this);
641
642 ret = 1;
643 }
644 }
645
646 return ret;
647 }
648
649
vidix_display_frame(vo_driver_t * this_gen,vo_frame_t * frame_gen)650 static void vidix_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
651
652 vidix_driver_t *this = (vidix_driver_t *) this_gen;
653 vidix_frame_t *frame = (vidix_frame_t *) frame_gen;
654
655 pthread_mutex_lock(&this->mutex);
656
657 if ( (frame->width != this->sc.delivered_width)
658 || (frame->height != this->sc.delivered_height)
659 || (frame->ratio != this->sc.delivered_ratio)
660 || (frame->format != this->delivered_format )
661 || (frame->vo_frame.crop_left != this->sc.crop_left)
662 || (frame->vo_frame.crop_right != this->sc.crop_right)
663 || (frame->vo_frame.crop_top != this->sc.crop_top)
664 || (frame->vo_frame.crop_bottom != this->sc.crop_bottom) ) {
665 lprintf("video_out_vidix: change frame format\n");
666
667 this->sc.delivered_width = frame->width;
668 this->sc.delivered_height = frame->height;
669 this->sc.delivered_ratio = frame->ratio;
670 this->delivered_format = frame->format;
671
672 this->sc.crop_left = frame->vo_frame.crop_left;
673 this->sc.crop_right = frame->vo_frame.crop_right;
674 this->sc.crop_top = frame->vo_frame.crop_top;
675 this->sc.crop_bottom = frame->vo_frame.crop_bottom;
676
677 vidix_compute_ideal_size( this );
678 this->sc.force_redraw = 1;
679 }
680
681 /*
682 * check if we have to reconfigure vidix because of
683 * format/window position change
684 */
685 this->got_frame_data = 1;
686 vidix_redraw_needed(this_gen);
687
688 if(this->vidix_started > 0) {
689 write_frame_sfb(this, frame);
690
691 if( this->vidix_play.num_frames > 1 ) {
692 vdlPlaybackFrameSelect(this->vidix_handler,this->next_frame);
693 this->next_frame=(this->next_frame+1)%this->vidix_play.num_frames;
694 }
695 }
696
697 frame->vo_frame.free(frame_gen);
698
699 pthread_mutex_unlock(&this->mutex);
700 }
701
702
vidix_get_property(vo_driver_t * this_gen,int property)703 static int vidix_get_property (vo_driver_t *this_gen, int property) {
704
705 vidix_driver_t *this = (vidix_driver_t *) this_gen;
706
707 if ((property < 0) || (property >= VO_NUM_PROPERTIES)) return 0;
708
709 switch (property) {
710 case VO_PROP_WINDOW_WIDTH:
711 this->props[property].value = this->sc.gui_width;
712 break;
713 case VO_PROP_WINDOW_HEIGHT:
714 this->props[property].value = this->sc.gui_height;
715 break;
716 case VO_PROP_OUTPUT_WIDTH:
717 this->props[property].value = this->sc.output_width;
718 break;
719 case VO_PROP_OUTPUT_HEIGHT:
720 this->props[property].value = this->sc.output_height;
721 break;
722 case VO_PROP_OUTPUT_XOFFSET:
723 this->props[property].value = this->sc.output_xoffset;
724 break;
725 case VO_PROP_OUTPUT_YOFFSET:
726 this->props[property].value = this->sc.output_yoffset;
727 break;
728 }
729
730 lprintf ("video_out_vidix: property #%d = %d\n", property,
731 this->props[property].value);
732
733 return this->props[property].value;
734 }
735
736
vidix_set_property(vo_driver_t * this_gen,int property,int value)737 static int vidix_set_property (vo_driver_t *this_gen,
738 int property, int value) {
739
740 vidix_driver_t *this = (vidix_driver_t *) this_gen;
741 int err;
742
743 if ((property < 0) || (property >= VO_NUM_PROPERTIES)) return 0;
744
745 if ((value >= this->props[property].min) &&
746 (value <= this->props[property].max))
747 {
748 this->props[property].value = value;
749
750 if ( property == VO_PROP_ASPECT_RATIO) {
751 if(value >= XINE_VO_ASPECT_NUM_RATIOS)
752 value = this->props[property].value = XINE_VO_ASPECT_AUTO;
753
754 lprintf("video_out_vidix: aspect ratio changed to %s\n",
755 _x_vo_scale_aspect_ratio_name_table[value]);
756
757 this->sc.user_ratio = value;
758 vidix_compute_ideal_size (this);
759 this->sc.force_redraw = 1;
760 }
761
762 if ( property == VO_PROP_ZOOM_X ) {
763 this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
764
765 vidix_compute_ideal_size (this);
766 this->sc.force_redraw = 1;
767 }
768
769 if ( property == VO_PROP_ZOOM_Y ) {
770 this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
771
772 vidix_compute_ideal_size (this);
773 this->sc.force_redraw = 1;
774 }
775
776 if ( property == VO_PROP_HUE ) {
777 this->vidix_eq.cap = VEQ_CAP_HUE;
778 this->vidix_eq.hue = value;
779
780 if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0)
781 xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set hue: %s\n", strerror(err));
782 }
783
784 if ( property == VO_PROP_SATURATION ) {
785 this->vidix_eq.cap = VEQ_CAP_SATURATION;
786 this->vidix_eq.saturation = value;
787
788 if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0)
789 xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set saturation: %s\n", strerror(err));
790 }
791
792 if ( property == VO_PROP_BRIGHTNESS ) {
793 this->vidix_eq.cap = VEQ_CAP_BRIGHTNESS;
794 this->vidix_eq.brightness = value;
795
796 if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0)
797 xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set brightness: %s\n", strerror(err));
798 }
799
800 if ( property == VO_PROP_CONTRAST ) {
801 this->vidix_eq.cap = VEQ_CAP_CONTRAST;
802 this->vidix_eq.contrast = value;
803
804 if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0)
805 xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set contrast: %s\n", strerror(err));
806 }
807 }
808
809 return value;
810 }
811
812
vidix_ckey_callback(vo_driver_t * this_gen,xine_cfg_entry_t * entry)813 static void vidix_ckey_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) {
814
815 vidix_driver_t *this = (vidix_driver_t *) this_gen;
816
817 if(strcmp(entry->key, "video.device.vidix_colour_key_red") == 0) {
818 this->vidix_grkey.ckey.red = entry->num_value;
819 }
820
821 if(strcmp(entry->key, "video.device.vidix_colour_key_green") == 0) {
822 this->vidix_grkey.ckey.green = entry->num_value;
823 }
824
825 if(strcmp(entry->key, "video.device.vidix_colour_key_blue") == 0) {
826 this->vidix_grkey.ckey.blue = entry->num_value;
827 }
828
829 vidix_update_colourkey(this);
830 this->sc.force_redraw = 1;
831 }
832
833
vidix_db_callback(vo_driver_t * this_gen,xine_cfg_entry_t * entry)834 static void vidix_db_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) {
835
836 vidix_driver_t *this = (vidix_driver_t *) this_gen;
837
838 this->use_doublebuffer = entry->num_value;
839 this->sc.force_redraw = 1;
840 }
841
842
vidix_rgb_callback(vo_driver_t * this_gen,xine_cfg_entry_t * entry)843 static void vidix_rgb_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) {
844 int err;
845 vidix_driver_t *this = (vidix_driver_t *) this_gen;
846
847 this->vidix_eq.cap = VEQ_CAP_RGB_INTENSITY;
848
849 if(!strcmp(entry->key, "video.output.vidix_red_intensity")) {
850 this->vidix_eq.red_intensity = entry->num_value;
851 } else if(!strcmp(entry->key, "video.output.vidix_green_intensity")) {
852 this->vidix_eq.green_intensity = entry->num_value;
853 } else if(!strcmp(entry->key, "video.output.vidix_blue_intensity")) {
854 this->vidix_eq.blue_intensity = entry->num_value;
855 }
856
857 if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)))
858 xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set rgb intensity: %s\n", strerror(err));
859 }
860
861
vidix_get_property_min_max(vo_driver_t * this_gen,int property,int * min,int * max)862 static void vidix_get_property_min_max (vo_driver_t *this_gen,
863 int property, int *min, int *max) {
864
865 vidix_driver_t *this = (vidix_driver_t *) this_gen;
866
867 if ((property < 0) || (property >= VO_NUM_PROPERTIES)) {
868 *min = *max = 0;
869 return;
870 }
871 *min = this->props[property].min;
872 *max = this->props[property].max;
873 }
874
vidix_gui_data_exchange(vo_driver_t * this_gen,int data_type,void * data)875 static int vidix_gui_data_exchange (vo_driver_t *this_gen,
876 int data_type, void *data) {
877
878 int ret = 0;
879 vidix_driver_t *this = (vidix_driver_t *) this_gen;
880
881 pthread_mutex_lock(&this->mutex);
882
883 switch (data_type) {
884
885 case XINE_GUI_SEND_DRAWABLE_CHANGED:
886 lprintf ("video_out_vidix: GUI_DATA_EX_DRAWABLE_CHANGED\n");
887
888 if(this->visual_type == XINE_VISUAL_TYPE_X11) {
889 #ifdef HAVE_X11
890 this->drawable = (Drawable) data;
891 XLockDisplay(this->display);
892 XFreeGC(this->display, this->gc);
893 this->gc = XCreateGC(this->display, this->drawable, 0, NULL);
894 if(this->xoverlay)
895 x11osd_drawable_changed(this->xoverlay, this->drawable);
896 this->ovl_changed = 1;
897 XUnlockDisplay(this->display);
898 #endif
899 }
900 break;
901
902 case XINE_GUI_SEND_EXPOSE_EVENT:
903 lprintf ("video_out_vidix: GUI_DATA_EX_EXPOSE_EVENT\n");
904 vidix_clean_output_area(this);
905 #ifdef HAVE_X11
906 XLockDisplay (this->display);
907 if(this->xoverlay)
908 x11osd_expose(this->xoverlay);
909
910 XSync(this->display, False);
911 XUnlockDisplay (this->display);
912 #endif
913 break;
914
915 case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
916 {
917 int x1, y1, x2, y2;
918 x11_rectangle_t *rect = data;
919
920 _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y,
921 &x1, &y1);
922 _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h,
923 &x2, &y2);
924 rect->x = x1;
925 rect->y = y1;
926 rect->w = x2-x1;
927 rect->h = y2-y1;
928 }
929 break;
930
931 default:
932 ret = -1;
933 }
934 pthread_mutex_unlock(&this->mutex);
935
936 return ret;
937 }
938
vidix_exit(vo_driver_t * this_gen)939 static void vidix_exit (vo_driver_t *this_gen) {
940
941 vidix_driver_t *this = (vidix_driver_t *) this_gen;
942
943 if( this->vidix_started > 0 ) {
944 vdlPlaybackOff(this->vidix_handler);
945 }
946 vdlClose(this->vidix_handler);
947
948 #ifdef HAVE_X11
949 XLockDisplay (this->display);
950 XFreeGC(this->display, this->gc);
951
952 if( this->xoverlay )
953 x11osd_destroy (this->xoverlay);
954
955 XUnlockDisplay (this->display);
956 #endif
957
958 _x_alphablend_free(&this->alphablend_extra_data);
959 _x_vo_scale_cleanup (&this->sc, this->config);
960
961 free (this);
962 }
963
open_plugin(video_driver_class_t * class_gen)964 static vidix_driver_t *open_plugin (video_driver_class_t *class_gen) {
965 vidix_class_t *class = (vidix_class_t *) class_gen;
966 config_values_t *config = class->xine->config;
967 vidix_driver_t *this;
968 int err;
969
970 this = (vidix_driver_t *) calloc(1, sizeof(vidix_driver_t));
971 if (!this)
972 return NULL;
973
974 _x_alphablend_init(&this->alphablend_extra_data, class->xine);
975
976 pthread_mutex_init (&this->mutex, NULL);
977
978 this->vidix_handler = class->vidix_handler;
979 this->vidix_cap = class->vidix_cap;
980
981 _x_vo_scale_init( &this->sc, 1, /*this->vidix_cap.flags & FLAG_UPSCALER,*/ 0, config );
982
983 this->xine = class->xine;
984 this->config = config;
985
986 this->got_frame_data = 0;
987 this->capabilities = VO_CAP_CROP | VO_CAP_ZOOM_X | VO_CAP_ZOOM_Y;
988
989 /* Find what equalizer flags are supported */
990 if(this->vidix_cap.flags & FLAG_EQUALIZER) {
991 if((err = vdlPlaybackGetEq(this->vidix_handler, &this->vidix_eq)) != 0) {
992 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
993 "video_out_vidix: couldn't get equalizer capabilities: %s\n", strerror(err));
994 } else {
995 if(this->vidix_eq.cap & VEQ_CAP_BRIGHTNESS) {
996 this->capabilities |= VO_CAP_BRIGHTNESS;
997 this->props[VO_PROP_BRIGHTNESS].value = 0;
998 this->props[VO_PROP_BRIGHTNESS].min = -1000;
999 this->props[VO_PROP_BRIGHTNESS].max = 1000;
1000 }
1001
1002 if(this->vidix_eq.cap & VEQ_CAP_CONTRAST) {
1003 this->capabilities |= VO_CAP_CONTRAST;
1004 this->props[VO_PROP_CONTRAST].value = 0;
1005 this->props[VO_PROP_CONTRAST].min = -1000;
1006 this->props[VO_PROP_CONTRAST].max = 1000;
1007 }
1008
1009 if(this->vidix_eq.cap & VEQ_CAP_SATURATION) {
1010 this->capabilities |= VO_CAP_SATURATION;
1011 this->props[VO_PROP_SATURATION].value = 0;
1012 this->props[VO_PROP_SATURATION].min = -1000;
1013 this->props[VO_PROP_SATURATION].max = 1000;
1014 }
1015
1016 if(this->vidix_eq.cap & VEQ_CAP_HUE) {
1017 this->capabilities |= VO_CAP_HUE;
1018 this->props[VO_PROP_HUE].value = 0;
1019 this->props[VO_PROP_HUE].min = -1000;
1020 this->props[VO_PROP_HUE].max = 1000;
1021 }
1022
1023 if(this->vidix_eq.cap & VEQ_CAP_RGB_INTENSITY) {
1024 this->vidix_eq.red_intensity = config->register_range(config,
1025 "video.output.vidix_red_intensity", 0, -1000, 1000,
1026 _("red intensity"), _("The intensity of the red colour components."), 10,
1027 (void*) vidix_rgb_callback, this);
1028
1029 this->vidix_eq.green_intensity = config->register_range(config,
1030 "video.output.vidix_green_intensity", 0, -1000, 1000,
1031 _("green intensity"), _("The intensity of the green colour components."), 10,
1032 (void*) vidix_rgb_callback, this);
1033
1034 this->vidix_eq.blue_intensity = config->register_range(config,
1035 "video.output.vidix_blue_intensity", 0, -1000, 1000,
1036 _("blue intensity"), _("The intensity of the blue colour components."), 10,
1037 (void*) vidix_rgb_callback, this);
1038
1039 if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)))
1040 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
1041 "video_out_vidix: can't set rgb intensity: %s\n", strerror(err));
1042 }
1043 }
1044 }
1045
1046 /* Configuration for double buffering */
1047 this->use_doublebuffer = config->register_bool(config,
1048 "video.device.vidix_double_buffer", 1, _("enable double buffering"),
1049 _("Double buffering will synchronize the update of the video image to the repainting of the entire "
1050 "screen (\"vertical retrace\"). This eliminates flickering and tearing artifacts, but will use "
1051 "more graphics memory."), 20,
1052 (void*) vidix_db_callback, this);
1053
1054 /* Set up remaining props */
1055 this->props[VO_PROP_ASPECT_RATIO].value = XINE_VO_ASPECT_AUTO;
1056 this->props[VO_PROP_ASPECT_RATIO].min = 0;
1057 this->props[VO_PROP_ASPECT_RATIO].max = XINE_VO_ASPECT_NUM_RATIOS;
1058
1059 this->props[VO_PROP_ZOOM_X].value = 100;
1060 this->props[VO_PROP_ZOOM_X].min = XINE_VO_ZOOM_MIN;
1061 this->props[VO_PROP_ZOOM_X].max = XINE_VO_ZOOM_MAX;
1062
1063 this->props[VO_PROP_ZOOM_Y].value = 100;
1064 this->props[VO_PROP_ZOOM_Y].min = XINE_VO_ZOOM_MIN;
1065 this->props[VO_PROP_ZOOM_Y].max = XINE_VO_ZOOM_MAX;
1066
1067 this->vo_driver.get_capabilities = vidix_get_capabilities;
1068 this->vo_driver.alloc_frame = vidix_alloc_frame;
1069 this->vo_driver.update_frame_format = vidix_update_frame_format;
1070 this->vo_driver.overlay_begin = vidix_overlay_begin;
1071 this->vo_driver.overlay_blend = vidix_overlay_blend;
1072 this->vo_driver.overlay_end = vidix_overlay_end;
1073 this->vo_driver.display_frame = vidix_display_frame;
1074 this->vo_driver.get_property = vidix_get_property;
1075 this->vo_driver.set_property = vidix_set_property;
1076 this->vo_driver.get_property_min_max = vidix_get_property_min_max;
1077 this->vo_driver.gui_data_exchange = vidix_gui_data_exchange;
1078 this->vo_driver.dispose = vidix_exit;
1079 this->vo_driver.redraw_needed = vidix_redraw_needed;
1080
1081 return this;
1082 }
1083
query_fourccs(vidix_driver_t * this)1084 static void query_fourccs (vidix_driver_t *this) {
1085 vidix_fourcc_t vidix_fourcc;
1086 int err;
1087
1088 /* Detect if YUY2 is supported */
1089 memset(&vidix_fourcc, 0, sizeof(vidix_fourcc_t));
1090 vidix_fourcc.fourcc = IMGFMT_YUY2;
1091 vidix_fourcc.depth = this->depth;
1092
1093 if((err = vdlQueryFourcc(this->vidix_handler, &vidix_fourcc)) == 0) {
1094 this->capabilities |= VO_CAP_YUY2;
1095 xprintf(this->xine, XINE_VERBOSITY_LOG,
1096 _("video_out_vidix: adaptor supports the yuy2 format\n"));
1097 }
1098
1099 /* Detect if YV12 is supported - we always support yv12 but we need
1100 to know if we have to convert */
1101 this->capabilities |= VO_CAP_YV12;
1102 vidix_fourcc.fourcc = IMGFMT_YV12;
1103
1104 if((err = vdlQueryFourcc(this->vidix_handler, &vidix_fourcc)) == 0) {
1105 this->supports_yv12 = 1;
1106 xprintf(this->xine, XINE_VERBOSITY_LOG,
1107 _("video_out_vidix: adaptor supports the yv12 format\n"));
1108 } else
1109 this->supports_yv12 = 0;
1110 }
1111
init_class(xine_t * xine,const void * visual_gen)1112 static void *init_class (xine_t *xine, const void *visual_gen) {
1113 vidix_class_t *this;
1114 int err;
1115
1116 (void)visual_gen;
1117 this = (vidix_class_t *) calloc(1, sizeof(vidix_class_t));
1118 if (!this)
1119 return NULL;
1120
1121 if(vdlGetVersion() != VIDIX_VERSION)
1122 {
1123 xprintf(xine, XINE_VERBOSITY_LOG,
1124 _("video_out_vidix: You have wrong version of VIDIX library\n"));
1125 free(this);
1126 return NULL;
1127 }
1128 this->vidix_handler = vdlOpen((XINE_PLUGINDIR"/vidix/"), NULL, TYPE_OUTPUT, 0);
1129 if(this->vidix_handler == NULL)
1130 {
1131 xprintf(xine, XINE_VERBOSITY_LOG,
1132 _("video_out_vidix: Couldn't find working VIDIX driver\n"));
1133 free(this);
1134 return NULL;
1135 }
1136 if((err=vdlGetCapability(this->vidix_handler,&this->vidix_cap)) != 0)
1137 {
1138 xprintf(xine, XINE_VERBOSITY_DEBUG,
1139 "video_out_vidix: Couldn't get capability: %s\n",strerror(err));
1140 free(this);
1141 return NULL;
1142 }
1143
1144 xprintf(xine, XINE_VERBOSITY_LOG,
1145 _("video_out_vidix: using driver: %s by %s\n"), this->vidix_cap.name, this->vidix_cap.author);
1146
1147 this->xine = xine;
1148
1149 return this;
1150 }
1151
1152 #ifdef HAVE_X11
vidix_open_plugin(video_driver_class_t * class_gen,const void * visual_gen)1153 static vo_driver_t *vidix_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) {
1154 vidix_driver_t *this = open_plugin(class_gen);
1155 config_values_t *config = this->config;
1156 const x11_visual_t *visual = (const x11_visual_t *) visual_gen;
1157 XWindowAttributes window_attributes;
1158
1159 (void)visual_gen;
1160 this->visual_type = XINE_VISUAL_TYPE_X11;
1161
1162 this->display = visual->display;
1163 this->screen = visual->screen;
1164 this->drawable = visual->d;
1165 this->gc = XCreateGC(this->display, this->drawable, 0, NULL);
1166 this->xoverlay = NULL;
1167 this->ovl_changed = 0;
1168
1169 XGetWindowAttributes(this->display, this->drawable, &window_attributes);
1170 this->sc.gui_width = window_attributes.width;
1171 this->sc.gui_height = window_attributes.height;
1172 this->depth = window_attributes.depth;
1173
1174 this->sc.frame_output_cb = visual->frame_output_cb;
1175 this->sc.user_data = visual->user_data;
1176
1177 /* We'll assume all drivers support colour keying (which they do
1178 at the moment) */
1179 this->vidix_grkey.ckey.op = CKEY_TRUE;
1180
1181 /* Colour key components */
1182 this->vidix_grkey.ckey.red = config->register_range(config,
1183 "video.device.vidix_colour_key_red", 255, 0, 255,
1184 _("video overlay colour key red component"),
1185 _("The colour key is used to tell the graphics card where to overlay the video image. "
1186 "Try different values, if you experience windows becoming transparent."), 20,
1187 (void*) vidix_ckey_callback, this);
1188
1189 this->vidix_grkey.ckey.green = config->register_range(config,
1190 "video.device.vidix_colour_key_green", 0, 0, 255,
1191 _("video overlay colour key green component"),
1192 _("The colour key is used to tell the graphics card where to overlay the video image. "
1193 "Try different values, if you experience windows becoming transparent."), 20,
1194 (void*) vidix_ckey_callback, this);
1195
1196 this->vidix_grkey.ckey.blue = config->register_range(config,
1197 "video.device.vidix_colour_key_blue", 255, 0, 255,
1198 _("video overlay colour key blue component"),
1199 _("The colour key is used to tell the graphics card where to overlay the video image. "
1200 "Try different values, if you experience windows becoming transparent."), 20,
1201 (void*) vidix_ckey_callback, this);
1202
1203 vidix_update_colourkey(this);
1204
1205 query_fourccs(this);
1206
1207 XLockDisplay (this->display);
1208 if(this->colourkey) {
1209 this->xoverlay = x11osd_create (this->xine, this->display, this->screen,
1210 this->drawable, X11OSD_COLORKEY);
1211 if(this->xoverlay)
1212 x11osd_colorkey(this->xoverlay, this->colourkey, &this->sc);
1213 } else {
1214 this->xoverlay = x11osd_create (this->xine, this->display, this->screen,
1215 this->drawable, X11OSD_SHAPED);
1216 }
1217 XUnlockDisplay (this->display);
1218
1219 if( this->xoverlay )
1220 this->capabilities |= VO_CAP_UNSCALED_OVERLAY;
1221
1222 return &this->vo_driver;
1223 }
1224
vidix_init_class(xine_t * xine,const void * visual_gen)1225 static void *vidix_init_class (xine_t *xine, const void *visual_gen) {
1226
1227 vidix_class_t *this = init_class (xine, visual_gen);
1228
1229 if(this) {
1230 this->driver_class.open_plugin = vidix_open_plugin;
1231 this->driver_class.identifier = "vidix";
1232 this->driver_class.description = N_("xine video output plugin using libvidix for x11");
1233 this->driver_class.dispose = default_video_driver_class_dispose;
1234 }
1235
1236 return this;
1237 }
1238
1239 static const vo_info_t vo_info_vidix = {
1240 .priority = 2,
1241 .visual_type = XINE_VISUAL_TYPE_X11,
1242 };
1243 #endif
1244
1245 #ifdef HAVE_FB
vidixfb_open_plugin(video_driver_class_t * class_gen,const void * visual_gen)1246 static vo_driver_t *vidixfb_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) {
1247 vidix_driver_t *this = open_plugin(class_gen);
1248 config_values_t *config = this->config;
1249 char *device;
1250 int fd;
1251 struct fb_var_screeninfo fb_var;
1252
1253 (void)visual_gen;
1254 this->visual_type = XINE_VISUAL_TYPE_FB;
1255
1256 /* Register config option for fb device */
1257 device = config->register_filename(config, "video.device.vidixfb_device", "/dev/fb0", XINE_CONFIG_STRING_IS_DEVICE_NAME,
1258 _("framebuffer device name"),
1259 _("Specifies the file name for the framebuffer device to be used.\n"
1260 "This setting is security critical, because when changed to a different file, xine "
1261 "can be used to fill this file with arbitrary content. So you should be careful that "
1262 "the value you enter really is a proper framebuffer device."),
1263 XINE_CONFIG_SECURITY, NULL, NULL);
1264
1265 /* Open fb device for reading */
1266 if((fd = xine_open_cloexec("/dev/fb0", O_RDONLY)) < 0) {
1267 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
1268 "video_out_vidix: unable to open frame buffer device \"%s\": %s\n", device, strerror(errno));
1269 return NULL;
1270 }
1271
1272 /* Read screen info */
1273 if(ioctl(fd, FBIOGET_VSCREENINFO, &fb_var) != 0) {
1274 xprintf(this->xine, XINE_VERBOSITY_DEBUG,
1275 "video_out_vidix: error in ioctl FBIOGET_VSCREENINFO: %s", strerror(errno));
1276 close(fd);
1277 return NULL;
1278 }
1279
1280 /* Store screen bpp and dimensions */
1281 this->depth = fb_var.bits_per_pixel;
1282 this->fb_width = fb_var.xres;
1283 this->fb_height = fb_var.yres;
1284
1285 /* Close device */
1286 close(fd);
1287
1288 this->sc.frame_output_cb = vidixfb_frame_output_cb;
1289 this->sc.user_data = this;
1290
1291 /* Make sure colour keying is turned off */
1292 this->vidix_grkey.ckey.op = CKEY_FALSE;
1293 vdlSetGrKeys(this->vidix_handler, &this->vidix_grkey);
1294
1295 query_fourccs(this);
1296
1297 return &this->vo_driver;
1298 }
1299
vidixfb_init_class(xine_t * xine,const void * visual_gen)1300 static void *vidixfb_init_class (xine_t *xine, const void *visual_gen) {
1301
1302 vidix_class_t *this = init_class (xine, visual_gen);
1303
1304 if(this) {
1305 this->driver_class.open_plugin = vidixfb_open_plugin;
1306 this->driver_class.identifier = "vidixfb";
1307 this->driver_class.description = N_("xine video output plugin using libvidix for linux frame buffer");
1308 this->driver_class.dispose = default_video_driver_class_dispose;
1309 }
1310
1311 return this;
1312 }
1313
1314 static const vo_info_t vo_info_vidixfb = {
1315 .priority = 2,
1316 .visual_type = XINE_VISUAL_TYPE_FB,
1317 };
1318 #endif
1319
1320 /*
1321 * exported plugin catalog entry
1322 */
1323
1324 const plugin_info_t xine_plugin_info[] EXPORTED = {
1325 /* type, API, "name", version, special_info, init_function */
1326 #ifdef HAVE_X11
1327 { PLUGIN_VIDEO_OUT, 22, "vidix", XINE_VERSION_CODE, &vo_info_vidix, vidix_init_class },
1328 #endif
1329 #ifdef HAVE_FB
1330 { PLUGIN_VIDEO_OUT, 22, "vidixfb", XINE_VERSION_CODE, &vo_info_vidixfb, vidixfb_init_class },
1331 #endif
1332 { PLUGIN_NONE, 0, NULL, 0, NULL, NULL }
1333 };
1334