diff options
Diffstat (limited to 'src/video_out')
31 files changed, 1455 insertions, 492 deletions
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index d447417c5..3e182fc14 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CPPFLAGS = -DXINE_COMPILE @@ -100,6 +101,7 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \ $(xxmc_module) \ $(xcbshm_module) \ $(xcbxv_module) \ + xineplug_vo_out_raw.la \ xineplug_vo_out_none.la xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD) @@ -130,11 +132,11 @@ xineplug_vo_out_xxmc_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(XV_CFLAGS) -fn xineplug_vo_out_opengl_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ video_out_opengl.c myglext.h $(X11OSD) -xineplug_vo_out_opengl_la_LIBADD = $(MLIB_LIBS) $(OPENGL_LIBS) $(GLUT_LIBS) \ - $(GLU_LIBS) $(X_LIBS) $(XINE_LIB) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) +xineplug_vo_out_opengl_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(OPENGL_LIBS) \ + $(GLUT_LIBS) $(GLU_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) xineplug_vo_out_opengl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(MLIB_CFLAGS) -fno-strict-aliasing -xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c +xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c xineplug_vo_out_syncfb_la_LIBADD = $(XINE_LIB) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_syncfb_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) @@ -177,28 +179,32 @@ xineplug_vo_out_sdl_la_SOURCES = video_out_sdl.c xineplug_vo_out_sdl_la_LIBADD = $(XINE_LIB) $(SDL_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_sdl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(SDL_CFLAGS) -xineplug_vo_out_stk_la_SOURCES = video_out_stk.c +xineplug_vo_out_stk_la_SOURCES = video_out_stk.c xineplug_vo_out_stk_la_LIBADD = $(XINE_LIB) $(LIBSTK_LIBS) $(PTHREAD_LIBS) xineplug_vo_out_stk_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBSTK_CFLAGS) -xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c +xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c xineplug_vo_out_directx_la_CPPFLAGS = $(AM_CPPFLAGS) $(DIRECTX_CPPFLAGS) -xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) +xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_vo_out_none_la_SOURCES = video_out_none.c xineplug_vo_out_none_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_none_la_CFLAGS = $(VISIBILITY_FLAG) +xineplug_vo_out_raw_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_raw.c +xineplug_vo_out_raw_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_raw_la_CFLAGS = $(VISIBILITY_FLAG) + xineplug_vo_out_macosx_la_SOURCES = video_out_macosx.m xineplug_vo_out_macosx_la_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(MLIB_CFLAGS) xineplug_vo_out_macosx_la_OBJCFLAGS = $(VISIBILITY_FLAG) -xineplug_vo_out_macosx_la_LIBADD = $(MLIB_LIBS) $(OPENGL_LIBS) $(GLUT_LIBS) \ - $(GLU_LIBS) $(X_LIBS) $(XINE_LIB) $(PTHREAD_LIBS) +xineplug_vo_out_macosx_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(OPENGL_LIBS) \ + $(GLUT_LIBS) $(GLU_LIBS) $(X_LIBS) $(PTHREAD_LIBS) # The "-Wl,-framework -Wl,Cocoa" is needed for libtool versions before # 1.5.x (1.257): the default version that ships with Mac OS X is 1.5 (1.1220) xineplug_vo_out_macosx_la_LDFLAGS = $(AM_LDFLAGS) \ -Wl,-framework -Wl,Cocoa -framework Cocoa -framework OpenGL noinst_HEADERS = deinterlace.h video_out_syncfb.h \ - yuv2rgb.h x11osd.h xcbosd.h + yuv2rgb.h x11osd.h xcbosd.h xv_common.h diff --git a/src/video_out/deinterlace.c b/src/video_out/deinterlace.c index 8ba161ebb..712e9a83e 100644 --- a/src/video_out/deinterlace.c +++ b/src/video_out/deinterlace.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -30,6 +30,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include "xine_internal.h" @@ -37,6 +41,18 @@ #include "xineutils.h" +const char *deinterlace_methods[] = { + "none", + "bob", + "weave", + "greedy", + "onefield", + "onefield_xv", + "linearblend", + NULL +}; + + /* DeinterlaceFieldBob algorithm Based on Virtual Dub plugin by Gunnar Thalin diff --git a/src/video_out/deinterlace.h b/src/video_out/deinterlace.h index 2ebbf53d9..d7712f581 100644 --- a/src/video_out/deinterlace.h +++ b/src/video_out/deinterlace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -41,15 +41,6 @@ void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[], #define DEINTERLACE_ONEFIELDXV 5 #define DEINTERLACE_LINEARBLEND 6 -static const char *deinterlace_methods[] = { - "none", - "bob", - "weave", - "greedy", - "onefield", - "onefield_xv", - "linearblend", - NULL -}; +extern const char *deinterlace_methods[]; #endif diff --git a/src/video_out/macosx/XineOpenGLView.m b/src/video_out/macosx/XineOpenGLView.m index a9ffee00f..1f947ca16 100644 --- a/src/video_out/macosx/XineOpenGLView.m +++ b/src/video_out/macosx/XineOpenGLView.m @@ -340,7 +340,7 @@ NSColorToYUV(NSColor *color) // http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, videoSize.width, videoSize.height, GL_YCBCR_422_APPLE, -#if WORDS_BIG_ENDIAN +#if WORDS_BIGENDIAN GL_UNSIGNED_SHORT_8_8_APPLE, #else GL_UNSIGNED_SHORT_8_8_REV_APPLE, diff --git a/src/video_out/video_out_aa.c b/src/video_out/video_out_aa.c index 012db9665..770b75a10 100644 --- a/src/video_out/video_out_aa.c +++ b/src/video_out/video_out_aa.c @@ -106,7 +106,7 @@ static vo_frame_t *aa_alloc_frame(vo_driver_t *this_gen) { /* aa_driver_t *this = (aa_driver_t*) this_gen; */ aa_frame_t *frame; - frame = (aa_frame_t *) xine_xmalloc (sizeof (aa_frame_t)); + frame = calloc(1, sizeof (aa_frame_t)); if (!frame) return NULL; @@ -276,7 +276,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi aa_class_t *class = (aa_class_t *) class_gen; aa_driver_t *this; - this = (aa_driver_t*) xine_xmalloc (sizeof (aa_driver_t)); + this = (aa_driver_t*) calloc(1, sizeof(aa_driver_t)); this->context = (aa_context*) visual_gen; @@ -316,7 +316,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { /* aa_context *context = (aa_context*) visual_gen; */ aa_class_t *this; - this = (aa_class_t *) xine_xmalloc(sizeof(aa_class_t)); + this = calloc(1, sizeof(aa_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_caca.c b/src/video_out/video_out_caca.c index 866eabcd8..65ebf707e 100644 --- a/src/video_out/video_out_caca.c +++ b/src/video_out/video_out_caca.c @@ -120,7 +120,7 @@ static vo_frame_t *caca_alloc_frame(vo_driver_t *this_gen) { caca_driver_t *this = (caca_driver_t*) this_gen; caca_frame_t *frame; - frame = (caca_frame_t *) xine_xmalloc (sizeof (caca_frame_t)); + frame = calloc(1, sizeof (caca_frame_t)); if (!frame) return NULL; @@ -276,9 +276,10 @@ static int caca_redraw_needed (vo_driver_t *this_gen) { static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { caca_class_t *class = (caca_class_t *) class_gen; + caca_display_t *dp = (caca_display_t *)visual_gen; caca_driver_t *this; - this = (caca_driver_t*) xine_xmalloc (sizeof (caca_driver_t)); + this = calloc(1, sizeof (caca_driver_t)); this->config = class->config; this->xine = class->xine; @@ -300,8 +301,13 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->yuv2rgb_factory = yuv2rgb_factory_init(MODE_32_RGB, 0, NULL); this->yuv2rgb_factory->set_csc_levels(this->yuv2rgb_factory, 0, 128, 128); - this->cv = cucul_create_canvas(0, 0); - this->dp = caca_create_display(this->cv); + if (dp) { + this->cv = caca_get_canvas(dp); + this->dp = dp; + } else { + this->cv = cucul_create_canvas(0, 0); + this->dp = caca_create_display(this->cv); + } caca_refresh_display(this->dp); return &this->vo_driver; @@ -322,7 +328,7 @@ static void dispose_class (video_driver_class_t *this_gen) { static void *init_class (xine_t *xine, void *visual_gen) { caca_class_t *this; - this = (caca_class_t *) xine_xmalloc(sizeof(caca_class_t)); + this = calloc(1, sizeof(caca_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_directfb.c b/src/video_out/video_out_directfb.c index e6e333a0c..2e9874cc0 100644 --- a/src/video_out/video_out_directfb.c +++ b/src/video_out/video_out_directfb.c @@ -168,10 +168,6 @@ typedef struct { "no-deinit-check" -#ifndef MAX -# define MAX( a, b ) (((a) > (b)) ? (a) : (b)) -#endif - #define YCBCR_TO_RGB( y, cb, cr, r, g, b ) \ do { \ int _y, _cb, _cr, _r, _g, _b; \ @@ -232,7 +228,7 @@ static vo_frame_t *directfb_alloc_frame (vo_driver_t *this_gen) { directfb_driver_t *this = (directfb_driver_t *) this_gen; directfb_frame_t *frame; - frame = (directfb_frame_t *) xine_xmalloc (sizeof (directfb_frame_t)); + frame = (directfb_frame_t *) calloc(1, sizeof(directfb_frame_t)); if (!frame) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_directfb: directfb_alloc_frame: out of memory\n"); @@ -1753,7 +1749,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void DFBDisplayLayerID id; DFBResult ret; - this = xine_xmalloc (sizeof (directfb_driver_t)); + this = calloc(1, sizeof(directfb_driver_t)); if (!this) return NULL; @@ -1908,7 +1904,7 @@ static void *init_class_fb (xine_t *xine, void *visual_gen) { return NULL; } - this = (directfb_class_t *) xine_xmalloc (sizeof (directfb_class_t)); + this = (directfb_class_t *) calloc(1, sizeof(directfb_class_t)); this->driver_class.open_plugin = open_plugin_fb; this->driver_class.get_identifier = get_identifier_fb; this->driver_class.get_description = get_description_fb; @@ -1939,7 +1935,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void DFBDisplayLayerID id = DLID_PRIMARY; DFBResult ret; - this = xine_xmalloc (sizeof (directfb_driver_t)); + this = calloc(1, sizeof(directfb_driver_t)); if (!this) return NULL; @@ -2127,7 +2123,7 @@ static void *init_class_x11 (xine_t *xine, void *visual_gen) { if (strcmp (XServerVendor (visual->display), "Denis Oliver Kropp")) return NULL; - this = (directfb_class_t *) xine_xmalloc (sizeof (directfb_class_t)); + this = (directfb_class_t *) calloc(1, sizeof(directfb_class_t)); this->driver_class.open_plugin = open_plugin_x11; this->driver_class.get_identifier = get_identifier_x11; this->driver_class.get_description = get_description_x11; diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c index 11ee709e1..3c6f6e784 100644 --- a/src/video_out/video_out_directx.c +++ b/src/video_out/video_out_directx.c @@ -21,6 +21,10 @@ * by Matthew Grooms <elon@altavista.com> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + typedef unsigned char boolean; #include <windows.h> @@ -55,21 +59,33 @@ typedef unsigned char boolean; * the linking stage. *****************************************************************************/ #if 1 -static const GUID IID_IDirectDraw = { +static const GUID xine_IID_IDirectDraw = { 0x6C14DB80,0xA733,0x11CE,{0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60} }; +#ifdef IID_IDirectDraw +# undef IID_IDirectDraw +#endif +#define IID_IDirectDraw xine_IID_IDirectDraw #endif #if 0 static const GUID IID_IDirectDraw2 = { 0xB3A6F3E0,0x2B43,0x11CF,{0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56} }; +#ifdef IID_IDirectDraw2 +# undef IID_IDirectDraw2 +#endif +#define IID_IDirectDraw2 xine_IID_IDirectDraw2 #endif #if 0 static const GUID IID_IDirectDraw4 = { 0x9C59509A,0x39BD,0x11D1,{0x8C,0x4A,0x00,0xC0,0x4F,0xD9,0x30,0xC5} }; +#ifdef IID_IDirectDraw4 +# undef IID_IDirectDraw4 +#endif +#define IID_IDirectDraw4 xine_IID_IDirectDraw4 #endif /* ----------------------------------------- @@ -117,7 +133,8 @@ typedef struct { yuv2rgb_t *yuv2rgb; /* used for format conversion */ int mode; /* rgb mode */ int bytespp; /* rgb bits per pixel */ - + DDPIXELFORMAT primary_pixel_format; + DDSURFACEDESC ddsd; /* set by Lock(), used during display_frame */ alphablend_t alphablend_extra_data; } win32_driver_t; @@ -367,8 +384,9 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he lprintf("CreateSecondary() - Falling back to back buffer same as primary\n"); lprintf("CreateSecondary() - act_format = (NATIVE) %d\n", IMGFMT_NATIVE); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.ddpfPixelFormat = win32_driver->primary_pixel_format; win32_driver->act_format = IMGFMT_NATIVE; if( IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK ) @@ -429,6 +447,10 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver ) Error( 0, "IDirectDrawSurface_GetPixelFormat ( CheckPixelFormat ) : error 0x%lx", result ); return 0; } + + /* store pixel format for CreateSecondary */ + + win32_driver->primary_pixel_format = ddpf; /* TODO : support paletized video modes */ @@ -478,9 +500,11 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver ) win32_driver->mode = MODE_15_BGR; } + lprintf("win32 mode: %u\n", win32_driver->mode); return TRUE; } +#if 0 /* Create a Direct draw surface from * a bitmap resource.. * @@ -546,6 +570,7 @@ static LPDIRECTDRAWSURFACE CreateBMP( win32_driver_t * win32_driver, int resourc return bmp_surf; } +#endif /* Merge overlay with the current primary * surface. This funtion is only used when @@ -755,23 +780,22 @@ static boolean DisplayFrame( win32_driver_t * win32_driver ) /* Lock our back buffer to update its contents. */ -static void * Lock( void * surface ) +static void * Lock( win32_driver_t * win32_driver, void * surface ) { LPDIRECTDRAWSURFACE lock_surface = ( LPDIRECTDRAWSURFACE ) surface; - DDSURFACEDESC ddsd; HRESULT result; if( !surface ) return 0; - memset( &ddsd, 0, sizeof( ddsd ) ); - ddsd.dwSize = sizeof( ddsd ); + memset( &win32_driver->ddsd, 0, sizeof( win32_driver->ddsd ) ); + win32_driver->ddsd.dwSize = sizeof( win32_driver->ddsd ); - result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); + result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); if( result == DDERR_SURFACELOST ) { IDirectDrawSurface_Restore( lock_surface ); - result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); + result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); if( result != DD_OK ) return 0; @@ -786,7 +810,7 @@ static void * Lock( void * surface ) } } - return ddsd.lpSurface; + return win32_driver->ddsd.lpSurface; } /* Unlock our back buffer to prepair for display. */ @@ -863,7 +887,7 @@ static vo_frame_t * win32_alloc_frame( vo_driver_t * vo_driver ) { win32_frame_t *win32_frame; - win32_frame = ( win32_frame_t * ) xine_xmalloc( sizeof( win32_frame_t ) ); + win32_frame = calloc(1, sizeof(win32_frame_t)); if (!win32_frame) return NULL; @@ -946,8 +970,6 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame { win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver; win32_frame_t *win32_frame = ( win32_frame_t * ) vo_frame; - int offset; - int size; /* if the required width, height or format has changed @@ -966,7 +988,7 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame /* lock our surface to update its contents */ - win32_driver->contents = Lock( win32_driver->secondary ); + win32_driver->contents = Lock( win32_driver, win32_driver->secondary ); /* surface unavailable, skip frame render */ @@ -1051,37 +1073,47 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame /* the actual format is identical to our * stream format. we just need to copy it */ - switch(win32_frame->format) + int line; + uint8_t * src; + vo_frame_t * frame = vo_frame; + uint8_t * dst = (uint8_t *)win32_driver->contents; + + switch(win32_frame->format) { - case XINE_IMGFMT_YV12: - { - vo_frame_t *frame; - uint8_t *img; - - frame = vo_frame; - img = (uint8_t *)win32_driver->contents; - - offset = 0; - size = frame->pitches[0] * frame->height; - xine_fast_memcpy( img+offset, frame->base[0], size); - - offset += size; - size = frame->pitches[2]* frame->height / 2; - xine_fast_memcpy( img+offset, frame->base[2], size); - - offset += size; - size = frame->pitches[1] * frame->height / 2; - xine_fast_memcpy( img+offset, frame->base[1], size); - } + case XINE_IMGFMT_YV12: + src = frame->base[0]; + for (line = 0; line < frame->height ; line++){ + xine_fast_memcpy( dst, src, frame->width); + src += vo_frame->pitches[0]; + dst += win32_driver->ddsd.lPitch; + } + + src = frame->base[2]; + for (line = 0; line < frame->height/2 ; line++){ + xine_fast_memcpy( dst, src, frame->width/2); + src += vo_frame->pitches[2]; + dst += win32_driver->ddsd.lPitch/2; + } + + src = frame->base[1]; + for (line = 0; line < frame->height/2 ; line++){ + xine_fast_memcpy( dst, src, frame->width/2); + src += vo_frame->pitches[1]; + dst += win32_driver->ddsd.lPitch/2; + } break; + case XINE_IMGFMT_YUY2: - xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2); - break; default: - xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2); + src = frame->base[0]; + for (line = 0; line < frame->height ; line++){ + xine_fast_memcpy( dst, src, frame->width*2); + src += vo_frame->pitches[0]; + dst += win32_driver->ddsd.lPitch; + } break; } - } + } /* unlock the surface */ @@ -1143,11 +1175,38 @@ static int win32_gui_data_exchange( vo_driver_t * vo_driver, int data_type, void switch( data_type ) { + case GUI_WIN32_MOVED_OR_RESIZED: UpdateRect( win32_driver->win32_visual ); DisplayFrame( win32_driver ); break; + case XINE_GUI_SEND_DRAWABLE_CHANGED: + { + HRESULT result; + HWND newWndHnd = (HWND) data; + + /* set cooperative level */ + result = IDirectDraw_SetCooperativeLevel( win32_driver->ddobj, newWndHnd, DDSCL_NORMAL ); + if( result != DD_OK ) + { + Error( 0, "SetCooperativeLevel : error 0x%lx", result ); + return 0; + } + /* associate our clipper with new window */ + result = IDirectDrawClipper_SetHWnd( win32_driver->ddclipper, 0, newWndHnd ); + if( result != DD_OK ) + { + Error( 0, "ddclipper->SetHWnd : error 0x%lx", result ); + return 0; + } + /* store our objects in our visual struct */ + win32_driver->win32_visual->WndHnd = newWndHnd; + /* update video area and redraw current frame */ + UpdateRect( win32_driver->win32_visual ); + DisplayFrame( win32_driver ); + break; } + } return 0; } @@ -1183,7 +1242,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *wi /*vo_driver_t *init_video_out_plugin( config_values_t * config, void * win32_visual )*/ { directx_class_t *class = (directx_class_t *)class_gen; - win32_driver_t *win32_driver = ( win32_driver_t * ) xine_xmalloc ( sizeof( win32_driver_t ) ); + win32_driver_t *win32_driver = calloc(1, sizeof(win32_driver_t)); _x_alphablend_init(&win32_driver->alphablend_extra_data, class->xine); @@ -1249,7 +1308,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { /* * from this point on, nothing should go wrong anymore */ - directx = (directx_class_t *) xine_xmalloc (sizeof (directx_class_t)); + directx = calloc(1, sizeof (directx_class_t)); directx->driver_class.open_plugin = open_plugin; directx->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_fb.c b/src/video_out/video_out_fb.c index 95060a4d8..d67b0870d 100644 --- a/src/video_out/video_out_fb.c +++ b/src/video_out/video_out_fb.c @@ -221,7 +221,7 @@ static vo_frame_t *fb_alloc_frame(vo_driver_t *this_gen) this->total_num_native_buffers <= this->used_num_buffers) return 0; - frame = (fb_frame_t *)xine_xmalloc(sizeof(fb_frame_t)); + frame = calloc(1, sizeof(fb_frame_t)); if(!frame) return NULL; @@ -324,21 +324,10 @@ static void setup_colorspace_converter(fb_frame_t *frame, int flags) static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, uint32_t width, uint32_t height, int format) { - if(frame->chunk[0]) - { - free(frame->chunk[0]); - frame->chunk[0] = NULL; - } - if(frame->chunk[1]) - { - free(frame->chunk[1]); - frame->chunk[1] = NULL; - } - if(frame->chunk[2]) - { - free(frame->chunk[2]); - frame->chunk[2] = NULL; - } + free(frame->chunk[0]); + free(frame->chunk[1]); + free(frame->chunk[2]); + memset(frame->chunk, 0, sizeof(frame->chunk[0])*3); if(this->use_zero_copy) { @@ -348,10 +337,9 @@ static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, } else { - if(frame->data) - free(frame->data); - frame->data = xine_xmalloc(frame->sc.output_width * - frame->sc.output_height * + free(frame->data); + frame->data = calloc(frame->sc.output_width * + frame->sc.output_height, this->bytes_per_pixel); } @@ -1004,7 +992,7 @@ static vo_driver_t *fb_open_plugin(video_driver_class_t *class_gen, config = class->config; /* allocate plugin struct */ - this = (fb_driver_t *) xine_xmalloc(sizeof(fb_driver_t)); + this = calloc(1, sizeof(fb_driver_t)); if(!this) return NULL; @@ -1087,7 +1075,7 @@ static void fb_dispose_class(video_driver_class_t *this_gen) static void *fb_init_class(xine_t *xine, void *visual_gen) { - fb_class_t *this = (fb_class_t *)xine_xmalloc(sizeof(fb_class_t)); + fb_class_t *this = calloc(1, sizeof(fb_class_t)); this->driver_class.open_plugin = fb_open_plugin; this->driver_class.get_identifier = fb_get_identifier; diff --git a/src/video_out/video_out_macosx.m b/src/video_out/video_out_macosx.m index 4621d31b9..b5b4d731c 100644 --- a/src/video_out/video_out_macosx.m +++ b/src/video_out/video_out_macosx.m @@ -97,7 +97,7 @@ static vo_frame_t *macosx_alloc_frame(vo_driver_t *vo_driver) { /* macosx_driver_t *this = (macosx_driver_t *) vo_driver; */ macosx_frame_t *frame; - frame = (macosx_frame_t *) xine_xmalloc(sizeof(macosx_frame_t)); + frame = calloc(1, sizeof(macosx_frame_t)); if(!frame) return NULL; @@ -207,7 +207,7 @@ static void macosx_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) { break; case XINE_IMGFMT_YUY2: xine_fast_memcpy (texture_buffer, vo_frame->base[0], - vo_frame->pitches[0] * vo_frame->height * 2); + vo_frame->pitches[0] * vo_frame->height); [driver->view updateTexture]; break; default: @@ -320,7 +320,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void * macosx_driver_t *driver; XineOpenGLView *view = (XineOpenGLView *) visual; - driver = (macosx_driver_t *) xine_xmalloc(sizeof(macosx_driver_t)); + driver = calloc(1, sizeof(macosx_driver_t)); driver->config = class->config; driver->xine = class->xine; @@ -366,7 +366,7 @@ static void dispose_class (video_driver_class_t *driver_class) { static void *init_class (xine_t *xine, void *visual) { macosx_class_t *this; - this = (macosx_class_t *) xine_xmalloc(sizeof(macosx_class_t)); + this = calloc(1, sizeof(macosx_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_none.c b/src/video_out/video_out_none.c index 5f2424a60..0de6e34e8 100644 --- a/src/video_out/video_out_none.c +++ b/src/video_out/video_out_none.c @@ -88,7 +88,7 @@ static vo_frame_t *none_alloc_frame(vo_driver_t *vo_driver) { /* none_driver_t *this = (none_driver_t *) vo_driver; */ none_frame_t *frame; - frame = (none_frame_t *) xine_xmalloc(sizeof(none_frame_t)); + frame = calloc(1, sizeof(none_frame_t)); if(!frame) return NULL; @@ -243,7 +243,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void * none_class_t *class = (none_class_t *) driver_class; none_driver_t *driver; - driver = (none_driver_t *) xine_xmalloc(sizeof(none_driver_t)); + driver = calloc(1, sizeof(none_driver_t)); driver->config = class->config; driver->xine = class->xine; @@ -286,7 +286,7 @@ static void dispose_class (video_driver_class_t *driver_class) { static void *init_class (xine_t *xine, void *visual) { none_class_t *this; - this = (none_class_t *) xine_xmalloc(sizeof(none_class_t)); + this = calloc(1, sizeof(none_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_opengl.c b/src/video_out/video_out_opengl.c index 54696f452..a8f11db2f 100644 --- a/src/video_out/video_out_opengl.c +++ b/src/video_out/video_out_opengl.c @@ -669,8 +669,8 @@ static int render_image_envtex (opengl_driver_t *this, opengl_frame_t *frame) { * Render setup functions */ static int render_help_verify_ext (opengl_driver_t *this, char *ext) { - int ret = 0; - int l = strlen (ext); + int ret = 0; + const size_t l = strlen (ext); const char *e; for (e = (char *) this->gl_exts; e && *e; e = strchr (e, ' ')) { while (isspace (*e)) @@ -694,10 +694,9 @@ static void *getdladdr (const GLubyte *_funcName) { return NULL; #elif defined(__APPLE__) - char *temp = xine_xmalloc (strlen (funcName) + 2); + char *temp; + asprintf(&temp, "_%s", funcName); void *res = NULL; - temp[0] = '_'; /* Mac OS X prepends an underscore on function names */ - strcpy (temp+1, funcName); if (NSIsSymbolNameDefined (temp)) { NSSymbol symbol = NSLookupAndBindSymbol (temp); res = NSAddressOfSymbol (symbol); @@ -1281,7 +1280,7 @@ static vo_frame_t *opengl_alloc_frame (vo_driver_t *this_gen) { opengl_frame_t *frame; opengl_driver_t *this = (opengl_driver_t *) this_gen; - frame = (opengl_frame_t *) xine_xmalloc (sizeof (opengl_frame_t)); + frame = (opengl_frame_t *) calloc(1, sizeof(opengl_frame_t)); if (!frame) return NULL; @@ -1820,7 +1819,7 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v char **render_fun_names; int i; - this = (opengl_driver_t *) xine_xmalloc (sizeof (opengl_driver_t)); + this = (opengl_driver_t *) calloc(1, sizeof(opengl_driver_t)); if (!this) return NULL; @@ -1876,8 +1875,7 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v this->drawable, X11OSD_SHAPED); XUnlockDisplay (this->display); - render_fun_names = xine_xmalloc ((sizeof(opengl_rb)/sizeof(opengl_render_t)+1) - * sizeof (const char *)); + render_fun_names = calloc((sizeof(opengl_rb)/sizeof(opengl_render_t)+1), sizeof(const char*)); for (i = 0; i < sizeof (opengl_rb) / sizeof (opengl_render_t); i++) render_fun_names[i] = opengl_rb[i].name; render_fun_names[i] = NULL; @@ -1955,6 +1953,52 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v * class functions */ +static int opengl_verify_direct (x11_visual_t *vis) { + int attribs[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None + }; + Window root, win; + XVisualInfo *visinfo; + GLXContext ctx; + XSetWindowAttributes xattr; + int ret = 0; + + if (!vis || !vis->display || + ! (root = RootWindow (vis->display, vis->screen))) { + fprintf (stderr, "[videoout_opengl]: Don't have a root window to verify\n"); + return 0; + } + if (! (visinfo = glXChooseVisual (vis->display, vis->screen, attribs))) + return 0; + if (! (ctx = glXCreateContext (vis->display, visinfo, NULL, 1))) + return 0; + memset (&xattr, 0, sizeof (xattr)); + xattr.colormap = XCreateColormap(vis->display, root, visinfo->visual, AllocNone); + xattr.event_mask = StructureNotifyMask | ExposureMask; + if ( (win = XCreateWindow (vis->display, root, 0, 0, 1, 1, 0, visinfo->depth, + InputOutput, visinfo->visual, + CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, + &xattr))) { + if (glXMakeCurrent (vis->display, win, ctx)) { + const char *renderer = (const char *) glGetString(GL_RENDERER); + if (glXIsDirect (vis->display, ctx) && + ! strstr (renderer, "Software") && + ! strstr (renderer, "Indirect")) + ret = 1; + glXMakeCurrent (vis->display, None, NULL); + } + XDestroyWindow (vis->display, win); + } + glXDestroyContext (vis->display, ctx); + XFreeColormap (vis->display, xattr.colormap); + + return ret; +} + static char* opengl_get_identifier (video_driver_class_t *this_gen) { return "opengl"; } @@ -1970,7 +2014,18 @@ static void opengl_dispose_class (video_driver_class_t *this_gen) { } static void *opengl_init_class (xine_t *xine, void *visual_gen) { - opengl_class_t *this = (opengl_class_t *) xine_xmalloc (sizeof (opengl_class_t)); + + opengl_class_t *this; + + xprintf (xine, XINE_VERBOSITY_LOG, + "video_out_opengl: Testing for hardware accelerated direct rendering visual\n"); + if (! opengl_verify_direct ((x11_visual_t *)visual_gen)) { + xprintf (xine, XINE_VERBOSITY_LOG, + "video_out_opengl: Didn't find any\n"); + return NULL; + } + + this = (opengl_class_t *) calloc (1, sizeof(opengl_class_t)); this->driver_class.open_plugin = opengl_open_plugin; this->driver_class.get_identifier = opengl_get_identifier; diff --git a/src/video_out/video_out_pgx32.c b/src/video_out/video_out_pgx32.c index d903efc89..45a54cc76 100644 --- a/src/video_out/video_out_pgx32.c +++ b/src/video_out/video_out_pgx32.c @@ -386,7 +386,7 @@ static vo_frame_t *pgx32_alloc_frame(vo_driver_t *this_gen) /*pgx32_driver_t *this = (pgx32_driver_t *)(void *)this_gen;*/ pgx32_frame_t *frame; - frame = (pgx32_frame_t *) xine_xmalloc(sizeof(pgx32_frame_t)); + frame = calloc(1, sizeof(pgx32_frame_t)); if (!frame) { return NULL; } @@ -800,7 +800,7 @@ static vo_driver_t *pgx32_init_driver(video_driver_class_t *class_gen, const voi pgx32_driver_class_t *class = (pgx32_driver_class_t *)(void *)class_gen; pgx32_driver_t *this; - this = (pgx32_driver_t *)xine_xmalloc(sizeof(pgx32_driver_t)); + this = calloc(1, sizeof(pgx32_driver_t)); if (!this) { return NULL; } @@ -869,7 +869,7 @@ static void *pgx32_init_class(xine_t *xine, void *visual_gen) { pgx32_driver_class_t *class; - class = (pgx32_driver_class_t *)xine_xmalloc(sizeof(pgx32_driver_class_t)); + class = calloc(1, sizeof(pgx32_driver_class_t)); if (!class) { return NULL; } diff --git a/src/video_out/video_out_pgx64.c b/src/video_out/video_out_pgx64.c index 4abb794d7..abda51e2b 100644 --- a/src/video_out/video_out_pgx64.c +++ b/src/video_out/video_out_pgx64.c @@ -561,7 +561,7 @@ static vo_frame_t *pgx64_alloc_frame(vo_driver_t *this_gen) /*pgx64_driver_t *this = (pgx64_driver_t *)(void *)this_gen;*/ pgx64_frame_t *frame; - frame = (pgx64_frame_t *) xine_xmalloc(sizeof(pgx64_frame_t)); + frame = calloc(1, sizeof(pgx64_frame_t)); if (!frame) { return NULL; } @@ -1352,7 +1352,7 @@ static vo_driver_t *pgx64_init_driver(video_driver_class_t *class_gen, const voi struct fbgattr attr; long page_size; - this = (pgx64_driver_t *)xine_xmalloc(sizeof(pgx64_driver_t)); + this = calloc(1, sizeof(pgx64_driver_t)); if (!this) { return NULL; } @@ -1493,7 +1493,7 @@ static void *pgx64_init_class(xine_t *xine, void *visual_gen) { pgx64_driver_class_t *class; - class = (pgx64_driver_class_t *)xine_xmalloc(sizeof(pgx64_driver_class_t)); + class = calloc(1, sizeof(pgx64_driver_class_t)); if (!class) { return NULL; } diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c new file mode 100644 index 000000000..99e2c0004 --- /dev/null +++ b/src/video_out/video_out_raw.c @@ -0,0 +1,610 @@ +/* + * Copyright (C) 2007-2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * + * video_out_raw.c, a video output plugin to pass raw data to frontend + * + * Written by Christophe Thommeret <hftom@free.fr>, + * based on others' video output plugins. + * + */ + +/* #define LOG */ +#define LOG_MODULE "video_out_raw" + +/* Allow frontend some time to render frames +* However, frontends are strongly advised to render synchronously */ +#define NUM_FRAMES_BACKLOG 4 +#define BYTES_PER_PIXEL 3 + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <ctype.h> +#include <pthread.h> + +#include "xine.h" +#include "video_out.h" + +#include "xine_internal.h" +#include "yuv2rgb.h" +#include "xineutils.h" + + + +typedef struct { + vo_frame_t vo_frame; + + int width, height, format, flags; + double ratio; + uint8_t *chunk[4]; /* mem alloc by xmalloc_aligned */ + uint8_t *rgb, *rgb_dst; + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ + +} raw_frame_t; + +typedef struct { + vo_driver_t vo_driver; + + void *user_data; + + void (*raw_output_cb) (void *user_data, int format, + int frame_width, int frame_height, double frame_aspect, + void *data0, void *data1, void *data2); + + void (*raw_overlay_cb) (void *user_data, int num_ovl, + raw_overlay_t *overlays_p); + + int ovl_changed; + raw_overlay_t overlays[XINE_VORAW_MAX_OVL]; + yuv2rgb_t *ovl_yuv2rgb; + + int doYV12; + int doYUY2; + yuv2rgb_factory_t *yuv2rgb_factory; + /* Frame state */ + raw_frame_t *frame[NUM_FRAMES_BACKLOG]; + xine_t *xine; +} raw_driver_t; + + +typedef struct { + video_driver_class_t driver_class; + xine_t *xine; +} raw_class_t; + + + +static void raw_overlay_clut_yuv2rgb(raw_driver_t *this, vo_overlay_t *overlay, raw_frame_t *frame) +{ + int i; + clut_t* clut = (clut_t*) overlay->color; + + if (!overlay->rgb_clut) { + for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++ ) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->rgb_clut++; + } + if (!overlay->hili_rgb_clut) { + clut = (clut_t*) overlay->hili_color; + for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->hili_rgb_clut++; + } +} + + +static int raw_process_ovl( raw_driver_t *this_gen, vo_overlay_t *overlay ) +{ + raw_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; + + if ( overlay->width<=0 || overlay->height<=0 ) + return 0; + + if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) ) + ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 ); + ovl->ovl_w = overlay->width; + ovl->ovl_h = overlay->height; + ovl->ovl_x = overlay->x; + ovl->ovl_y = overlay->y; + + int num_rle = overlay->num_rle; + rle_elem_t *rle = overlay->rle; + uint8_t *rgba = ovl->ovl_rgba; + clut_t *low_colors = (clut_t*)overlay->color; + clut_t *hili_colors = (clut_t*)overlay->hili_color; + uint8_t *low_trans = overlay->trans; + uint8_t *hili_trans = overlay->hili_trans; + clut_t *colors; + uint8_t *trans; + uint8_t alpha; + int rlelen = 0; + uint8_t clr = 0; + int i, pos=0, x, y; + + while ( num_rle>0 ) { + x = pos%ovl->ovl_w; + y = pos/ovl->ovl_w; + if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) { + colors = hili_colors; + trans = hili_trans; + } + else { + colors = low_colors; + trans = low_trans; + } + rlelen = rle->len; + clr = rle->color; + alpha = trans[clr]; + for ( i=0; i<rlelen; ++i ) { + rgba[0] = colors[clr].y; + rgba[1] = colors[clr].cr; + rgba[2] = colors[clr].cb; + rgba[3] = alpha*255/15; + rgba+= 4; + ++pos; + } + ++rle; + --num_rle; + } + return 1; +} + + +static void raw_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + + if ( !changed ) + return; + + ++this->ovl_changed; +} + + +static void raw_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + + if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL ) + return; + + if (overlay->rle) { + if (!overlay->rgb_clut || !overlay->hili_rgb_clut) + raw_overlay_clut_yuv2rgb (this, overlay, frame); + if ( raw_process_ovl( this, overlay ) ) + ++this->ovl_changed; + } +} + + +static void raw_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + + if ( !this->ovl_changed ) + return; + + this->raw_overlay_cb( this->user_data, this->ovl_changed-1, this->overlays ); + + this->ovl_changed = 0; +} + + +static void raw_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + + vo_img->proc_called = 1; + if (! frame->rgb_dst) + return; + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) + { + /* TODO: ?!? */ + return; + } + + if (frame->format == XINE_IMGFMT_YV12) + frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0], src[1], src[2]); + else + frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0]); +} + + + +static void raw_frame_field (vo_frame_t *vo_img, int which_field) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + raw_driver_t *this = (raw_driver_t *) vo_img->driver; + + if ( frame->format==XINE_IMGFMT_YV12 && this->doYV12 ) { + frame->rgb_dst = 0; + return; + } + else if ( frame->format==XINE_IMGFMT_YUY2 && this->doYUY2 ) { + frame->rgb_dst = 0; + return; + } + + switch (which_field) { + case VO_TOP_FIELD: + frame->rgb_dst = (uint8_t *)frame->rgb; + break; + case VO_BOTTOM_FIELD: + frame->rgb_dst = (uint8_t *)frame->rgb + frame->width * BYTES_PER_PIXEL; + break; + case VO_BOTH_FIELDS: + frame->rgb_dst = (uint8_t *)frame->rgb; + break; + } + + frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL); +} + + + +static void raw_frame_dispose (vo_frame_t *vo_img) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + + frame->yuv2rgb->dispose (frame->yuv2rgb); + + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame->chunk[3]); + free (frame); +} + + + +static vo_frame_t *raw_alloc_frame (vo_driver_t *this_gen) +{ + raw_frame_t *frame; + raw_driver_t *this = (raw_driver_t *) this_gen; + + frame = (raw_frame_t *) calloc(1, sizeof(raw_frame_t)); + + if (!frame) + return NULL; + + pthread_mutex_init (&frame->vo_frame.mutex, NULL); + + /* + * supply required functions/fields + */ + frame->vo_frame.proc_slice = raw_frame_proc_slice; + frame->vo_frame.proc_frame = NULL; + frame->vo_frame.field = raw_frame_field; + frame->vo_frame.dispose = raw_frame_dispose; + frame->vo_frame.driver = this_gen; + + /* + * colorspace converter for this frame + */ + frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); + + return (vo_frame_t *) frame; +} + + + +static void raw_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) +{ + raw_frame_t *frame = (raw_frame_t *) frame_gen; + + /* Check frame size and format and reallocate if necessary */ + if ((frame->width != width) + || (frame->height != height) + || (frame->format != format) + || (frame->flags != flags)) { +/* lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ + + flags &= VO_BOTH_FIELDS; + + /* (re-) allocate render space */ + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame->chunk[3]); + + if (format == XINE_IMGFMT_YV12) { + frame->vo_frame.pitches[0] = 8*((width + 7) / 8); + frame->vo_frame.pitches[1] = 8*((width + 15) / 16); + frame->vo_frame.pitches[2] = 8*((width + 15) / 16); + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); + frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]); + frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]); + } else { + frame->vo_frame.pitches[0] = 8*((width + 3) / 4); + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); + frame->chunk[1] = NULL; + frame->chunk[2] = NULL; + } + frame->rgb = xine_xmalloc_aligned (16, BYTES_PER_PIXEL*width*height, + (void **) &frame->chunk[3]); + + /* set up colorspace converter */ + switch (flags) { + case VO_TOP_FIELD: + case VO_BOTTOM_FIELD: + frame->yuv2rgb->configure (frame->yuv2rgb, + width, + height, + 2*frame->vo_frame.pitches[0], + 2*frame->vo_frame.pitches[1], + width, + height, + BYTES_PER_PIXEL*width * 2); + break; + case VO_BOTH_FIELDS: + frame->yuv2rgb->configure (frame->yuv2rgb, + width, + height, + frame->vo_frame.pitches[0], + frame->vo_frame.pitches[1], + width, + height, + BYTES_PER_PIXEL*width); + break; + } + + frame->width = width; + frame->height = height; + frame->format = format; + + raw_frame_field ((vo_frame_t *)frame, flags); + } + + frame->ratio = ratio; +} + + + +static int raw_redraw_needed (vo_driver_t *this_gen) +{ + return 0; +} + + + +static void raw_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + int i; + + if (this->frame[NUM_FRAMES_BACKLOG-1]) { + this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame.free (&this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame); + } + for (i = NUM_FRAMES_BACKLOG-1; i > 0; i--) + this->frame[i] = this->frame[i-1]; + this->frame[0] = frame; + + if ( frame->rgb_dst ) { + this->raw_output_cb( this->user_data, XINE_VORAW_RGB, frame->width, frame->height, frame->ratio, frame->rgb, 0, 0 ); + } + else if ( frame->format==XINE_IMGFMT_YV12 ) { + this->raw_output_cb( this->user_data, XINE_VORAW_YV12, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], + frame->vo_frame.base[1], frame->vo_frame.base[2] ); + } + else { + this->raw_output_cb( this->user_data, XINE_VORAW_YUY2, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], 0, 0 ); + } +} + + + +static int raw_get_property (vo_driver_t *this_gen, int property) +{ + switch (property) { + case VO_PROP_ASPECT_RATIO: + return XINE_VO_ASPECT_AUTO; + case VO_PROP_MAX_NUM_FRAMES: + return 15; + case VO_PROP_BRIGHTNESS: + return 0; + case VO_PROP_CONTRAST: + return 128; + case VO_PROP_SATURATION: + return 128; + case VO_PROP_WINDOW_WIDTH: + return 0; + case VO_PROP_WINDOW_HEIGHT: + return 0; + default: + return 0; + } +} + + + +static int raw_set_property (vo_driver_t *this_gen, int property, int value) +{ + return value; +} + + + +static void raw_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) +{ + *min = 0; + *max = 0; +} + + + +static int raw_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) +{ + return 0; +} + + + +static uint32_t raw_get_capabilities (vo_driver_t *this_gen) +{ + uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; + return capabilities; +} + + + +static void raw_dispose (vo_driver_t *this_gen) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + int i; + + for (i = 0; i < NUM_FRAMES_BACKLOG; i++) + if (this->frame[i]) + this->frame[i]->vo_frame.dispose (&this->frame[i]->vo_frame); + + this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + + for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) + free( this->overlays[i].ovl_rgba ); + + free (this); +} + + + +static vo_driver_t *raw_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) +{ + raw_class_t *class = (raw_class_t *) class_gen; + raw_visual_t *visual = (raw_visual_t *) visual_gen; + raw_driver_t *this; + int i; + + this = (raw_driver_t *) calloc(1, sizeof(raw_driver_t)); + + if (!this) + return NULL; + + this->raw_output_cb = visual->raw_output_cb; + this->user_data = visual->user_data; + this->xine = class->xine; + this->raw_overlay_cb = visual->raw_overlay_cb; + this->doYV12 = visual->supported_formats&XINE_VORAW_YV12; + this->doYUY2 = visual->supported_formats&XINE_VORAW_YUY2; + + this->vo_driver.get_capabilities = raw_get_capabilities; + this->vo_driver.alloc_frame = raw_alloc_frame; + this->vo_driver.update_frame_format = raw_update_frame_format; + this->vo_driver.overlay_begin = raw_overlay_begin; + this->vo_driver.overlay_blend = raw_overlay_blend; + this->vo_driver.overlay_end = raw_overlay_end; + this->vo_driver.display_frame = raw_display_frame; + this->vo_driver.get_property = raw_get_property; + this->vo_driver.set_property = raw_set_property; + this->vo_driver.get_property_min_max = raw_get_property_min_max; + this->vo_driver.gui_data_exchange = raw_gui_data_exchange; + this->vo_driver.dispose = raw_dispose; + this->vo_driver.redraw_needed = raw_redraw_needed; + + this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 1, NULL); /* converts to rgb */ + + for (i = 0; i < NUM_FRAMES_BACKLOG; i++) + this->frame[i] = 0; + + for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) { + this->overlays[i].ovl_w = this->overlays[i].ovl_h = 2; + this->overlays[i].ovl_rgba = (uint8_t*)malloc(2*2*4); + this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; + } + this->ovl_changed = 0; + + /* we have to use a second converter for overlays + * because "MODE_24_BGR, 1 (swap)" breaks overlays conversion */ + yuv2rgb_factory_t *factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); + this->ovl_yuv2rgb = factory->create_converter( factory ); + factory->dispose( factory ); + + return &this->vo_driver; +} + +/* + * class functions + */ + +static char* raw_get_identifier (video_driver_class_t *this_gen) +{ + return "raw"; +} + + + +static char* raw_get_description (video_driver_class_t *this_gen) +{ + return _("xine video output plugin passing raw data to supplied callback"); +} + + + +static void raw_dispose_class (video_driver_class_t *this_gen) +{ + raw_class_t *this = (raw_class_t *) this_gen; + free (this); +} + + + +static void *raw_init_class (xine_t *xine, void *visual_gen) +{ + raw_class_t *this = (raw_class_t *) calloc(1, sizeof(raw_class_t)); + + this->driver_class.open_plugin = raw_open_plugin; + this->driver_class.get_identifier = raw_get_identifier; + this->driver_class.get_description = raw_get_description; + this->driver_class.dispose = raw_dispose_class; + this->xine = xine; + + return this; +} + + + +static const vo_info_t vo_info_raw = { + 7, /* priority */ + XINE_VISUAL_TYPE_RAW /* visual type */ +}; + + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_VIDEO_OUT, 21, "raw", XINE_VERSION_CODE, &vo_info_raw, raw_init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/video_out/video_out_sdl.c b/src/video_out/video_out_sdl.c index 6705b4176..89150f5d0 100644 --- a/src/video_out/video_out_sdl.c +++ b/src/video_out/video_out_sdl.c @@ -138,7 +138,7 @@ static vo_frame_t *sdl_alloc_frame (vo_driver_t *this_gen) { /* sdl_driver_t *this = (sdl_driver_t *) this_gen; */ sdl_frame_t *frame ; - frame = (sdl_frame_t *) xine_xmalloc (sizeof (sdl_frame_t)); + frame = (sdl_frame_t *) calloc(1, sizeof(sdl_frame_t)); if (!frame) return NULL; @@ -469,13 +469,15 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi sdl_driver_t *this; const SDL_VideoInfo *vidInfo; -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(WIN32) static char SDL_windowhack[32]; x11_visual_t *visual = (x11_visual_t *) visual_gen; +#endif +#ifdef HAVE_X11 XWindowAttributes window_attributes; #endif - this = (sdl_driver_t *) xine_xmalloc (sizeof (sdl_driver_t)); + this = (sdl_driver_t *) calloc(1, sizeof(sdl_driver_t)); if (!this) return NULL; @@ -502,14 +504,18 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi _x_vo_scale_init( &this->sc, 0, 0, config); this->sc.frame_output_cb = visual->frame_output_cb; this->sc.user_data = visual->user_data; - - /* set SDL to use our existing X11 window */ - sprintf(SDL_windowhack,"SDL_WINDOWID=0x%x", (uint32_t) this->drawable ); - putenv(SDL_windowhack); #else _x_vo_scale_init( &this->sc, 0, 0, config ); #endif +#if defined(HAVE_X11) || defined(WIN32) + /* set SDL to use our existing X11/win32 window */ + if (visual->d){ + sprintf(SDL_windowhack,"SDL_WINDOWID=0x%x", (uint32_t) visual->d); + putenv(SDL_windowhack); + } +#endif + if ((SDL_Init (SDL_INIT_VIDEO)) < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_sdl: open_plugin - sdl video initialization failed.\n"); return NULL; @@ -596,7 +602,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { } SDL_QuitSubSystem (SDL_INIT_VIDEO); - this = (sdl_class_t*) xine_xmalloc (sizeof (sdl_class_t)); + this = (sdl_class_t*) calloc(1, sizeof(sdl_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_stk.c b/src/video_out/video_out_stk.c index dfc4ae385..00dd80251 100644 --- a/src/video_out/video_out_stk.c +++ b/src/video_out/video_out_stk.c @@ -133,7 +133,7 @@ static vo_frame_t *stk_alloc_frame(vo_driver_t *this_gen) { stk_frame_t* frame; //printf("video_out_stk: alloc_frame()\n"); - frame = (stk_frame_t *) xine_xmalloc(sizeof(stk_frame_t)); + frame = calloc(1, sizeof(stk_frame_t)); if (!frame) return NULL; @@ -389,7 +389,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis //printf("video_out_stk: open_plugin()\n"); - this = (stk_driver_t *) xine_xmalloc (sizeof (stk_driver_t)); + this = calloc(1, sizeof (stk_driver_t)); if (!this) return NULL; @@ -463,7 +463,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { //printf("video_out_stk: init_class()\n"); - this = (stk_class_t *) xine_xmalloc(sizeof(stk_class_t)); + this = calloc(1, sizeof(stk_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c index b1fadbd58..f66817f36 100644 --- a/src/video_out/video_out_syncfb.c +++ b/src/video_out/video_out_syncfb.c @@ -478,7 +478,7 @@ static vo_frame_t* syncfb_alloc_frame(vo_driver_t* this_gen) /* syncfb_driver_t *this = (syncfb_driver_t *) this_gen; */ syncfb_frame_t *frame; - frame = (syncfb_frame_t *) xine_xmalloc(sizeof(syncfb_frame_t)); + frame = calloc(1, sizeof(syncfb_frame_t)); if(!frame) return NULL; @@ -882,7 +882,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi display = visual->display; - if(!(this = xine_xmalloc(sizeof (syncfb_driver_t)))) + if(!(this = calloc(1, sizeof (syncfb_driver_t)))) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); @@ -1105,7 +1105,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { /* * from this point on, nothing should go wrong anymore */ - this = (syncfb_class_t *) xine_xmalloc (sizeof (syncfb_class_t)); + this = calloc(1, sizeof (syncfb_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_vidix.c b/src/video_out/video_out_vidix.c index 9e3f870b1..482841a09 100644 --- a/src/video_out/video_out_vidix.c +++ b/src/video_out/video_out_vidix.c @@ -370,7 +370,7 @@ static vo_frame_t *vidix_alloc_frame (vo_driver_t *this_gen) { /* vidix_driver_t *this = (vidix_driver_t *) this_gen; */ vidix_frame_t *frame ; - frame = (vidix_frame_t *) xine_xmalloc (sizeof (vidix_frame_t)); + frame = (vidix_frame_t *) calloc(1, sizeof(vidix_frame_t)); if (!frame) return NULL; @@ -947,7 +947,7 @@ static vidix_driver_t *open_plugin (video_driver_class_t *class_gen) { vidix_driver_t *this; int err; - this = (vidix_driver_t *) xine_xmalloc (sizeof (vidix_driver_t)); + this = (vidix_driver_t *) calloc(1, sizeof(vidix_driver_t)); if (!this) return NULL; @@ -1089,7 +1089,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { vidix_class_t *this; int err; - this = (vidix_class_t *) xine_xmalloc (sizeof (vidix_class_t)); + this = (vidix_class_t *) calloc(1, sizeof(vidix_class_t)); if (!this) return NULL; diff --git a/src/video_out/video_out_xcbshm.c b/src/video_out/video_out_xcbshm.c index 2ac579555..a5282a24f 100644 --- a/src/video_out/video_out_xcbshm.c +++ b/src/video_out/video_out_xcbshm.c @@ -295,7 +295,7 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { xshm_frame_t *frame; xshm_driver_t *this = (xshm_driver_t *) this_gen; - frame = (xshm_frame_t *) xine_xmalloc (sizeof (xshm_frame_t)); + frame = (xshm_frame_t *) calloc(1, sizeof(xshm_frame_t)); if (!frame) return NULL; @@ -1015,7 +1015,7 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void const xcb_query_extension_reply_t *query_extension_reply; - this = (xshm_driver_t *) xine_xmalloc (sizeof (xshm_driver_t)); + this = (xshm_driver_t *) calloc(1, sizeof(xshm_driver_t)); if (!this) return NULL; @@ -1250,7 +1250,7 @@ static void xshm_dispose_class (video_driver_class_t *this_gen) { } static void *xshm_init_class (xine_t *xine, void *visual_gen) { - xshm_class_t *this = (xshm_class_t *) xine_xmalloc (sizeof (xshm_class_t)); + xshm_class_t *this = (xshm_class_t *) calloc(1, sizeof(xshm_class_t)); this->driver_class.open_plugin = xshm_open_plugin; this->driver_class.get_identifier = xshm_get_identifier; diff --git a/src/video_out/video_out_xcbxv.c b/src/video_out/video_out_xcbxv.c index 18ab5c6fb..1e6e2b663 100644 --- a/src/video_out/video_out_xcbxv.c +++ b/src/video_out/video_out_xcbxv.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004, 2007 the xine project + * Copyright (C) 2000-2004, 2007-2008 the xine project * * This file is part of xine, a free video player. * @@ -65,6 +65,7 @@ #include "xineutils.h" #include "vo_scale.h" #include "xcbosd.h" +#include "xv_common.h" typedef struct xv_driver_s xv_driver_t; @@ -137,6 +138,8 @@ struct xv_driver_s { int use_colorkey; uint32_t colorkey; + int sync_is_vsync; + /* hold initial port attributes values to restore on exit */ xine_list_t *port_attributes; @@ -155,6 +158,10 @@ typedef struct { xine_t *xine; } xv_class_t; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; + static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -186,7 +193,7 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { /* xv_driver_t *this = (xv_driver_t *) this_gen; */ xv_frame_t *frame ; - frame = (xv_frame_t *) xine_xmalloc (sizeof (xv_frame_t)); + frame = (xv_frame_t *) calloc(1, sizeof(xv_frame_t)); if (!frame) return NULL; @@ -432,7 +439,7 @@ static void xv_deinterlace_frame (xv_driver_t *this) { for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image + frame->width*frame->height; + recent_bitmaps[i] = this->recent_frames[i]->image + this->deinterlace_frame.xv_width*frame->height; else recent_bitmaps[i] = NULL; @@ -1101,6 +1108,8 @@ static int xv_check_yv12(xcb_connection_t *connection, xcb_xv_port_t port) { list_formats_cookie = xcb_xv_list_image_formats(connection, port); list_formats_reply = xcb_xv_list_image_formats_reply(connection, list_formats_cookie, NULL); + if (!list_formats_reply) + return 1; /* no formats listed; probably due to an invalid port no. */ format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply); for (; format_it.rem; xcb_xv_image_format_info_next(&format_it)) @@ -1122,7 +1131,7 @@ static void xv_check_capability (xv_driver_t *this, char *config_help) { int int_default; cfg_entry_t *entry; - char *str_prop = xcb_xv_attribute_info_name(attr); + const char *str_prop = xcb_xv_attribute_info_name(attr); xcb_xv_get_port_attribute_cookie_t get_attribute_cookie; xcb_xv_get_port_attribute_reply_t *get_attribute_reply; @@ -1207,44 +1216,42 @@ static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { this->deinterlace_method = entry->num_value; } -static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xv_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_filter; xcb_intern_atom_cookie_t atom_cookie; xcb_intern_atom_reply_t *atom_reply; - xv_filter = entry->num_value; - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_FILTER"), "XV_FILTER"); + atom_cookie = xcb_intern_atom(this->connection, 0, strlen (atomstr), atomstr); atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_filter); + xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, entry->num_value); free(atom_reply); pthread_mutex_unlock(&this->main_mutex); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_double_buffer; - - xcb_intern_atom_cookie_t atom_cookie; - xcb_intern_atom_reply_t *atom_reply; +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - xv_double_buffer = entry->num_value; +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_DOUBLE_BUFFER"), "XV_DOUBLE_BUFFER"); - atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_double_buffer); - free(atom_reply); - pthread_mutex_unlock(&this->main_mutex); +static void xv_update_XV_SYNC_TO_VBLANK(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, + sync_atoms[((xv_driver_t *)this_gen)->sync_is_vsync], + "sync to vblank"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: double buffering mode = %d\n", xv_double_buffer); +static void xv_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xv_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -1253,14 +1260,65 @@ static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry this->use_pitch_alignment = entry->num_value; } +static xcb_xv_port_t xv_open_port (xv_driver_t *this, xcb_xv_port_t port) { + xcb_xv_grab_port_cookie_t grab_port_cookie; + xcb_xv_grab_port_reply_t *grab_port_reply; + + if (xv_check_yv12 (this->connection, port)) + return 0; + + grab_port_cookie = xcb_xv_grab_port (this->connection, port, XCB_CURRENT_TIME); + grab_port_reply = xcb_xv_grab_port_reply (this->connection, grab_port_cookie, NULL); + + if (grab_port_reply && (grab_port_reply->result == XCB_GRAB_STATUS_SUCCESS)) + { + free (grab_port_reply); + return port; + } + free (grab_port_reply); + return 0; +} + +static xcb_xv_adaptor_info_iterator_t * +xv_find_adaptor_by_port (int port, xcb_xv_adaptor_info_iterator_t *adaptor_it) +{ + for (; adaptor_it->rem; xcb_xv_adaptor_info_next(adaptor_it)) + if (adaptor_it->data->type & XCB_XV_TYPE_IMAGE_MASK) + if (port >= adaptor_it->data->base_id && + port < adaptor_it->data->base_id + adaptor_it->data->num_ports) + return adaptor_it; + return NULL; /* shouldn't happen */ +} + +static xcb_xv_port_t xv_autodetect_port(xv_driver_t *this, + xcb_xv_adaptor_info_iterator_t *adaptor_it, + xcb_xv_port_t base, + xv_prefertype prefer_type) +{ + for (; adaptor_it->rem; xcb_xv_adaptor_info_next(adaptor_it)) + if (adaptor_it->data->type & XCB_XV_TYPE_IMAGE_MASK && + (prefer_type == xv_prefer_none || + strcasestr (xcb_xv_adaptor_info_name (adaptor_it->data), prefer_substrings[prefer_type]))) + { + int j; + for (j = 0; j < adaptor_it->data->num_ports; ++j) + { + xcb_xv_port_t port = adaptor_it->data->base_id + j; + if (port >= base && xv_open_port (this, port)) + return port; + } + } + return 0; +} + static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *visual_gen) { xv_class_t *class = (xv_class_t *) class_gen; config_values_t *config = class->config; xv_driver_t *this; int i; xcb_visual_t *visual = (xcb_visual_t *) visual_gen; - unsigned int j; xcb_xv_port_t xv_port; + xv_prefertype prefer_type; const xcb_query_extension_reply_t *query_extension_reply; @@ -1271,10 +1329,10 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis xcb_xv_list_image_formats_cookie_t list_formats_cookie; xcb_xv_list_image_formats_reply_t *list_formats_reply; - xcb_xv_adaptor_info_iterator_t adaptor_it; + xcb_xv_adaptor_info_iterator_t adaptor_it, adaptor_first; xcb_xv_image_format_info_iterator_t format_it; - this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t)); + this = (xv_driver_t *) calloc(1, sizeof(xv_driver_t)); if (!this) return NULL; @@ -1309,28 +1367,37 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis return NULL; } - adaptor_it = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply); - - xv_port = 0; - - for (; adaptor_it.rem && !xv_port; xcb_xv_adaptor_info_next(&adaptor_it)) { - - if (adaptor_it.data->type & XCB_XV_TYPE_IMAGE_MASK) { - - for (j = 0; j < adaptor_it.data->num_ports; j++) - if (!xv_check_yv12(this->connection, adaptor_it.data->base_id + j)) { - xcb_xv_grab_port_cookie_t grab_port_cookie; - xcb_xv_grab_port_reply_t *grab_port_reply; - grab_port_cookie = xcb_xv_grab_port(this->connection, adaptor_it.data->base_id + j, XCB_CURRENT_TIME); - grab_port_reply = xcb_xv_grab_port_reply(this->connection, grab_port_cookie, NULL); - if (grab_port_reply && (grab_port_reply->result == XCB_GRAB_STATUS_SUCCESS)) { - free(grab_port_reply); - xv_port = adaptor_it.data->base_id + j; - break; - } - free(grab_port_reply); - } - } + adaptor_first = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply); + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xv_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %d - autodetecting\n"), + LOG_MODULE, xv_port); + adaptor_it = adaptor_first; + xv_port = xv_autodetect_port (this, &adaptor_it, xv_port, prefer_type); + } else + xv_find_adaptor_by_port (xv_port, &adaptor_it); + } + if (!xv_port) + { + adaptor_it = adaptor_first; + xv_port = xv_autodetect_port (this, &adaptor_it, 0, prefer_type); + } + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + adaptor_it = adaptor_first; + xv_port = xv_autodetect_port (this, &adaptor_it, 0, xv_prefer_none); } if (!xv_port) { @@ -1411,10 +1478,11 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis for (; attribute_it.rem; xcb_xv_attribute_info_next(&attribute_it)) { if ((attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_SETTABLE) && (attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_GETTABLE)) { + const char *const name = xcb_xv_attribute_info_name(attribute_it.data); /* store initial port attribute value */ - xv_store_port_attribute(this, xcb_xv_attribute_info_name(attribute_it.data)); - - if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_HUE")) { + xv_store_port_attribute(this, name); + + if(!strcmp(name, "XV_HUE")) { if (!strncmp(xcb_xv_adaptor_info_name(adaptor_it.data), "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xcbxv: ignoring broken XV_HUE settings on NVidia cards\n"); } else { @@ -1422,64 +1490,61 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis adaptor_it.data->base_id, NULL, NULL, NULL); } - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xv_check_capability (this, VO_PROP_SATURATION, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xv_check_capability (this, VO_PROP_BRIGHTNESS, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xv_check_capability (this, VO_PROP_CONTRAST, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xv_check_capability (this, VO_PROP_COLORKEY, attribute_it.data, adaptor_it.data->base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xv_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attribute_it.data, adaptor_it.data->base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attribute_it.data->min, attribute_it.data->max, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xv_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), - 20, xv_update_XV_DOUBLE_BUFFER, this); + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, + 20, xv_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(!strcmp(name, sync_atoms[this->sync_is_vsync = 0]) || + !strcmp(name, sync_atoms[this->sync_is_vsync = 1])) { + int xv_sync_to_vblank; + xv_sync_to_vblank = + config->register_bool (config, "video.device.xv_sync_to_vblank", 1, + _("enable vblank sync"), + _("This option will synchronize the update of the video image to the " + "repainting of the entire screen (\"vertical retrace\"). This eliminates " + "flickering and tearing artifacts. On nvidia cards one may also " + "need to run \"nvidia-settings\" and choose which display device to " + "sync to under the XVideo Settings tab"), + 20, xv_update_XV_SYNC_TO_VBLANK, this); + config->update_num(config,"video.device.xv_sync_to_vblank",xv_sync_to_vblank); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xv_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -1524,8 +1589,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xv_update_xv_pitch_alignment, this); this->deinterlace_method = @@ -1596,7 +1660,7 @@ static void dispose_class (video_driver_class_t *this_gen) { } static void *init_class (xine_t *xine, void *visual_gen) { - xv_class_t *this = (xv_class_t *) xine_xmalloc (sizeof (xv_class_t)); + xv_class_t *this = (xv_class_t *) calloc(1, sizeof(xv_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 9e901821a..74791f145 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -276,7 +276,7 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->bytes_per_pixel = this->bpp / 8; this->image_byte_order = myimage->byte_order; - myimage->data = xine_xmalloc (width * this->bytes_per_pixel * height); + myimage->data = calloc (width * height, this->bytes_per_pixel); } return myimage; @@ -387,7 +387,7 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { xshm_frame_t *frame; xshm_driver_t *this = (xshm_driver_t *) this_gen; - frame = (xshm_frame_t *) xine_xmalloc (sizeof (xshm_frame_t)); + frame = (xshm_frame_t *) calloc(1, sizeof(xshm_frame_t)); if (!frame) return NULL; @@ -1083,7 +1083,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v int cpu_byte_order; XColor dummy; - this = (xshm_driver_t *) xine_xmalloc (sizeof (xshm_driver_t)); + this = (xshm_driver_t *) calloc(1, sizeof(xshm_driver_t)); if (!this) return NULL; @@ -1310,7 +1310,7 @@ static void xshm_dispose_class (video_driver_class_t *this_gen) { } static void *xshm_init_class (xine_t *xine, void *visual_gen) { - xshm_class_t *this = (xshm_class_t *) xine_xmalloc (sizeof (xshm_class_t)); + xshm_class_t *this = (xshm_class_t *) calloc(1, sizeof(xshm_class_t)); this->driver_class.open_plugin = xshm_open_plugin_old; this->driver_class.get_identifier = xshm_get_identifier; diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 3bb0a93dc..f2c47ef7e 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * * This file is part of xine, a free video player. * @@ -70,6 +70,7 @@ #include "xineutils.h" #include "vo_scale.h" #include "x11osd.h" +#include "xv_common.h" #define LOCK_DISPLAY(this) {if(this->lock_display) this->lock_display(this->user_data); \ else XLockDisplay(this->display);} @@ -142,6 +143,8 @@ struct xv_driver_s { int use_colorkey; uint32_t colorkey; + int sync_is_vsync; + /* hold initial port attributes values to restore on exit */ xine_list_t *port_attributes; @@ -168,6 +171,10 @@ typedef struct { static int gX11Fail; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; + static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -208,7 +215,7 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { /* xv_driver_t *this = (xv_driver_t *) this_gen; */ xv_frame_t *frame ; - frame = (xv_frame_t *) xine_xmalloc (sizeof (xv_frame_t)); + frame = (xv_frame_t *) calloc(1, sizeof(xv_frame_t)); if (!frame) return NULL; @@ -521,7 +528,7 @@ static void xv_deinterlace_frame (xv_driver_t *this) { for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image->data + frame->width*frame->height; + recent_bitmaps[i] = this->recent_frames[i]->image->data + this->deinterlace_frame.image->width*frame->height; else recent_bitmaps[i] = NULL; @@ -851,8 +858,8 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { if( factor > 1 ) { - lprintf( "%s PutImage %dX interval (%fs)\n", - log_line_prefix(), factor, elapse_time ); + lprintf( "%s PutImage %dX interval (%fs)\n", + LOG_MODULE, factor, elapse_time ); } } @@ -1090,7 +1097,7 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, return 0; } -static void xv_store_port_attribute(xv_driver_t *this, char *name) { +static void xv_store_port_attribute(xv_driver_t *this, const char *name) { Atom atom; xv_portattribute_t *attr; @@ -1190,14 +1197,13 @@ static int xv_check_yv12 (Display *display, XvPortID port) { /* called xlocked */ static void xv_check_capability (xv_driver_t *this, - int property, XvAttribute attr, - int base_id, + int property, XvAttribute attr, int base_id, char *config_name, char *config_desc, char *config_help) { int int_default; cfg_entry_t *entry; - char *str_prop = attr.name; + const char *str_prop = attr.name; /* * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing. @@ -1267,36 +1273,38 @@ static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { this->deinterlace_method = entry->num_value; } -static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xv_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xv_driver_t *this = (xv_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); UNLOCK_DISPLAY(this); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - xv_double_buffer = entry->num_value; +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - UNLOCK_DISPLAY(this); +static void xv_update_XV_SYNC_TO_VBLANK(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, + sync_atoms[((xv_driver_t *)this_gen)->sync_is_vsync], + "sync to vblank"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: double buffering mode = %d\n", xv_double_buffer); +static void xv_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xv_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -1305,6 +1313,52 @@ static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry this->use_pitch_alignment = entry->num_value; } +static int xv_open_port (xv_driver_t *this, XvPortID port) { + int ret; + x11_InstallXErrorHandler (this); + ret = ! xv_check_yv12(this->display, port) + && XvGrabPort(this->display, port, 0) == Success; + x11_DeInstallXErrorHandler (this); + return ret; +} + +static unsigned int +xv_find_adaptor_by_port (int port, unsigned int adaptors, + XvAdaptorInfo *adaptor_info) +{ + unsigned int an; + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask) + if (port >= adaptor_info[an].base_id && + port < adaptor_info[an].base_id + adaptor_info[an].num_ports) + return an; + return 0; /* shouldn't happen */ +} + +static XvPortID xv_autodetect_port(xv_driver_t *this, + unsigned int adaptors, + XvAdaptorInfo *adaptor_info, + unsigned int *adaptor_num, + XvPortID base, + xv_prefertype prefer_type) +{ + unsigned int an, j; + + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask && + (prefer_type == xv_prefer_none || + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) + for (j = 0; j < adaptor_info[an].num_ports; j++) { + XvPortID port = adaptor_info[an].base_id + j; + if (port >= base && xv_open_port(this, port)) { + *adaptor_num = an; + return port; + } + } + + return 0; +} + /* expects XINE_VISUAL_TYPE_X11_2 with configurable locking */ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void *visual_gen) { xv_class_t *class = (xv_class_t *) class_gen; @@ -1317,14 +1371,15 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; XvImage *myimage; - unsigned int adaptors, j; + unsigned int adaptors; unsigned int ver,rel,req,ev,err; XShmSegmentInfo myshminfo; XvPortID xv_port; XvAdaptorInfo *adaptor_info; unsigned int adaptor_num; + xv_prefertype prefer_type; - this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t)); + this = (xv_driver_t *) calloc(1, sizeof(xv_driver_t)); if (!this) return NULL; @@ -1360,24 +1415,31 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * return NULL; } - xv_port = 0; - - for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) { - - if (adaptor_info[adaptor_num].type & XvImageMask) { - - for (j = 0; j < adaptor_info[adaptor_num].num_ports && !xv_port; j++) - if (( !(xv_check_yv12 (this->display, - adaptor_info[adaptor_num].base_id + j))) - && (XvGrabPort (this->display, - adaptor_info[adaptor_num].base_id + j, - 0) == Success)) { - xv_port = adaptor_info[adaptor_num].base_id + j; - } - - if( xv_port ) - break; - } + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xv_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %"PRId32" - autodetecting\n"), + LOG_MODULE, xv_port); + xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type); + } else + adaptor_num = xv_find_adaptor_by_port (xv_port, adaptors, adaptor_info); + } + if (!xv_port) + xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); } if (!xv_port) { @@ -1469,10 +1531,11 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { + const char *const name = attr[k].name; /* store initial port attribute value */ - xv_store_port_attribute(this, attr[k].name); + xv_store_port_attribute(this, name); - if(!strcmp(attr[k].name, "XV_HUE")) { + if(!strcmp(name, "XV_HUE")) { if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xv: ignoring broken XV_HUE settings on NVidia cards\n"); } else { @@ -1480,64 +1543,61 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); } - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xv_check_capability (this, VO_PROP_SATURATION, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xv_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xv_check_capability (this, VO_PROP_CONTRAST, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xv_check_capability (this, VO_PROP_COLORKEY, attr[k], adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xv_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attr[k].min_value, attr[k].max_value, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xv_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), - 20, xv_update_XV_DOUBLE_BUFFER, this); + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, + 20, xv_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(((this->sync_is_vsync = 0), !strcmp(name, sync_atoms[0])) || + ((this->sync_is_vsync = 1), !strcmp(name, sync_atoms[1]))) { + int xv_sync_to_vblank; + xv_sync_to_vblank = + config->register_bool (config, "video.device.xv_sync_to_vblank", 1, + _("enable vblank sync"), + _("This option will synchronize the update of the video image to the " + "repainting of the entire screen (\"vertical retrace\"). This eliminates " + "flickering and tearing artifacts. On nvidia cards one may also " + "need to run \"nvidia-settings\" and choose which display device to " + "sync to under the XVideo Settings tab"), + 20, xv_update_XV_SYNC_TO_VBLANK, this); + config->update_num(config,"video.device.xv_sync_to_vblank",xv_sync_to_vblank); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xv_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -1593,8 +1653,7 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xv_update_xv_pitch_alignment, this); this->deinterlace_method = @@ -1684,7 +1743,7 @@ static void dispose_class (video_driver_class_t *this_gen) { } static void *init_class (xine_t *xine, void *visual_gen) { - xv_class_t *this = (xv_class_t *) xine_xmalloc (sizeof (xv_class_t)); + xv_class_t *this = (xv_class_t *) calloc(1, sizeof(xv_class_t)); this->driver_class.open_plugin = open_plugin_old; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_xvmc.c b/src/video_out/video_out_xvmc.c index a17e4d6a0..c2560ccc0 100644 --- a/src/video_out/video_out_xvmc.c +++ b/src/video_out/video_out_xvmc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * * This file is part of xine, a free video player. * @@ -75,6 +75,7 @@ #include "xineutils.h" #include "vo_scale.h" +#include "xv_common.h" /* #define LOG1 */ /* #define DLOG */ @@ -225,8 +226,6 @@ typedef struct { Display *display; config_values_t *config; XvPortID xv_port; - XvAdaptorInfo *adaptor_info; - unsigned int adaptor_num; int surface_type_id; unsigned int max_surface_width; @@ -556,7 +555,7 @@ static vo_frame_t *xvmc_alloc_frame (vo_driver_t *this_gen) { lprintf ("xvmc_alloc_frame\n"); - frame = (xvmc_frame_t *) xine_xmalloc (sizeof (xvmc_frame_t)); + frame = calloc(1, sizeof (xvmc_frame_t)); if (!frame) return NULL; @@ -595,8 +594,8 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, /* initialize block & macro block pointers first time */ if(macroblocks->blocks == NULL || macroblocks->macro_blocks == NULL) { - macroblocks->blocks = xine_xmalloc(sizeof(XvMCBlockArray)); - macroblocks->macro_blocks = xine_xmalloc(sizeof(XvMCMacroBlockArray)); + macroblocks->blocks = calloc(1, sizeof(XvMCBlockArray)); + macroblocks->macro_blocks = calloc(1, sizeof(XvMCMacroBlockArray)); lprintf("macroblocks->blocks %lx ->macro_blocks %lx\n", macroblocks->blocks,macroblocks->macro_blocks); @@ -700,6 +699,7 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, return NULL; } +#if 0 static XvImage *create_ximage (xvmc_driver_t *this, XShmSegmentInfo *shminfo, int width, int height, int format) { unsigned int xvmc_format; @@ -755,6 +755,7 @@ static void dispose_ximage (xvmc_driver_t *this, lprintf ("dispose_ximage\n"); XFree(myimage); } +#endif static void xvmc_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, @@ -1252,13 +1253,13 @@ static void xvmc_dispose (vo_driver_t *this_gen) { /* called xlocked */ static void xvmc_check_capability (xvmc_driver_t *this, - int property, XvAttribute attr, - int base_id, char *str_prop, - char *config_name, - char *config_desc, - char *config_help) { + int property, XvAttribute attr, int base_id, + const char *config_name, + const char *config_desc, + const char *config_help) { int int_default; cfg_entry_t *entry; + const char *str_prop = attr.name; /* * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing. @@ -1281,13 +1282,13 @@ static void xvmc_check_capability (xvmc_driver_t *this, if ((attr.min_value == 0) && (attr.max_value == 1)) { this->config->register_bool (this->config, config_name, int_default, config_desc, - NULL, 20, xvmc_property_callback, &this->props[property]); + config_help, 20, xvmc_property_callback, &this->props[property]); } else { this->config->register_range (this->config, config_name, int_default, this->props[property].min, this->props[property].max, config_desc, - NULL, 20, xvmc_property_callback, &this->props[property]); + config_help, 20, xvmc_property_callback, &this->props[property]); } entry = this->config->lookup_entry (this->config, config_name); @@ -1333,7 +1334,6 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi xvmc_class_t *class = (xvmc_class_t *) class_gen; config_values_t *config = class->config; xvmc_driver_t *this = NULL; - Display *display = NULL; unsigned int i, formats; XvPortID xv_port = class->xv_port; XvAttribute *attr; @@ -1341,14 +1341,13 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi int nattr; x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; + XvAdaptorInfo *adaptor_info; + unsigned int adaptor_num; /* XvImage *myimage; */ lprintf ("open_plugin\n"); - display = visual->display; - - /* TODO ??? */ - this = (xvmc_driver_t *) xine_xmalloc (sizeof (xvmc_driver_t)); + this = calloc(1, sizeof (xvmc_driver_t)); if (!this) return NULL; @@ -1430,56 +1429,47 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->capabilities |= VO_CAP_XVMC_IDCT; XLockDisplay(this->display); - attr = XvQueryPortAttributes(display, xv_port, &nattr); + attr = XvQueryPortAttributes(this->display, xv_port, &nattr); if(attr && nattr) { int k; for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { - if(!strcmp(attr[k].name, "XV_HUE")) { - xvmc_check_capability (this, VO_PROP_HUE, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_HUE", - NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + const char *const name = attr[k].name; + if(!strcmp(name, "XV_HUE")) { + if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { + xprintf (this->xine, XINE_VERBOSITY_NONE, LOG_MODULE ": ignoring broken XV_HUE settings on NVidia cards\n"); + } else { + xvmc_check_capability (this, VO_PROP_HUE, attr[k], + adaptor_info[adaptor_num].base_id, + NULL, NULL, NULL); + } + } else if(!strcmp(name, "XV_SATURATION")) { xvmc_check_capability (this, VO_PROP_SATURATION, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_SATURATION", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { xvmc_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_BRIGHTNESS", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xvmc_check_capability (this, VO_PROP_CONTRAST, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_CONTRAST", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xvmc_check_capability (this, VO_PROP_COLORKEY, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xvmc_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xvmc_double_buffer; - xvmc_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), - 20, xvmc_update_XV_DOUBLE_BUFFER, this); + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xvmc_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, + 20, xvmc_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xvmc_double_buffer); } } @@ -1494,7 +1484,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi /* * check supported image formats */ - fo = XvListImageFormats(display, this->xv_port, (int*)&formats); + fo = XvListImageFormats(this->display, this->xv_port, (int*)&formats); XUnlockDisplay(this->display); this->xvmc_format_yv12 = 0; @@ -1613,10 +1603,6 @@ static char* get_description (video_driver_class_t *this_gen) { static void dispose_class (video_driver_class_t *this_gen) { xvmc_class_t *this = (xvmc_class_t *) this_gen; - XLockDisplay(this->display); - XvFreeAdaptorInfo (this->adaptor_info); - XUnlockDisplay(this->display); - free (this); } @@ -1789,8 +1775,6 @@ static void *init_class (xine_t *xine, void *visual_gen) { this->display = display; this->config = xine->config; this->xv_port = xv_port; - this->adaptor_info = adaptor_info; - this->adaptor_num = adaptor_num; this->surface_type_id = surface_type; this->max_surface_width = max_width; this->max_surface_height = max_height; diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index 28679e95d..61e0139e3 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * Copyright (C) 2004 the Unichrome project * * This file is part of xine, a free video player. @@ -34,9 +34,9 @@ */ - #include "xxmc.h" #include <unistd.h> +#include "xv_common.h" static int gX11Fail; @@ -45,6 +45,8 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, XvImage *myimage); +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; /* * Acceleration level priority. Static for now. It may well turn out that IDCT @@ -158,18 +160,13 @@ static void xxmc_xvmc_dump_subpictures(xxmc_driver_t *this) static void xxmc_xvmc_surface_handler_construct(xxmc_driver_t *this) { - int i; xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; pthread_mutex_init(&handler->mutex,NULL); - for (i=0; i<XVMC_MAX_SURFACES; ++i) { - handler->surfInUse[i] = 0; - handler->surfValid[i] = 0; - } - for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) { - handler->subInUse[i] = 0; - handler->subValid[i] = 0; - } + memset(handler->surfInUse, 0, sizeof(handler->surfInUse)); + memset(handler->surfValid, 0, sizeof(handler->surfValid)); + memset(handler->subInUse, 0, sizeof(handler->subInUse)); + memset(handler->subValid, 0, sizeof(handler->subValid)); } static void xxmc_xvmc_destroy_surfaces(xxmc_driver_t *this) @@ -550,7 +547,7 @@ static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame ; - frame = (xxmc_frame_t *) xine_xmalloc (sizeof (xxmc_frame_t)); + frame = calloc(1, sizeof (xxmc_frame_t)); if (!frame) return NULL; @@ -1611,8 +1608,8 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) * other than 100 %, so let's disable deinterlacing at all for this frame */ if (this->deinterlace_enabled && this->bob) { - disable_deinterlace = this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame - || this->disable_bob_for_scaled_osd && this->scaled_osd_active + disable_deinterlace = (this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame) + || (this->disable_bob_for_scaled_osd && this->scaled_osd_active) || !frame->vo_frame.stream || xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) != XINE_FINE_SPEED_NORMAL; if (!disable_deinterlace) { @@ -2065,13 +2062,13 @@ static int xxmc_check_yv12 (Display *display, XvPortID port) { /* called xlocked */ static void xxmc_check_capability (xxmc_driver_t *this, - int property, XvAttribute attr, - int base_id, char *str_prop, - char *config_name, - char *config_desc, - char *config_help) { + int property, XvAttribute attr, int base_id, + const char *config_name, + const char *config_desc, + const char *config_help) { int int_default; cfg_entry_t *entry; + const char *str_prop = attr.name; if (VO_PROP_COLORKEY && (attr.max_value == ~0)) attr.max_value = 2147483615; @@ -2133,36 +2130,32 @@ static void xxmc_check_capability (xxmc_driver_t *this, this->props[property].value = int_default; } -static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xxmc_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xxmc_driver_t *this = (xxmc_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); XUnlockDisplay(this->display); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xxmc_driver_t *this = (xxmc_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; - - xv_double_buffer = entry->num_value; +static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - XUnlockDisplay(this->display); +static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer); +static void xxmc_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xxmc_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xxmc_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -2201,6 +2194,52 @@ static void xxmc_update_disable_bob_for_scaled_osd(void *this_gen, xine_cfg_entr this->disable_bob_for_scaled_osd = entry->num_value; } +static int xxmc_open_port (xxmc_driver_t *this, XvPortID port) { + int ret; + x11_InstallXErrorHandler (this); + ret = ! xxmc_check_yv12(this->display, port) + && XvGrabPort(this->display, port, 0) == Success; + x11_DeInstallXErrorHandler (this); + return ret; +} + +static unsigned int +xxmc_find_adaptor_by_port (int port, unsigned int adaptors, + XvAdaptorInfo *adaptor_info) +{ + unsigned int an; + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask) + if (port >= adaptor_info[an].base_id && + port < adaptor_info[an].base_id + adaptor_info[an].num_ports) + return an; + return 0; /* shouldn't happen */ +} + +static XvPortID xxmc_autodetect_port(xxmc_driver_t *this, + unsigned int adaptors, + XvAdaptorInfo *adaptor_info, + unsigned int *adaptor_num, + XvPortID base, + xv_prefertype prefer_type) +{ + unsigned int an, j; + + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask && + (prefer_type == xv_prefer_none || + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) + for (j = 0; j < adaptor_info[an].num_ports; j++) { + XvPortID port = adaptor_info[an].base_id + j; + if (port >= base && xxmc_open_port(this, port)) { + *adaptor_num = an; + return port; + } + } + + return 0; +} + static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) { @@ -2363,17 +2402,18 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; XvImage *myimage; - unsigned int adaptors, j; + unsigned int adaptors; unsigned int ver,rel,req,ev,err; XShmSegmentInfo myshminfo; XvPortID xv_port; XvAdaptorInfo *adaptor_info; unsigned int adaptor_num; + xv_prefertype prefer_type; cfg_entry_t *entry; int use_more_frames; int use_unscaled; - this = (xxmc_driver_t *) xine_xmalloc (sizeof (xxmc_driver_t)); + this = calloc(1, sizeof (xxmc_driver_t)); if (!this) return NULL; @@ -2404,24 +2444,31 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi return NULL; } - xv_port = 0; - - for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) { - - if (adaptor_info[adaptor_num].type & XvImageMask) { - - for (j = 0; j < adaptor_info[adaptor_num].num_ports && !xv_port; j++) - if (( !(xxmc_check_yv12 (this->display, - adaptor_info[adaptor_num].base_id + j))) - && (XvGrabPort (this->display, - adaptor_info[adaptor_num].base_id + j, - 0) == Success)) { - xv_port = adaptor_info[adaptor_num].base_id + j; - } - - if( xv_port ) - break; - } + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xxmc_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %d - autodetecting\n"), + LOG_MODULE, xv_port); + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type); + } else + adaptor_num = xxmc_find_adaptor_by_port (xv_port, adaptors, adaptor_info); + } + if (!xv_port) + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); } if (!xv_port) { @@ -2510,72 +2557,60 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { - if(!strcmp(attr[k].name, "XV_HUE")) { + const char *const name = attr[k].name; + if(!strcmp(name, "XV_HUE")) { if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xxmc: ignoring broken XV_HUE settings on NVidia cards\n"); } else { xxmc_check_capability (this, VO_PROP_HUE, attr[k], - adaptor_info[adaptor_num].base_id, "XV_HUE", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); } - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xxmc_check_capability (this, VO_PROP_SATURATION, attr[k], - adaptor_info[adaptor_num].base_id, "XV_SATURATION", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xxmc_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], - adaptor_info[adaptor_num].base_id, "XV_BRIGHTNESS", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xxmc_check_capability (this, VO_PROP_CONTRAST, attr[k], - adaptor_info[adaptor_num].base_id, "XV_CONTRAST", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xxmc_check_capability (this, VO_PROP_COLORKEY, attr[k], - adaptor_info[adaptor_num].base_id, "XV_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xxmc_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], - adaptor_info[adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attr[k].min_value, attr[k].max_value, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xxmc_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, 20, xxmc_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xxmc_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -2639,8 +2674,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xxmc_update_xv_pitch_alignment, this); use_more_frames= @@ -2744,7 +2778,7 @@ static void dispose_class (video_driver_class_t *this_gen) { } static void *init_class (xine_t *xine, void *visual_gen) { - xxmc_class_t *this = (xxmc_class_t *) xine_xmalloc (sizeof (xxmc_class_t)); + xxmc_class_t *this = calloc(1, sizeof (xxmc_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/x11osd.c b/src/video_out/x11osd.c index e0cb6f1f6..4d0e46287 100644 --- a/src/video_out/x11osd.c +++ b/src/video_out/x11osd.c @@ -245,7 +245,7 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x XSetWindowAttributes attr; XWindowAttributes getattr; - osd = xine_xmalloc (sizeof (x11osd)); + osd = calloc(1, sizeof(x11osd)); if (!osd) return NULL; diff --git a/src/video_out/xcbosd.c b/src/video_out/xcbosd.c index 4bb2b60af..d8cf119a2 100644 --- a/src/video_out/xcbosd.c +++ b/src/video_out/xcbosd.c @@ -238,7 +238,7 @@ xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t * xcb_void_cookie_t generic_cookie; xcb_generic_error_t *generic_error; - osd = xine_xmalloc (sizeof (xcbosd)); + osd = calloc(1, sizeof(xcbosd)); if (!osd) return NULL; diff --git a/src/video_out/xv_common.h b/src/video_out/xv_common.h new file mode 100644 index 000000000..ff49286f0 --- /dev/null +++ b/src/video_out/xv_common.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * xv_common.h: X11 Xv common bits + */ + +#define VIDEO_DEVICE_XV_COLORKEY_HELP \ + _("video overlay colour key"), \ + _("The colour key is used to tell the graphics card where to " \ + "overlay the video image. Try different values, if you "\ + "experience windows becoming transparent.") + +#define VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP \ + _("autopaint colour key"), \ + _("Make Xv autopaint its colour key.") + +#define VIDEO_DEVICE_XV_FILTER_HELP \ + _("bilinear scaling mode"), \ + _("Selects the bilinear scaling mode for Permedia cards. " \ + "The individual values are:\n\n" \ + "Permedia 2\n" \ + "0 - disable bilinear filtering\n" \ + "1 - enable bilinear filtering\n\n" \ + "Permedia 3\n" \ + "0 - disable bilinear filtering\n" \ + "1 - horizontal linear filtering\n" \ + "2 - enable full bilinear filtering") + +#define VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP \ + _("enable double buffering"), \ + _("Double buffering will synchronize the update of the video " \ + "image to the repainting of the entire screen (\"vertical " \ + "retrace\"). This eliminates flickering and tearing artifacts, " \ + "but will use more graphics memory.") + +#define VIDEO_DEVICE_XV_PORT_HELP \ + _("Xv port number"), \ + _("Selects the Xv port number to use (0 to autodetect).") + +#define VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP \ + _("pitch alignment workaround"), \ + _("Some buggy video drivers need a workaround to function properly.") + +#define VIDEO_DEVICE_XV_DECL_SYNC_ATOMS \ + static const char *const sync_atoms[] = \ + { "XV_SYNC_TO_VBLANK", "XV_VSYNC" }; + +#define VIDEO_DEVICE_XV_DECL_PREFER_TYPES \ + typedef enum { \ + xv_prefer_none, xv_prefer_overlay, xv_prefer_textured, xv_prefer_blitter, \ + } xv_prefertype; \ + static const char *const prefer_labels[] = \ + { "Any", "Overlay", "Textured Video", "Blitter", NULL }; \ + static const char prefer_substrings[][8] = \ + { "", "Overlay", "Texture", "Blitter" }; +#define VIDEO_DEVICE_XV_PREFER_TYPE_HELP \ + _("video display method preference"), \ + _("Selects which video output method is preferred. " \ + "Detection is done using the reported Xv adaptor names.\n" \ + "(Only applies when auto-detecting which Xv port to use.)") + +#define VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES \ + static const char *const bicubic_types[] = { "Off", "On", "Auto", NULL }; +#define VIDEO_DEVICE_XV_BICUBIC_HELP \ + _("bicubic filtering"), \ + _("This option controls bicubic filtering of the video image. " \ + "It may be used instead of, or as well as, xine's deinterlacers.") diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h index 1c24991be..03b12c15b 100644 --- a/src/video_out/xxmc.h +++ b/src/video_out/xxmc.h @@ -37,6 +37,14 @@ #define XVMC_THREAD_SAFE +/* + * some implementations are not aware of the display having been locked + * already before calling the xvmc function and may therefore deadlock. + */ +/* +#define XVMC_LOCKDISPLAY_SAFE +*/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -171,7 +179,7 @@ typedef struct context_lock_s { return; \ } -#ifdef XVMC_THREAD_SAFE +#if defined(XVMC_THREAD_SAFE) && defined(XVMC_LOCKDISPLAY_SAFE) #define XVMCLOCKDISPLAY(display) #define XVMCUNLOCKDISPLAY(display) #else diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c index c98dd518f..fb2d63e6c 100644 --- a/src/video_out/yuv2rgb.c +++ b/src/video_out/yuv2rgb.c @@ -3144,7 +3144,7 @@ static void yuy22rgb_c_init (yuv2rgb_factory_t *this) static yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) { - yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t)); + yuv2rgb_t *this = calloc(1, sizeof(yuv2rgb_t)); this->swapped = factory->swapped; this->cmap = factory->cmap; diff --git a/src/video_out/yuv2rgb_mlib.c b/src/video_out/yuv2rgb_mlib.c index 8635526ed..22e67efa8 100644 --- a/src/video_out/yuv2rgb_mlib.c +++ b/src/video_out/yuv2rgb_mlib.c @@ -38,8 +38,6 @@ #include "xineutils.h" #include "yuv2rgb.h" -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - static void mlib_yuv420_rgb24(yuv2rgb_t *this, uint8_t * image, uint8_t * py, uint8_t * pu, uint8_t * pv) |