2
* Copyright (C) 2002, 2003 Billy Biggs <vektor@dumbterm.net>.
4
* Helped by XTest code from xine, a free video player,
5
* Copyright (C) 2000-2003 the xine project
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2, or (at your option)
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software Foundation,
19
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37
#include <X11/extensions/XShm.h>
38
#include <X11/extensions/Xv.h>
39
#include <X11/extensions/Xvlib.h>
43
#define FOURCC_YUY2 0x32595559
45
static Display *display;
46
static Window output_window;
48
static XvImage *image;
49
static uint8_t *image_data;
50
static XShmSegmentInfo shminfo;
51
static XvPortID xv_port;
53
static int input_width, input_height;
54
static int xvoutput_verbose;
55
static int xvoutput_error = 0;
57
static int HandleXError( Display *display, XErrorEvent *xevent )
61
if( xevent->error_code == BadAlloc ) {
63
" Cannot allocate enough off-screen video memory. This may be fixed by:\n"
65
" 1. Closing or restarting large X applications.\n"
66
" 2. Lowering the input width of tvtime (--inputwidth parameter).\n"
67
" 3. Lowering your colour depth or highest configured resolution.\n"
68
" 4. Increasing the amount of video memory in your X config file\n"
69
" (for example, if you are using the i810 XFree86 driver.)\n"
71
" See http://tvtime.net/ for more information.\n\n" );
74
XGetErrorText( display, xevent->error_code, str, 1024 );
75
fprintf( stderr, "xvoutput: Received X error: %s\n", str );
81
static void x11_InstallXErrorHandler( void )
83
XSetErrorHandler( HandleXError );
87
static int xv_port_has_yuy2( XvPortID port )
89
XvImageFormatValues *formatValues;
93
formatValues = XvListImageFormats( display, port, &formats );
94
for( i = 0; i < formats; i++ ) {
95
if((formatValues[ i ].id == FOURCC_YUY2) && (!(strcmp( formatValues[ i ].guid, "YUY2" )))) {
100
XFree( formatValues );
104
static int xv_check_extension( void )
106
unsigned int version;
107
unsigned int release;
109
unsigned int adaptors;
113
XvAdaptorInfo *adaptorInfo;
115
if( ( XvQueryExtension( display, &version, &release,
116
&dummy, &dummy, &dummy) != Success ) ||
117
( version < 2 ) || ( ( version == 2 ) && ( release < 2 ) ) ) {
119
fprintf( stderr, "xvoutput: XVIDEO extension not found: X too old? didn't load extmod?\n" );
123
XvQueryAdaptors( display, output_window, &adaptors, &adaptorInfo );
125
for( i = 0; i < adaptors; i++ ) {
126
if( adaptorInfo[ i ].type & XvImageMask ) {
127
for( j = 0; j < adaptorInfo[ i ].num_ports; j++ ) {
128
if( xv_port_has_yuy2( adaptorInfo[ i ].base_id + j ) ) {
129
if( XvGrabPort( display, adaptorInfo[ i ].base_id + j, 0 ) == Success ) {
130
xv_port = adaptorInfo[ i ].base_id + j;
131
if( xvoutput_verbose ) {
132
fprintf( stderr, "xvoutput: Using XVIDEO adaptor %lu: %s.\n",
133
adaptorInfo[ i ].base_id + j, adaptorInfo[ i ].name );
135
XvFreeAdaptorInfo( adaptorInfo );
144
XvFreeAdaptorInfo( adaptorInfo );
147
fprintf( stderr, "xvoutput: No YUY2 XVIDEO port available.\n" );
149
fprintf( stderr, "\n*** tvtime requires a hardware YUY2 overlay. One is supported\n"
150
"*** by your driver, but we could not grab it. It is likely\n"
151
"*** being used by another application, either another tvtime\n"
152
"*** instance or a media player. Please shut down this other\n"
153
"*** application and try tvtime again.\n\n" );
155
fprintf( stderr, "xvoutput: No XVIDEO port found which supports YUY2 images.\n" );
157
fprintf( stderr, "\n*** tvtime requires hardware YUY2 overlay support from your video card\n"
158
"*** driver. If you are using an older NVIDIA card (TNT2), then\n"
159
"*** this capability is only available with their binary drivers.\n"
160
"*** For some ATI cards, this feature may be found in the experimental\n"
161
"*** GATOS drivers: http://gatos.souceforge.net/\n"
162
"*** If unsure, please check with your distribution to see if your\n"
163
"*** X driver supports hardware overlay surfaces.\n\n" );
168
static void *create_shm( int size )
170
struct shmid_ds shm_info;
177
if( ( XShmQueryVersion( display, &major, &minor, &pixmaps) == 0 ) ||
178
(major < 1) || ((major == 1) && (minor < 1))) {
179
fprintf( stderr, "xvoutput: No xshm extension available.\n" );
183
maxid = shmctl( 0, SHM_INFO, &shm_info );
185
fprintf( stderr, "\n"
186
" Your kernel has been compiled without support for shared\n"
187
" memory. Please fix this in your kernel before running\n"
192
shminfo.shmid = shmget( IPC_PRIVATE, size, IPC_CREAT | 0777 );
193
if( shminfo.shmid != -1 ) {
194
shminfo.shmaddr = (char *) shmat( shminfo.shmid, 0, 0 );
195
if( shminfo.shmaddr != (char *)-1 ) {
198
* XShmAttach fails on remote displays, so we have to catch
202
XSync( display, False );
203
x11_InstallXErrorHandler();
205
shminfo.readOnly = True;
206
if( XShmAttach( display, &shminfo ) ) {
209
fprintf( stderr, "xvoutput: tvtime cannot run on a remote X server.\n" );
212
XSync( display, False );
215
* We immediately delete the shared memory segment to ensure
216
* that we clean up after crashes.
218
shmctl( shminfo.shmid, IPC_RMID, 0 );
221
fprintf( stderr, "xvoutput: Out of memory.\n" );
227
return shminfo.shmaddr;
231
static int xv_alloc_frame( void )
236
size = input_width * input_height * 2;
237
alloc = create_shm( size );
239
/* Initialize the input image to black. */
240
blit_colour_packed422_scanline( alloc, input_width * input_height,
242
image = XvShmCreateImage( display, xv_port, FOURCC_YUY2, (char *) alloc,
243
input_width, input_height, &shminfo );
251
static int get_colourkey( void )
258
attr = XvQueryPortAttributes( display, xv_port, &nattr );
263
for( k = 0; k < nattr; k++ ) {
264
if( (attr[ k ].flags & XvSettable) && (attr[ k ].flags & XvGettable)) {
265
if( !strcmp( attr[ k ].name, "XV_COLORKEY" ) ) {
266
atom = XInternAtom( display, "XV_COLORKEY", False );
268
XvGetPortAttribute( display, xv_port, atom, &value );
269
XvSetPortAttribute( display, xv_port, atom, value );
270
XvGetPortAttribute( display, xv_port, atom, &value );
283
static int xv_init( int outputheight, int aspect, int verbose )
285
xvoutput_verbose = verbose;
287
if( !xcommon_open_display( aspect, outputheight, verbose ) ) {
290
display = xcommon_get_display();
291
output_window = xcommon_get_output_window();
293
if( !xv_check_extension() ) return 0;
294
xcommon_set_colourkey( get_colourkey() );
298
static int xv_show_frame( int x, int y, int width, int height )
300
area_t video_area = xcommon_get_video_area();
305
scale_area.width = width;
306
scale_area.height = height;
308
xcommon_set_video_scale( scale_area );
310
xcommon_ping_screensaver();
311
XvShmPutImage( display, xv_port, output_window, xcommon_get_gc(), image,
313
video_area.x, video_area.y,
314
video_area.width, video_area.height, False );
315
xcommon_frame_drawn();
316
XSync( display, False );
317
if( xvoutput_error ) return 0;
321
static int xv_set_input_size( int inputwidth, int inputheight )
323
input_width = inputwidth;
324
input_height = inputheight;
326
if( !xv_alloc_frame() ) {
330
xv_show_frame( 0, 0, input_width, input_height );
331
xcommon_clear_screen();
335
static void xv_quit( void )
337
XShmDetach( display, &shminfo );
338
shmdt( shminfo.shmaddr );
339
xcommon_close_display();
342
static int xv_get_stride( void )
344
return image->pitches[ 0 ];
347
static int xv_is_interlaced( void )
352
static void xv_wait_for_sync( int field )
356
static void xv_lock_output( void )
360
static void xv_unlock_output( void )
364
static uint8_t *xv_get_output( void )
369
static int xv_can_read_from_buffer( void )
374
static int xv_is_overscan_supported( void )
379
static output_api_t xvoutput =
388
xv_can_read_from_buffer,
392
xcommon_get_visible_width,
393
xcommon_get_visible_height,
394
xcommon_is_fullscreen,
395
xcommon_is_alwaysontop,
397
xcommon_is_fullscreen_supported,
398
xcommon_is_alwaysontop_supported,
399
xv_is_overscan_supported,
405
xcommon_toggle_aspect,
406
xcommon_toggle_alwaysontop,
407
xcommon_toggle_fullscreen,
408
xcommon_resize_window_fullscreen,
409
xcommon_set_window_caption,
411
xcommon_set_window_position,
412
xcommon_set_window_height,
413
xcommon_set_fullscreen_position,
420
output_api_t *get_xv_output( void )
427
output_api_t *get_xv_output( void )