From f030f9e939d8949d43a6a4c11fc1e7c16617ca8d Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Sat, 16 Feb 2002 22:43:24 +0000 Subject: beginning of video_out_driver changes - driver will ask gui for output size on every frame - shm driver has a seperate yuv2rgb converter instance for every frame - all drivers disabled except xshm, until they're fixed I'm planning to introduce a queue of video_out_events in video_out.c, so events are delivered by video_out_loop which means that all driver functions are called from the same thread (no locking necessary, should help the opengl driver) CVS patchset: 1499 CVS date: 2002/02/16 22:43:24 --- src/video_out/Makefile.am | 19 +- src/video_out/video_out_x11.h | 36 +- src/video_out/video_out_xshm.c | 794 ++++++++++++++++++++--------------------- src/video_out/video_out_xv.c | 6 +- src/video_out/yuv2rgb.c | 160 ++++++--- src/video_out/yuv2rgb.h | 166 +++++---- src/video_out/yuv2rgb_mlib.c | 8 +- src/video_out/yuv2rgb_mmx.c | 18 +- src/xine-engine/load_plugins.c | 45 +-- src/xine-engine/video_out.h | 11 +- 10 files changed, 662 insertions(+), 601 deletions(-) (limited to 'src') diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 5fb10d21a..ad9500cee 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -33,14 +33,17 @@ sdl_module = xineplug_vo_out_sdl.la endif -## -# IMPORTANT: -# --------- -# All of xine video out plugins should be named like the -# scheme "xineplug_vo_out_" -# -lib_LTLIBRARIES = $(xv_module) $(syncfb_module) $(xshm_module) $(aa_module) \ - $(fb_module) $(sdl_module) $(opengl_module) $(directfb_module) + +# important: +# +# all xine video out plugins should be named +# "xineplug_vo_out_*" + +# FIXME: temporarily disabled until they're adapted to new interface +# lib_LTLIBRARIES = $(xv_module) $(syncfb_module) $(xshm_module) $(aa_module) \ +# $(fb_module) $(sdl_module) $(opengl_module) $(directfb_module) + +lib_LTLIBRARIES = $(xshm_module) xineplug_vo_out_xv_la_SOURCES = deinterlace.c alphablend.c video_out_xv.c xineplug_vo_out_xv_la_LIBADD = $(XV_LIB) $(X_LIBS) -lXext diff --git a/src/video_out/video_out_x11.h b/src/video_out/video_out_x11.h index 8bb8c7f49..34479867a 100644 --- a/src/video_out/video_out_x11.h +++ b/src/video_out/video_out_x11.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000-2001 the xine project + * Copyright (C) 2000-2002 the xine project * - * This file is part of xine, a unix video player. + * 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 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_x11.h,v 1.13 2002/01/24 23:09:54 guenter Exp $ + * $Id: video_out_x11.h,v 1.14 2002/02/16 22:43:24 guenter Exp $ * * structs and defines specific to all x11 related output plugins * (any x11 base xine ui should include this) @@ -56,23 +56,25 @@ typedef struct { void *user_data; /* - * calc dest size + * dest size callback * * this will be called by the video driver to find out * how big the video output area size will be for a * given video size. The ui should _not_ adjust it's * video out area, just do some calculations and return - * the size + * the size. This will be called for every frame, ui + * implementation should be fast. */ - void (*calc_dest_size) (void *user_data, - int video_width, int video_height, - int *dest_width, int *dest_height); + void (*dest_size_cb) (void *user_data, + int video_width, int video_height, + int *dest_width, int *dest_height); /* - * request dest size + * frame output callback * - * this will be called by the video driver to request - * the video output area to be resized to fit the video. + * this will be called by the video driver for every frame + * it's about to draw. ui can adapt it's size if necessary + * here. * note: the ui doesn't have to adjust itself to this * size, this is just to be taken as a hint. * ui must return the actual size of the video output @@ -81,10 +83,10 @@ typedef struct { * preserving aspect ration and stuff). */ - void (*request_dest_size) (void *user_data, - int video_width, int video_height, - int *dest_x, int *dest_y, - int *dest_width, int *dest_height); + void (*frame_output_cb) (void *user_data, + int video_width, int video_height, + int *dest_x, int *dest_y, + int *dest_width, int *dest_height); } x11_visual_t; @@ -92,8 +94,6 @@ typedef struct { * constants for gui_data_exchange's data_type parameter */ -/* x11_rectangle_t *data */ -#define GUI_DATA_EX_DEST_POS_SIZE_CHANGED 0 /* xevent *data */ #define GUI_DATA_EX_COMPLETION_EVENT 1 /* Drawable has changed */ @@ -104,8 +104,6 @@ typedef struct { #define GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO 4 /* int *data */ #define GUI_DATA_EX_VIDEOWIN_VISIBLE 5 -/* int *data */ -#define GUI_DATA_EX_FULLSCREEN 7 /* *data contains chosen visual, select a new one or change it to NULL * to indicate the visual to use or that no visual will work */ diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 61e9b3fb2..2b4e591a6 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000, 2001 the xine project + * Copyright (C) 2000-2002 the xine project * - * This file is part of xine, a unix video player. + * 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 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xshm.c,v 1.56 2002/02/09 07:13:24 guenter Exp $ + * $Id: video_out_xshm.c,v 1.57 2002/02/16 22:43:24 guenter Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -59,100 +59,114 @@ #include "yuv2rgb.h" #include "xineutils.h" +#define LOG + extern int XShmGetEventBase(Display *); typedef struct xshm_frame_s { vo_frame_t vo_frame; + /* frame properties as delivered by the decoder: */ int width, height; - int rgb_width, rgb_height; - Drawable drawable_ref; + int ratio_code; + int format; + int flags; + + int user_ratio; + + /* + * "ideal" size of this frame : + * width/height corrected by aspect ratio + */ + + int ideal_width, ideal_height; + + /* + * "gui" size of this frame: + * what gui told us about how much room we have + * to display this frame on + */ + + int gui_width, gui_height; + + /* + * "rgb" size of this frame: + * this is finally the ideal size "fitted" into the + * gui size while maintaining the aspect ratio + */ + + int output_width, output_height; + + + double ratio_factor;/* ideal/rgb size must fulfill: height = width * ratio_factor */ XImage *image; - uint8_t *rgb_dst; - int stripe_inc; XShmSegmentInfo shminfo; - int format; + uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ + + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ + uint8_t *rgb_dst; + int yuv_stride; + int stripe_height, stripe_inc; - uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ } xshm_frame_t; typedef struct xshm_driver_s { - vo_driver_t vo_driver; - - config_values_t *config; - - /* X11 / Xv related stuff */ - Display *display; - int screen; - Drawable drawable; - Visual *visual; - GC gc; - int use_shm; - int zoom_mpeg1; - int scaling_disabled; - int depth, bpp, bytes_per_pixel, image_byte_order; - int expecting_event; - uint8_t *fast_rgb; - - yuv2rgb_t *yuv2rgb; - - xshm_frame_t *cur_frame; - vo_overlay_t *overlay; - - /* size / aspect ratio calculations */ - int delivered_width; /* everything is set up for these frame dimensions */ - int delivered_height; /* the dimension as they come from the decoder */ - int delivered_ratio_code; - int delivered_flags; - double ratio_factor; /* output frame must fulfill: height = width * ratio_factor */ - double output_scale_factor; /* additional scale factor for the output frame */ - int output_width; /* frames will appear in this size (pixels) on screen */ - int output_height; - int stripe_height; - int yuv_width; /* width/height yuv2rgb is configured for */ - int yuv_height; - int yuv_stride; - - int user_ratio; - - int last_frame_rgb_width; /* size of scaled rgb output img gui */ - int last_frame_rgb_height; /* has most recently adopted to */ - Drawable last_frame_drawable_ref; - - int gui_width; /* size of gui window */ - int gui_height; - int gui_changed; - int dest_x; - int dest_y; - - /* display anatomy */ - double display_ratio; /* given by visual parameter from init function */ - - /* profiler */ - int prof_yuv2rgb; - - void *user_data; + vo_driver_t vo_driver; + + config_values_t *config; + + /* X11 / XShm related stuff */ + Display *display; + int screen; + Drawable drawable; + Visual *visual; + GC gc; + int depth, bpp, bytes_per_pixel, image_byte_order; + int use_shm; + + int yuv2rgb_mode; + int yuv2rgb_swap; + int yuv2rgb_gamma; + uint8_t *yuv2rgb_cmap; + yuv2rgb_factory_t *yuv2rgb_factory; + int user_ratio; + + /* speed tradeoffs */ + int zoom_mpeg1; + int scaling_disabled; + + int expecting_event; /* completion event */ + + xshm_frame_t *cur_frame; + vo_overlay_t *overlay; + + /* video pos/size in gui window */ + int gui_x; + int gui_y; + int gui_width; + int gui_height; + + /* aspect ratio of pixels on screen */ + double display_ratio; + + void *user_data; /* gui callbacks */ - void (*request_dest_size) (void *user_data, - int video_width, int video_height, - int *dest_x, int *dest_y, - int *dest_height, int *dest_width); + void (*frame_output_cb) (void *user_data, + int video_width, int video_height, + int *dest_x, int *dest_y, + int *dest_height, int *dest_width); - void (*calc_dest_size) (void *user_data, - int video_width, int video_height, - int *dest_width, int *dest_height); + void (*dest_size_cb) (void *user_data, + int video_width, int video_height, + int *dest_width, int *dest_height); } xshm_driver_t; -/* possible values for xshm_driver_t, field gui_changed */ -#define GUI_SIZE_CHANGED 1 -#define GUI_ASPECT_CHANGED 2 - int gX11Fail; @@ -161,7 +175,7 @@ int gX11Fail; */ vo_info_t *get_video_out_plugin_info(); -int HandleXError (Display *display, XErrorEvent *xevent) { +static int HandleXError (Display *display, XErrorEvent *xevent) { char str [1024]; @@ -349,38 +363,34 @@ static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { static void xshm_frame_copy (vo_frame_t *vo_img, uint8_t **src) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; - xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; - - xine_profiler_start_count (this->prof_yuv2rgb); + /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */ if (frame->format == IMGFMT_YV12) { - this->yuv2rgb->yuv2rgb_fun (this->yuv2rgb, frame->rgb_dst, - src[0], src[1], src[2]); + frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, + src[0], src[1], src[2]); } else { - this->yuv2rgb->yuy22rgb_fun (this->yuv2rgb, frame->rgb_dst, - src[0]); + frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, + src[0]); } - xine_profiler_stop_count (this->prof_yuv2rgb); - frame->rgb_dst += frame->stripe_inc; } static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; - xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; + /* xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */ switch (which_field) { case VO_TOP_FIELD: frame->rgb_dst = (uint8_t *)frame->image->data; - frame->stripe_inc = 2*this->stripe_height * frame->image->bytes_per_line; + frame->stripe_inc = 2*frame->stripe_height * frame->image->bytes_per_line; break; case VO_BOTTOM_FIELD: frame->rgb_dst = (uint8_t *)frame->image->data + frame->image->bytes_per_line ; - frame->stripe_inc = 2*this->stripe_height * frame->image->bytes_per_line; + frame->stripe_inc = 2*frame->stripe_height * frame->image->bytes_per_line; break; case VO_BOTH_FIELDS: frame->rgb_dst = (uint8_t *)frame->image->data; @@ -404,7 +414,9 @@ static void xshm_frame_dispose (vo_frame_t *vo_img) { static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { - xshm_frame_t *frame ; + + xshm_frame_t *frame ; + xshm_driver_t *this = (xshm_driver_t *) this_gen; frame = (xshm_frame_t *) malloc (sizeof (xshm_frame_t)); if (frame==NULL) { @@ -425,41 +437,33 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { frame->vo_frame.dispose = xshm_frame_dispose; frame->vo_frame.driver = this_gen; - return (vo_frame_t *) frame; -} + /* + * colorspace converter for this frame + */ -static void xshm_calc_output_size (xshm_driver_t *this) { + frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); - double image_ratio, desired_ratio; - double corr_factor, x_factor, y_factor; - int ideal_width, ideal_height; - int dest_width, dest_height; - /* - * aspect ratio calculation - */ + return (vo_frame_t *) frame; +} - if (this->delivered_width == 0 && this->delivered_height == 0) - return; /* ConfigureNotify/VisibilityNotify, no decoder output size known */ +static void xshm_compute_ideal_size (xshm_driver_t *this, xshm_frame_t *frame) { if (this->scaling_disabled) { - /* quick hack to allow testing of unscaled yuv2rgb conversion routines */ - this->output_width = this->delivered_width; - this->output_height = this->delivered_height; - this->ratio_factor = 1.0; - this->calc_dest_size (this->user_data, - this->output_width, this->output_height, - &dest_width, &dest_height); + frame->ideal_width = frame->width; + frame->ideal_height = frame->height; + frame->ratio_factor = 1.0; } else { + + double image_ratio, desired_ratio, corr_factor; - image_ratio = - (double) this->delivered_width / (double) this->delivered_height; + image_ratio = (double) frame->width / (double) frame->height; - switch (this->user_ratio) { + switch (frame->user_ratio) { case ASPECT_AUTO: - switch (this->delivered_ratio_code) { + switch (frame->ratio_code) { case XINE_ASPECT_RATIO_ANAMORPHIC: /* anamorphic */ desired_ratio = 16.0 /9.0; break; @@ -474,7 +478,7 @@ static void xshm_calc_output_size (xshm_driver_t *this) { printf ("video_out_xshm: invalid ratio, using 4:3\n"); default: printf ("video_out_xshm: unknown aspect ratio (%d) in stream => using 4:3\n", - this->delivered_ratio_code); + frame->ratio_code); case XINE_ASPECT_RATIO_4_3: /* 4:3 */ desired_ratio = 4.0 / 3.0; break; @@ -494,74 +498,57 @@ static void xshm_calc_output_size (xshm_driver_t *this) { desired_ratio = 4.0 / 3.0; } - this->ratio_factor = this->display_ratio * desired_ratio; - - /* - * calc ideal output frame size - */ + frame->ratio_factor = this->display_ratio * desired_ratio; - corr_factor = this->ratio_factor / image_ratio ; + corr_factor = frame->ratio_factor / image_ratio ; if (fabs(corr_factor - 1.0) < 0.005) { - ideal_width = this->delivered_width; - ideal_height = this->delivered_height; - } - else if (corr_factor >= 1.0) { - ideal_width = this->delivered_width * corr_factor + 0.5; - ideal_height = this->delivered_height; - } - else { - ideal_width = this->delivered_width; - ideal_height = this->delivered_height / corr_factor + 0.5; - } - - /* little hack to zoom mpeg1 / other small streams by default*/ - if ( this->use_shm && this->zoom_mpeg1 && (this->delivered_width<400)) { - ideal_width *= 2; - ideal_height *= 2; - } + frame->ideal_width = frame->width; + frame->ideal_height = frame->height; - if (fabs(this->output_scale_factor - 1.0) > 0.005) { - ideal_width *= this->output_scale_factor; - ideal_height *= this->output_scale_factor; - } - - /* yuv2rgb_mmx prefers "width%8 == 0" */ - /* but don't change if it would introduce scaling */ - if( ideal_width != this->delivered_width || - ideal_height != this->delivered_height ) - ideal_width &= ~7; + } else { - this->calc_dest_size (this->user_data, - ideal_width, ideal_height, - &dest_width, &dest_height); + if (corr_factor >= 1.0) { + frame->ideal_width = frame->width * corr_factor + 0.5; + frame->ideal_height = frame->height; + } else { + frame->ideal_width = frame->width; + frame->ideal_height = frame->height / corr_factor + 0.5; + } - /* - * make the frames fit into the given destination area - */ + } + } +} - x_factor = (double) dest_width / (double) ideal_width; - y_factor = (double) dest_height / (double) ideal_height; +static void xshm_compute_rgb_size (xshm_driver_t *this, xshm_frame_t *frame) { - if ( x_factor < y_factor ) { - this->output_width = (double) ideal_width * x_factor ; - this->output_height = (double) ideal_height * x_factor ; - } else { - this->output_width = (double) ideal_width * y_factor ; - this->output_height = (double) ideal_height * y_factor ; - } + double x_factor, y_factor; + /* + * make the frame fit into the given destination area + */ + + x_factor = (double) frame->gui_width / (double) frame->ideal_width; + y_factor = (double) frame->gui_height / (double) frame->ideal_height; + + if ( x_factor < y_factor ) { + frame->output_width = (double) frame->ideal_width * x_factor ; + frame->output_height = (double) frame->ideal_height * x_factor ; + } else { + frame->output_width = (double) frame->ideal_width * y_factor ; + frame->output_height = (double) frame->ideal_height * y_factor ; } - printf("video_out_xshm: " - "frame source %d x %d => screen output %d x %d%s\n", - this->delivered_width, this->delivered_height, - this->output_width, this->output_height, - ( this->delivered_width != this->output_width - || this->delivered_height != this->output_height +#ifdef LOG + printf("video_out_xshm: frame source %d x %d => screen output %d x %d%s\n", + frame->width, frame->height, + frame->output_width, frame->output_height, + ( frame->width != frame->output_width + || frame->height != frame->output_height ? ", software scaling" : "" ) ); +#endif } static void xshm_update_frame_format (vo_driver_t *this_gen, @@ -571,41 +558,63 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, xshm_driver_t *this = (xshm_driver_t *) this_gen; xshm_frame_t *frame = (xshm_frame_t *) frame_gen; - int setup_yuv = 0; + int do_adapt; + int gui_width, gui_height; flags &= VO_BOTH_FIELDS; - frame->drawable_ref = this->drawable; + /* find out if we need to adapt this frame */ - if ((width != this->delivered_width) - || (height != this->delivered_height) - || (ratio_code != this->delivered_ratio_code) - || (flags != this->delivered_flags) - || this->gui_changed) { + do_adapt = 0; - this->delivered_width = width; - this->delivered_height = height; - this->delivered_ratio_code = ratio_code; - this->delivered_flags = flags; - this->gui_changed = 0; - - xshm_calc_output_size (this); + if ((width != frame->width) + || (height != frame->height) + || (ratio_code != frame->ratio_code) + || (flags != frame->flags) + || (this->user_ratio != frame->user_ratio)) { - setup_yuv = 1; + do_adapt = 1; + +#ifdef LOG + printf ("video_out_xshm: frame format (from decoder) has changed => adapt\n"); +#endif + + frame->width = width; + frame->height = height; + frame->ratio_code = ratio_code; + frame->flags = flags; + frame->user_ratio = this->user_ratio; + + xshm_compute_ideal_size (this, frame); } - if ((frame->rgb_width != this->output_width) - || (frame->rgb_height != this->output_height) - || (frame->width != width) - || (frame->height != height) - || (frame->format != format)) { + /* ask gui what output size we'll have for this frame*/ - int image_size; + this->dest_size_cb (this->user_data, frame->ideal_width, frame->ideal_height, + &gui_width, &gui_height); - /* + if ((frame->gui_width != gui_width) || (frame->gui_height != gui_height)) { + + do_adapt = 1; + frame->gui_width = gui_width; + frame->gui_height = gui_height; + + xshm_compute_rgb_size (this, frame); + +#ifdef LOG + printf ("video_out_xshm: gui_size has changed => adapt\n"); +#endif + } + + + /* ok, now do what we have to do */ + + if (do_adapt) { + +#ifdef LOG printf ("video_out_xshm: updating frame to %d x %d\n", - this->output_width,this->output_height); - */ + frame->output_width, frame->output_height); +#endif XLockDisplay (this->display); @@ -634,109 +643,93 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, } frame->image = create_ximage (this, &frame->shminfo, - this->output_width, this->output_height); + frame->output_width, frame->output_height); XUnlockDisplay (this->display); if (format == IMGFMT_YV12) { - image_size = width * height; - frame->vo_frame.base[0] = my_malloc_aligned(16,image_size, &frame->chunk[0]); - frame->vo_frame.base[1] = my_malloc_aligned(16,image_size/4, &frame->chunk[1]); - frame->vo_frame.base[2] = my_malloc_aligned(16,image_size/4, &frame->chunk[2]); + int image_size = frame->width * frame->height; + frame->vo_frame.base[0] = my_malloc_aligned (16, image_size, &frame->chunk[0]); + frame->vo_frame.base[1] = my_malloc_aligned (16, image_size/4, &frame->chunk[1]); + frame->vo_frame.base[2] = my_malloc_aligned (16, image_size/4, &frame->chunk[2]); } else { - image_size = width * height; - frame->vo_frame.base[0] = my_malloc_aligned(16,image_size*2, &frame->chunk[0]); + int image_size = frame->width * frame->height; + frame->vo_frame.base[0] = my_malloc_aligned (16, image_size*2, &frame->chunk[0]); + frame->chunk[1] = NULL; + frame->chunk[2] = NULL; } - - frame->format = format; - frame->width = width; - frame->height = height; - - frame->rgb_width = this->output_width; - frame->rgb_height = this->output_height; - } - if (frame->image) { - this->stripe_height = 16 * this->output_height / this->delivered_height; + frame->stripe_height = 16 * frame->output_height / frame->height; frame->rgb_dst = (uint8_t *)frame->image->data; switch (flags) { case VO_TOP_FIELD: frame->rgb_dst = (uint8_t *)frame->image->data; - frame->stripe_inc = 2 * this->stripe_height * frame->image->bytes_per_line; + frame->stripe_inc = 2 * frame->stripe_height * frame->image->bytes_per_line; break; case VO_BOTTOM_FIELD: frame->rgb_dst = (uint8_t *)frame->image->data + frame->image->bytes_per_line ; - frame->stripe_inc = 2 * this->stripe_height * frame->image->bytes_per_line; + frame->stripe_inc = 2 * frame->stripe_height * frame->image->bytes_per_line; break; case VO_BOTH_FIELDS: frame->rgb_dst = (uint8_t *)frame->image->data; - frame->stripe_inc = this->stripe_height * frame->image->bytes_per_line; + frame->stripe_inc = frame->stripe_height * frame->image->bytes_per_line; break; } - if (flags == VO_BOTH_FIELDS) { - if (this->yuv_stride != frame->image->bytes_per_line) - setup_yuv = 1; - } else { /* VO_TOP_FIELD, VO_BOTTOM_FIELD */ - if (this->yuv_stride != (frame->image->bytes_per_line*2)) - setup_yuv = 1; - } + /* + * set up colorspace converter + */ - if (setup_yuv - || (this->yuv_height != this->stripe_height) - || (this->yuv_width != this->output_width)) { - switch (flags) { - case VO_TOP_FIELD: - case VO_BOTTOM_FIELD: - yuv2rgb_setup (this->yuv2rgb, - this->delivered_width, - 16, - this->delivered_width*2, - this->delivered_width, - this->output_width, - this->stripe_height, - frame->image->bytes_per_line*2); - this->yuv_stride = frame->image->bytes_per_line*2; - break; - case VO_BOTH_FIELDS: - yuv2rgb_setup (this->yuv2rgb, - this->delivered_width, - 16, - this->delivered_width, - this->delivered_width/2, - this->output_width, - this->stripe_height, - frame->image->bytes_per_line); - this->yuv_stride = frame->image->bytes_per_line; - break; - } - this->yuv_height = this->stripe_height; - this->yuv_width = this->output_width; + switch (flags) { + case VO_TOP_FIELD: + case VO_BOTTOM_FIELD: + frame->yuv2rgb->configure (frame->yuv2rgb, + frame->width, + 16, + frame->width*2, + frame->width, + frame->output_width, + frame->stripe_height, + frame->image->bytes_per_line*2); + frame->yuv_stride = frame->image->bytes_per_line*2; + break; + case VO_BOTH_FIELDS: + frame->yuv2rgb->configure (frame->yuv2rgb, + frame->width, + 16, + frame->width, + frame->width/2, + frame->output_width, + frame->stripe_height, + frame->image->bytes_per_line); + frame->yuv_stride = frame->image->bytes_per_line; + break; } } } -static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overlay) -{ +static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overlay, + xshm_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->yuv2rgb->yuv2rgb_single_pixel_fun(this->yuv2rgb, - clut[i].y, clut[i].cb, clut[i].cr); + frame->yuv2rgb->yuv2rgb_single_pixel_fun (frame->yuv2rgb, + clut[i].y, clut[i].cb, clut[i].cr); } - overlay->rgb_clut++; + overlay->rgb_clut++; } if (!overlay->clip_rgb_clut) { clut = (clut_t*) overlay->clip_color; for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) { *((uint32_t *)&clut[i]) = - this->yuv2rgb->yuv2rgb_single_pixel_fun(this->yuv2rgb, - clut[i].y, clut[i].cb, clut[i].cr); + frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, + clut[i].y, clut[i].cb, clut[i].cr); } - overlay->clip_rgb_clut++; + overlay->clip_rgb_clut++; } } @@ -746,27 +739,27 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo /* Alpha Blend here */ if (overlay->rle) { - if( !overlay->rgb_clut || !overlay->clip_rgb_clut) - xshm_overlay_clut_yuv2rgb(this,overlay); + if (!overlay->rgb_clut || !overlay->clip_rgb_clut) + xshm_overlay_clut_yuv2rgb (this, overlay, frame); - switch(this->bpp) { + switch (this->bpp) { case 16: - blend_rgb16( (uint8_t *)frame->image->data, overlay, - frame->rgb_width, frame->rgb_height, - this->delivered_width, this->delivered_height); + blend_rgb16 ((uint8_t *)frame->image->data, overlay, + frame->output_width, frame->output_height, + frame->width, frame->height); break; case 24: - blend_rgb24( (uint8_t *)frame->image->data, overlay, - frame->rgb_width, frame->rgb_height, - this->delivered_width, this->delivered_height); + blend_rgb24 ((uint8_t *)frame->image->data, overlay, + frame->output_width, frame->output_height, + frame->width, frame->height); break; case 32: - blend_rgb32( (uint8_t *)frame->image->data, overlay, - frame->rgb_width, frame->rgb_height, - this->delivered_width, this->delivered_height); + blend_rgb32 ((uint8_t *)frame->image->data, overlay, + frame->output_width, frame->output_height, + frame->width, frame->height); break; default: - /* It should never get here */ + /* it should never get here */ break; } } @@ -779,52 +772,74 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { int xoffset; int yoffset; +#ifdef LOG + printf ("video_out_xshm: display frame...\n"); +#endif + if (this->expecting_event) { +#ifdef LOG + printf ("video_out_xshm: display frame...expecting event (%d)\n", + this->expecting_event); +#endif this->expecting_event--; frame->vo_frame.displayed (&frame->vo_frame); } else { - if ( (frame->rgb_width != this->last_frame_rgb_width) - || (frame->rgb_height != this->last_frame_rgb_height) - || (frame->drawable_ref != this->last_frame_drawable_ref) ) { + int gui_x, gui_y, gui_width, gui_height; - /* - xprintf (VIDEO, "video_out_xshm: requesting dest size of %d x %d \n", - frame->rgb_width, frame->rgb_height); - */ +#ifdef LOG + printf ("video_out_xshm: about to draw frame %d x %d...\n", + frame->output_width, frame->output_height); +#endif - this->request_dest_size (this->user_data, - frame->rgb_width, frame->rgb_height, - &this->dest_x, &this->dest_y, - &this->gui_width, &this->gui_height); - /* for fullscreen modes, clear unused areas of old video area */ - XClearWindow(this->display, this->drawable); + /* + * tell gui that we are about to display a frame, + * ask for offset + */ - this->last_frame_rgb_width = frame->rgb_width; - this->last_frame_rgb_height = frame->rgb_height; - this->last_frame_drawable_ref = frame->drawable_ref; + this->frame_output_cb (this->user_data, + frame->output_width, frame->output_height, + &gui_x, &gui_y, &gui_width, &gui_height); - printf ("video_out_xshm: gui size %d x %d, frame size %d x %d\n", - this->gui_width, this->gui_height, - frame->rgb_width, frame->rgb_height); + XLockDisplay (this->display); +#ifdef LOG + printf ("video_out_xshm: display locked...\n"); +#endif + + if ( (this->gui_x != gui_x) || (this->gui_y != gui_y) + || (this->gui_width != gui_width) + || (this->gui_height != gui_height) ) { + + /* + * clear unused areas of old video area + * + * FIXME: really just clear those areas, not the whole window + * + */ + XClearWindow(this->display, this->drawable); + this->gui_x = gui_x; + this->gui_y = gui_y; + this->gui_width = gui_width; + this->gui_height = gui_height; } - XLockDisplay (this->display); - if( this->cur_frame ) this->cur_frame->vo_frame.displayed (&this->cur_frame->vo_frame); this->cur_frame = frame; - xoffset = (this->gui_width - frame->rgb_width) / 2; - yoffset = (this->gui_height - frame->rgb_height) / 2; + xoffset = (this->gui_width - frame->output_width) / 2 + this->gui_x; + yoffset = (this->gui_height - frame->output_height) / 2 + this->gui_y; if (this->use_shm) { +#ifdef LOG + printf ("video_out_xshm: put image (shm)\n"); +#endif XShmPutImage(this->display, this->drawable, this->gc, frame->image, 0, 0, xoffset, yoffset, - frame->rgb_width, frame->rgb_height, True); + frame->output_width, frame->output_height, True); this->expecting_event = 10; @@ -832,10 +847,14 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { } else { +#ifdef LOG + printf ("video_out_xshm: put image (plain/remote)\n"); +#endif + XPutImage(this->display, this->drawable, this->gc, frame->image, 0, 0, xoffset, yoffset, - frame->rgb_width, frame->rgb_height); + frame->output_width, frame->output_height); XFlush(this->display); @@ -846,6 +865,10 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { XUnlockDisplay (this->display); } + +#ifdef LOG + printf ("video_out_xshm: display frame done\n"); +#endif } static int xshm_get_property (vo_driver_t *this_gen, int property) { @@ -855,7 +878,7 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { if ( property == VO_PROP_ASPECT_RATIO) { return this->user_ratio ; } else if ( property == VO_PROP_BRIGHTNESS) { - return yuv2rgb_get_gamma(this->yuv2rgb); + return this->yuv2rgb_gamma; } else { printf ("video_out_xshm: tried to get unsupported property %d\n", property); } @@ -863,8 +886,8 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { return 0; } -static char *aspect_ratio_name(int a) -{ +static char *aspect_ratio_name(int a) { + switch (a) { case ASPECT_AUTO: return "auto"; @@ -887,16 +910,19 @@ static int xshm_set_property (vo_driver_t *this_gen, xshm_driver_t *this = (xshm_driver_t *) this_gen; if ( property == VO_PROP_ASPECT_RATIO) { + if (value>=NUM_ASPECT_RATIOS) value = ASPECT_AUTO; this->user_ratio = value; - this->gui_changed |= GUI_ASPECT_CHANGED; - printf("video_out_xshm: aspect ratio changed to %s\n", - aspect_ratio_name(value)); + printf ("video_out_xshm: aspect ratio changed to %s\n", + aspect_ratio_name(value)); + } else if ( property == VO_PROP_BRIGHTNESS) { - yuv2rgb_set_gamma(this->yuv2rgb,value); - printf("video_out_xshm: gamma changed to %d\n",value); + this->yuv2rgb_gamma = value; + this->yuv2rgb_factory->set_gamma (this->yuv2rgb_factory, value); + + printf ("video_out_xshm: gamma changed to %d\n",value); } else { printf ("video_out_xshm: tried to set unsupported property %d\n", property); } @@ -918,25 +944,20 @@ static void xshm_get_property_min_max (vo_driver_t *this_gen, } -static int is_fullscreen_size (xshm_driver_t *this, int w, int h) -{ - return w == DisplayWidth(this->display, this->screen) - && h == DisplayHeight(this->display, this->screen); -} +static void xshm_translate_gui2video (xshm_driver_t *this, + xshm_frame_t * frame, + int x, int y, + int *vid_x, int *vid_y) { -static void xshm_translate_gui2video(xshm_driver_t *this, - int x, int y, - int *vid_x, int *vid_y) -{ - if (this->output_width > 0 && this->output_height > 0) { + if ( (frame->output_width > 0) && (frame->output_height > 0)) { /* * 1. * the xshm driver may center a small output area inside a larger * gui area. This is the case in fullscreen mode, where we often * have black borders on the top/bottom/left/right side. */ - x -= (this->gui_width - this->output_width) >> 1; - y -= (this->gui_height - this->output_height) >> 1; + x -= ((this->gui_width - frame->output_width) >> 1) + this->gui_x; + y -= ((this->gui_height - frame->output_height) >> 1) + this->gui_y; /* * 2. @@ -944,8 +965,8 @@ static void xshm_translate_gui2video(xshm_driver_t *this, * translate output area coordianates into the delivered area * coordiantes. */ - x = x * this->delivered_width / this->output_width; - y = y * this->delivered_height / this->output_height; + x = x * frame->width / frame->output_width; + y = y * frame->height / frame->output_height; } *vid_x = x; @@ -953,70 +974,11 @@ static void xshm_translate_gui2video(xshm_driver_t *this, } static int xshm_gui_data_exchange (vo_driver_t *this_gen, - int data_type, void *data) { + int data_type, void *data) { xshm_driver_t *this = (xshm_driver_t *) this_gen; - x11_rectangle_t *area; switch (data_type) { - case GUI_DATA_EX_DEST_POS_SIZE_CHANGED: - - area = (x11_rectangle_t *) data; - - XLockDisplay (this->display); - - if (this->gui_width != area->w || this->gui_height != area->h) { - - printf("video_out_xshm: video window size changed from %d x %d to %d x %d\n", - this->gui_width, this->gui_height, - area->w, area->h); - - /* - * if the old or new video window size size is not for the - * fullscreen frame, update our output_scale_factor. We - * preserve the non-fullscreen output_scale_factor to be able to - * restore the old window size when going back from fullscreen - * to windowing mode. - */ - if (this->gui_width > 0 && this->gui_height > 0 - && !is_fullscreen_size(this, this->gui_width, this->gui_height) - && !is_fullscreen_size(this, area->w, area->h)) { - double log_scale; - double int_scale; - - this->output_scale_factor *= - sqrt( (double) (area->w * area->h) - / (double) (this->gui_width * this->gui_height) ); - - /* - * if we are near an exact power of 1.2, round the output_scale_factor - * to the exact value, to increase the chance that we can avoid - * the software image scaler. - */ - log_scale = log(this->output_scale_factor) / log(1.2); - int_scale = rint(log_scale); - if (fabs(log_scale - int_scale) < 0.03) - this->output_scale_factor = pow(1.2, int_scale); - } - printf("video_out_xshm: output_scale %f\n", this->output_scale_factor); - - /* - * The GUI_DATA_EX_DEST_POS_SIZE_CHANGED notification might be - * slow, and we may already have painted frames at the wrong - * position on the resized window. Just clear the window. - */ - XClearWindow(this->display, this->drawable); - - this->gui_width = area->w; - this->gui_height = area->h; - - this->gui_changed |= GUI_SIZE_CHANGED; - } - - XUnlockDisplay (this->display); - - - break; case GUI_DATA_EX_COMPLETION_EVENT: { XShmCompletionEvent *cev = (XShmCompletionEvent *) data; @@ -1035,6 +997,8 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, case GUI_DATA_EX_EXPOSE_EVENT: +#if 0 + /* FIXME : take care of completion events */ if (this->cur_frame) { @@ -1047,15 +1011,15 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, XLockDisplay (this->display); - xoffset = (this->gui_width - this->cur_frame->rgb_width) / 2; - yoffset = (this->gui_height - this->cur_frame->rgb_height) / 2; + xoffset = (this->gui_width - this->cur_frame->output_width) / 2; + yoffset = (this->gui_height - this->cur_frame->output_height) / 2; if (this->use_shm) { XShmPutImage(this->display, this->drawable, this->gc, this->cur_frame->image, 0, 0, xoffset, yoffset, - this->cur_frame->rgb_width, this->cur_frame->rgb_height, + this->cur_frame->output_width, this->cur_frame->output_height, False); } else { @@ -1063,7 +1027,7 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, XPutImage(this->display, this->drawable, this->gc, this->cur_frame->image, 0, 0, xoffset, yoffset, - this->cur_frame->rgb_width, this->cur_frame->rgb_height); + this->cur_frame->output_width, this->cur_frame->output_height); } XFlush (this->display); @@ -1071,6 +1035,8 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, } } +#endif + break; case GUI_DATA_EX_DRAWABLE_CHANGED: @@ -1082,19 +1048,24 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, break; case GUI_DATA_EX_TRANSLATE_GUI_TO_VIDEO: - { - int x1, y1, x2, y2; - x11_rectangle_t *rect = data; - xshm_translate_gui2video(this, rect->x, rect->y, + if (this->cur_frame) { + + x11_rectangle_t *rect = data; + int x1, y1, x2, y2; + + xshm_translate_gui2video(this, this->cur_frame, + rect->x, rect->y, &x1, &y1); - xshm_translate_gui2video(this, rect->x + rect->w, rect->y + rect->h, + xshm_translate_gui2video(this, this->cur_frame, + rect->x + rect->w, rect->y + rect->h, &x2, &y2); rect->x = x1; rect->y = y1; rect->w = x2-x1; rect->h = y2-y1; } + break; default: @@ -1111,9 +1082,8 @@ static void xshm_exit (vo_driver_t *this_gen) { } -static int -ImlibPaletteLUTGet(xshm_driver_t *this) -{ +static int ImlibPaletteLUTGet(xshm_driver_t *this) { + unsigned char *retval; Atom type_ret; unsigned long bytes_after, num_ret; @@ -1134,9 +1104,9 @@ ImlibPaletteLUTGet(xshm_driver_t *this) num_colors = retval[0]; j = 1 + num_colors*4; - this->fast_rgb = malloc(sizeof(uint8_t) * 32 * 32 * 32); + this->yuv2rgb_cmap = malloc(sizeof(uint8_t) * 32 * 32 * 32); for (i = 0; i < 32 * 32 * 32 && j < num_ret; i++) - this->fast_rgb[i] = retval[1+4*retval[j++]+3]; + this->yuv2rgb_cmap[i] = retval[1+4*retval[j++]+3]; XFree(retval); return 1; @@ -1147,8 +1117,8 @@ ImlibPaletteLUTGet(xshm_driver_t *this) } -static char *visual_class_name(Visual *visual) -{ +static char *visual_class_name(Visual *visual) { + switch (visual->class) { case StaticGray: return "StaticGray"; @@ -1199,14 +1169,14 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->display = visual->display; this->screen = visual->screen; this->display_ratio = visual->display_ratio; - this->request_dest_size = visual->request_dest_size; - this->calc_dest_size = visual->calc_dest_size; + this->frame_output_cb = visual->frame_output_cb; + this->dest_size_cb = visual->dest_size_cb; this->user_data = visual->user_data; - this->output_width = 0; - this->output_height = 0; - this->output_scale_factor = 1.0; + this->gui_x = 0; + this->gui_y = 0; this->gui_width = 0; this->gui_height = 0; + this->user_ratio = ASPECT_AUTO; this->zoom_mpeg1 = config->register_bool (config, "video.zoom_mpeg1", 1, "Zoom small video formats to double size", NULL, NULL, NULL); @@ -1218,14 +1188,14 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { * 1: enable aspect ratio switch * 2: like 1, double the size for small videos */ - this->scaling_disabled = getenv("VIDEO_OUT_NOSCALE") != NULL; + this->scaling_disabled = config->register_bool (config, "video.disable_scaling", 0, + "disable all video scaling", + NULL, NULL, NULL); this->drawable = visual->d; this->expecting_event = 0; this->gc = XCreateGC (this->display, this->drawable, 0, NULL); - this->prof_yuv2rgb = xine_profiler_allocate_slot ("xshm yuv2rgb convert"); - this->vo_driver.get_capabilities = xshm_get_capabilities; this->vo_driver.alloc_frame = xshm_alloc_frame; this->vo_driver.update_frame_format = xshm_update_frame_format; @@ -1254,7 +1224,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { XGetWindowAttributes(display, this->drawable, &attribs); this->visual = attribs.visual; this->depth = attribs.depth; - + if (this->depth>16) printf ("\n\n" "WARNING: current display depth is %d. For better performance\n" @@ -1352,20 +1322,26 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { return NULL; } - this->yuv2rgb = yuv2rgb_init (mode, swapped, this->fast_rgb); - yuv2rgb_set_gamma(this->yuv2rgb, config->register_range (config, "video.xshm_gamma", 0, - -100, 100, "gamma correction for XShm driver", - NULL, NULL, NULL)); + this->yuv2rgb_mode = mode; + this->yuv2rgb_swap = swapped; + this->yuv2rgb_gamma = config->register_range (config, "video.xshm_gamma", 0, + -100, 100, + "gamma correction for XShm driver", + NULL, NULL, NULL); + + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, + this->yuv2rgb_cmap); + this->yuv2rgb_factory->set_gamma (this->yuv2rgb_factory, this->yuv2rgb_gamma); return &this->vo_driver; } static vo_info_t vo_info_shm = { - 3, - "XShm", + 4, /* interface version */ + "XShm", /* id */ "xine video output plugin using the MIT X shared memory extension", - VISUAL_TYPE_X11, - 5 + VISUAL_TYPE_X11, /* visual_type */ + 6 }; vo_info_t *get_video_out_plugin_info() { diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 30aadd009..1b3183f18 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2000, 2001 the xine project + * Copyright (C) 2000-2002 the xine project * - * This file is part of xine, a unix video player. + * 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 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xv.c,v 1.91 2002/02/09 07:13:24 guenter Exp $ + * $Id: video_out_xv.c,v 1.92 2002/02/16 22:43:24 guenter Exp $ * * video_out_xv.c, X11 video extension interface for xine * diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c index 587292618..522d72278 100644 --- a/src/video_out/yuv2rgb.c +++ b/src/video_out/yuv2rgb.c @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: yuv2rgb.c,v 1.27 2001/11/17 14:26:39 f1rmb Exp $ + * $Id: yuv2rgb.c,v 1.28 2002/02/16 22:43:24 guenter Exp $ */ #include "config.h" @@ -68,11 +68,11 @@ static void *my_malloc_aligned (size_t alignment, size_t size, void **chunk) { } -int yuv2rgb_setup (yuv2rgb_t *this, - int source_width, int source_height, - int y_stride, int uv_stride, - int dest_width, int dest_height, - int rgb_stride) { +static int yuv2rgb_configure (yuv2rgb_t *this, + int source_width, int source_height, + int y_stride, int uv_stride, + int dest_width, int dest_height, + int rgb_stride) { /* printf ("yuv2rgb setup (%d x %d => %d x %d)\n", source_width, source_height, dest_width, dest_height); @@ -1265,15 +1265,15 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest, #define DST1CMAP(i) \ Y = py_1[2*i]; \ - dst_1[2*i] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; \ + dst_1[2*i] = this->cmap[r[Y] + g[Y] + b[Y]]; \ Y = py_1[2*i+1]; \ - dst_1[2*i+1] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; + dst_1[2*i+1] = this->cmap[r[Y] + g[Y] + b[Y]]; #define DST2CMAP(i) \ Y = py_2[2*i]; \ - dst_2[2*i] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; \ + dst_2[2*i] = this->cmap[r[Y] + g[Y] + b[Y]]; \ Y = py_2[2*i+1]; \ - dst_2[2*i+1] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; + dst_2[2*i+1] = this->cmap[r[Y] + g[Y] + b[Y]]; static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) @@ -2088,7 +2088,7 @@ static int div_round (int dividend, int divisor) return -((-dividend + (divisor>>1)) / divisor); } -static void yuv2rgb_setup_tables (yuv2rgb_t *this, int mode, int swapped) +static void yuv2rgb_setup_tables (yuv2rgb_factory_t *this, int mode, int swapped) { int i; uint8_t table_Y[1024]; @@ -2334,13 +2334,13 @@ static uint32_t yuv2rgb_single_pixel_palette (yuv2rgb_t *this, uint8_t y, uint8_ g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]); b = this->table_bU[u]; - return this->fast_rgb[r[y] + g[y] + b[y]]; + return this->cmap[r[y] + g[y] + b[y]]; } -static void yuv2rgb_c_init (yuv2rgb_t *this, int mode, int swapped) +static void yuv2rgb_c_init (yuv2rgb_factory_t *this) { - switch (mode) { + switch (this->mode) { case MODE_32_RGB: case MODE_32_BGR: this->yuv2rgb_fun = yuv2rgb_c_32; @@ -2349,7 +2349,7 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode, int swapped) case MODE_24_RGB: case MODE_24_BGR: this->yuv2rgb_fun = - (mode==MODE_24_RGB && !swapped) || (mode==MODE_24_BGR && swapped) + (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; break; @@ -2375,15 +2375,15 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode, int swapped) break; default: - fprintf (stderr, "mode %d not supported by yuv2rgb\n", mode); + printf ("yuv2rgb: mode %d not supported by yuv2rgb\n", this->mode); exit (1); } } -static void yuv2rgb_single_pixel_init (yuv2rgb_t *this, int mode, int swapped) -{ - switch (mode) { +static void yuv2rgb_single_pixel_init (yuv2rgb_factory_t *this) { + + switch (this->mode) { case MODE_32_RGB: case MODE_32_BGR: this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_32; @@ -2392,7 +2392,7 @@ static void yuv2rgb_single_pixel_init (yuv2rgb_t *this, int mode, int swapped) case MODE_24_RGB: case MODE_24_BGR: this->yuv2rgb_single_pixel_fun = - (mode==MODE_24_RGB && !swapped) || (mode==MODE_24_BGR && swapped) + (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped) ? yuv2rgb_single_pixel_24_rgb : yuv2rgb_single_pixel_24_bgr; break; @@ -2418,7 +2418,7 @@ static void yuv2rgb_single_pixel_init (yuv2rgb_t *this, int mode, int swapped) break; default: - fprintf (stderr, "mode %d not supported by yuv2rgb\n", mode); + printf ("yuv2rgb: mode %d not supported by yuv2rgb\n", this->mode); exit (1); } } @@ -2916,9 +2916,9 @@ static void yuy22rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) } } -static void yuy22rgb_c_init (yuv2rgb_t *this, int mode, int swapped) +static void yuy22rgb_c_init (yuv2rgb_factory_t *this) { - switch (mode) { + switch (this->mode) { case MODE_32_RGB: case MODE_32_BGR: this->yuy22rgb_fun = yuy22rgb_c_32; @@ -2927,7 +2927,7 @@ static void yuy22rgb_c_init (yuv2rgb_t *this, int mode, int swapped) case MODE_24_RGB: case MODE_24_BGR: this->yuy22rgb_fun = - (mode==MODE_24_RGB && !swapped) || (mode==MODE_24_BGR && swapped) + (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped) ? yuy22rgb_c_24_rgb : yuy22rgb_c_24_bgr; break; @@ -2952,26 +2952,78 @@ static void yuy22rgb_c_init (yuv2rgb_t *this, int mode, int swapped) break; default: - printf ("yuv2rgb: mode %d not supported for yuy2\n", mode); + printf ("yuv2rgb: mode %d not supported for yuy2\n", this->mode); } } -yuv2rgb_t *yuv2rgb_init (int mode, int swapped, uint8_t *colormap) { +yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) { + + yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t)); + + this->cmap = factory->cmap; + + this->y_chunk = this->y_buffer = NULL; + this->u_chunk = this->u_buffer = NULL; + this->v_chunk = this->v_buffer = NULL; + + this->table_rV = factory->table_rV; + this->table_gU = factory->table_gU; + this->table_gV = factory->table_gV; + this->table_bU = factory->table_bU; + + this->yuv2rgb_fun = factory->yuv2rgb_fun; + this->yuy22rgb_fun = factory->yuy22rgb_fun; + this->yuv2rgb_single_pixel_fun = factory->yuv2rgb_single_pixel_fun; + + this->configure = yuv2rgb_configure; + return this; +} + +/* + * factory functions + */ + +void yuv2rgb_set_gamma (yuv2rgb_factory_t *this, int gamma) { + + int i; + + for (i = 0; i < 256; i++) { + (uint8_t *)this->table_rV[i] += this->entry_size*(gamma - this->gamma); + (uint8_t *)this->table_gU[i] += this->entry_size*(gamma - this->gamma); + (uint8_t *)this->table_bU[i] += this->entry_size*(gamma - this->gamma); + } +#ifdef ARCH_X86 + mmx_yuv2rgb_set_gamma(gamma); +#endif + this->gamma = gamma; +} + +int yuv2rgb_get_gamma (yuv2rgb_factory_t *this) { + + return this->gamma; +} + +yuv2rgb_factory_t* yuv2rgb_factory_init (int mode, int swapped, + uint8_t *cmap) { + + yuv2rgb_factory_t *this; #ifdef ARCH_X86 uint32_t mm = xine_mm_accel(); #endif - yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t)); + this = malloc (sizeof (yuv2rgb_factory_t)); + this->mode = mode; + this->swapped = swapped; + this->cmap = cmap; + this->create_converter = yuv2rgb_create_converter; + this->set_gamma = yuv2rgb_set_gamma; + this->get_gamma = yuv2rgb_get_gamma; this->matrix_coefficients = 6; - this->fast_rgb = colormap; - this->y_chunk = this->y_buffer = NULL; - this->u_chunk = this->u_buffer = NULL; - this->v_chunk = this->v_buffer = NULL; - yuv2rgb_setup_tables(this, mode, swapped); + yuv2rgb_setup_tables (this, mode, swapped); /* * auto-probe for the best yuv2rgb function @@ -2980,56 +3032,48 @@ yuv2rgb_t *yuv2rgb_init (int mode, int swapped, uint8_t *colormap) { this->yuv2rgb_fun = NULL; #ifdef ARCH_X86 if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMXEXT)) { - yuv2rgb_init_mmxext (this, mode, swapped); + + yuv2rgb_init_mmxext (this); + if (this->yuv2rgb_fun != NULL) printf ("yuv2rgb: using MMXEXT for colorspace transform\n"); } + if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMX)) { - yuv2rgb_init_mmx (this, mode, swapped); + + yuv2rgb_init_mmx (this); + if (this->yuv2rgb_fun != NULL) printf ("yuv2rgb: using MMX for colorspace transform\n"); } #endif #if HAVE_MLIB if (this->yuv2rgb_fun == NULL) { - yuv2rgb_init_mlib (this, mode, swapped); + + yuv2rgb_init_mlib (this); + if (this->yuv2rgb_fun != NULL) printf ("yuv2rgb: using medialib for colorspace transform\n"); } #endif if (this->yuv2rgb_fun == NULL) { printf ("yuv2rgb: no accelerated colorspace conversion found\n"); - yuv2rgb_c_init (this, mode, swapped); + yuv2rgb_c_init (this); } - yuv2rgb_single_pixel_init (this, mode, swapped); - /* * auto-probe for the best yuy22rgb function */ /* FIXME: implement mmx/mlib functions */ - yuy22rgb_c_init (this, mode, swapped); + yuy22rgb_c_init (this); - return this; -} + /* + * set up single pixel function + */ -void yuv2rgb_set_gamma (yuv2rgb_t *this, int gamma) -{ - int i; - - for (i = 0; i < 256; i++) { - (uint8_t *)this->table_rV[i] += this->entry_size*(gamma - this->gamma); - (uint8_t *)this->table_gU[i] += this->entry_size*(gamma - this->gamma); - (uint8_t *)this->table_bU[i] += this->entry_size*(gamma - this->gamma); - } -#ifdef ARCH_X86 - mmx_yuv2rgb_set_gamma(gamma); -#endif - this->gamma = gamma; -} + yuv2rgb_single_pixel_init (this); -int yuv2rgb_get_gamma (yuv2rgb_t *this) -{ - return this->gamma; + return this; } + diff --git a/src/video_out/yuv2rgb.h b/src/video_out/yuv2rgb.h index 493481260..6efa64f28 100644 --- a/src/video_out/yuv2rgb.h +++ b/src/video_out/yuv2rgb.h @@ -4,113 +4,151 @@ #include +typedef struct yuv2rgb_s yuv2rgb_t; + +typedef struct yuv2rgb_factory_s yuv2rgb_factory_t; + +/* + * function types for functions which can be replaced + * by hardware-accelerated versions + */ /* internal function use to scale yuv data */ typedef void (*scale_line_func_t) (uint8_t *source, uint8_t *dest, int width, int step); +typedef void (*yuv2rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * py, + uint8_t * pu, uint8_t * pv) ; + +typedef void (*yuy22rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * p); + +typedef uint32_t (*yuv2rgb_single_pixel_fun_t) (yuv2rgb_t *this, uint8_t y, + uint8_t u, uint8_t v); + /* * modes supported - feel free to implement yours */ -#define MODE_8_RGB 1 -#define MODE_8_BGR 2 -#define MODE_15_RGB 3 -#define MODE_15_BGR 4 -#define MODE_16_RGB 5 -#define MODE_16_BGR 6 -#define MODE_24_RGB 7 -#define MODE_24_BGR 8 -#define MODE_32_RGB 9 -#define MODE_32_BGR 10 -#define MODE_8_GRAY 11 +#define MODE_8_RGB 1 +#define MODE_8_BGR 2 +#define MODE_15_RGB 3 +#define MODE_15_BGR 4 +#define MODE_16_RGB 5 +#define MODE_16_BGR 6 +#define MODE_24_RGB 7 +#define MODE_24_BGR 8 +#define MODE_32_RGB 9 +#define MODE_32_BGR 10 +#define MODE_8_GRAY 11 #define MODE_PALETTE 12 -typedef struct yuv2rgb_s yuv2rgb_t; - struct yuv2rgb_s { + /* + * configure converter for scaling factors + */ + int (*configure) (yuv2rgb_t *this, + int source_width, int source_height, + int y_stride, int uv_stride, + int dest_width, int dest_height, + int rgb_stride); + /* * this is the function to call for the yuv2rgb and scaling process */ - void (*yuv2rgb_fun) (yuv2rgb_t *this, uint8_t * image, uint8_t * py, - uint8_t * pu, uint8_t * pv) ; + yuv2rgb_fun_t yuv2rgb_fun; /* * this is the function to call for the yuy2->rgb and scaling process */ - void (*yuy22rgb_fun) (yuv2rgb_t *this, uint8_t * image, uint8_t * p); + yuy22rgb_fun_t yuy22rgb_fun; /* * this is the function to call for the yuv2rgb for a single pixel * (used for converting clut colors) */ - uint32_t (*yuv2rgb_single_pixel_fun) (yuv2rgb_t *this, uint8_t y, - uint8_t u, uint8_t v); + + yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun; /* private stuff below */ - uint32_t matrix_coefficients; - int source_width, source_height; - int y_stride, uv_stride; - int dest_width, dest_height; - int rgb_stride; - int step_dx, step_dy; - int do_scale; - uint8_t *y_buffer; - uint8_t *u_buffer; - uint8_t *v_buffer; - void *y_chunk; - void *u_chunk; - void *v_chunk; - - void *table_rV[256]; - void *table_gU[256]; - int table_gV[256]; - void *table_bU[256]; - - uint8_t *fast_rgb; + int source_width, source_height; + int y_stride, uv_stride; + int dest_width, dest_height; + int rgb_stride; + int step_dx, step_dy; + int do_scale; + + uint8_t *y_buffer; + uint8_t *u_buffer; + uint8_t *v_buffer; + void *y_chunk; + void *u_chunk; + void *v_chunk; + + void **table_rV; + void **table_gU; + int *table_gV; + void **table_bU; + + uint8_t *cmap; scale_line_func_t scale_line; - int gamma; - int entry_size; } ; - -/* call once on startup */ -yuv2rgb_t *yuv2rgb_init (int mode, int swapped, uint8_t *colormap); - /* - * set up yuv2rgb function, determine scaling parameters if necessary - * returns 0 on failure, 1 otherwise + * convenience class to easily create a lot of converters */ -int yuv2rgb_setup (yuv2rgb_t *this, - int source_width, int source_height, - int y_stride, int uv_stride, - int dest_width, int dest_height, - int rgb_stride); -/* adjust gamma (-100 to 100 looks fine) */ -void yuv2rgb_set_gamma (yuv2rgb_t *this, int gamma); +struct yuv2rgb_factory_s { + + yuv2rgb_t* (*create_converter) (yuv2rgb_factory_t *this); + + /* + * adjust gamma (-100 to 100 looks fine) + * for all converters produced by this factory + */ + void (*set_gamma) (yuv2rgb_factory_t *this, int gamma); -/* get gamma value */ -int yuv2rgb_get_gamma (yuv2rgb_t *this); + /* + * get gamma value + */ + int (*get_gamma) (yuv2rgb_factory_t *this); + /* private data */ + + int mode; + int swapped; + uint8_t *cmap; + + int gamma; + int entry_size; + + uint32_t matrix_coefficients; + + void *table_rV[256]; + void *table_gU[256]; + int table_gV[256]; + void *table_bU[256]; + + /* preselected functions for mode/swap/hardware */ + yuv2rgb_fun_t *yuv2rgb_fun; + yuy22rgb_fun_t *yuy22rgb_fun; + yuv2rgb_single_pixel_fun_t *yuv2rgb_single_pixel_fun; + +}; + +yuv2rgb_factory_t *yuv2rgb_factory_init (int mode, int swapped, uint8_t *colormap); + /* * internal stuff below this line */ void mmx_yuv2rgb_set_gamma(int gamma); -void yuv2rgb_init_mmxext (yuv2rgb_t *this, int mode, int swapped); -void yuv2rgb_init_mmx (yuv2rgb_t *this, int mode, int swapped); -void yuv2rgb_init_mlib (yuv2rgb_t *this, int mode, int swapped); - -/* -void Color565DitherYV12MMX1X(unsigned char *lum, unsigned char *cr, - unsigned char *cb, unsigned char *out, - int rows, int cols, int mod ); -*/ +void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this); +void yuv2rgb_init_mmx (yuv2rgb_factory_t *this); +void yuv2rgb_init_mlib (yuv2rgb_factory_t *this); #endif diff --git a/src/video_out/yuv2rgb_mlib.c b/src/video_out/yuv2rgb_mlib.c index 0e992e1c0..c627e8a73 100644 --- a/src/video_out/yuv2rgb_mlib.c +++ b/src/video_out/yuv2rgb_mlib.c @@ -293,11 +293,11 @@ static void mlib_yuv420_abgr32 (yuv2rgb_t *this, } -void yuv2rgb_init_mlib (yuv2rgb_t *this, int mode, int swapped) -{ - if (swapped) return; /*no swapped pixel output upto now*/ +void yuv2rgb_init_mlib (yuv2rgb_factory_t *this) { + + if (this->swapped) return; /*no swapped pixel output upto now*/ - switch (mode) { + switch (this->mode) { case MODE_24_RGB: this->yuv2rgb_fun = mlib_yuv420_rgb24; break; diff --git a/src/video_out/yuv2rgb_mmx.c b/src/video_out/yuv2rgb_mmx.c index 8c94e5cb5..853b3a82a 100644 --- a/src/video_out/yuv2rgb_mmx.c +++ b/src/video_out/yuv2rgb_mmx.c @@ -982,11 +982,12 @@ static void mmx_abgr32 (yuv2rgb_t *this, uint8_t * image, emms(); /* re-initialize x86 FPU after MMX use */ } -void yuv2rgb_init_mmxext (yuv2rgb_t *this, int mode, int swapped) -{ - if (swapped) return; /*no swapped pixel output upto now*/ +void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this) { + + if (this->swapped) + return; /*no swapped pixel output upto now*/ - switch (mode) { + switch (this->mode) { case MODE_15_RGB: this->yuv2rgb_fun = mmxext_rgb15; break; @@ -1005,11 +1006,12 @@ void yuv2rgb_init_mmxext (yuv2rgb_t *this, int mode, int swapped) } } -void yuv2rgb_init_mmx (yuv2rgb_t *this, int mode, int swapped) -{ - if (swapped) return; /*no swapped pixel output upto now*/ +void yuv2rgb_init_mmx (yuv2rgb_factory_t *this) { + + if (this->swapped) + return; /*no swapped pixel output upto now*/ - switch (mode) { + switch (this->mode) { case MODE_15_RGB: this->yuv2rgb_fun = mmx_rgb15; break; diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 59183304d..7063d7bed 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: load_plugins.c,v 1.68 2002/02/02 17:05:43 richwareham Exp $ + * $Id: load_plugins.c,v 1.69 2002/02/16 22:43:24 guenter Exp $ * * * Load input/demux/audio_out/video_out/codec plugins @@ -47,9 +47,7 @@ #include "xineutils.h" #include "compat.h" -/* -#define LOAD_LOG -*/ +#define LOG #ifdef __GNUC__ #define LOG_MSG_STDERR(xine, message, args...) { \ @@ -662,15 +660,16 @@ char **xine_list_video_output_plugins (int visual_type) { && (dir_entry->d_name[nLen-2]=='s') && (dir_entry->d_name[nLen-1]=='o'))) { - /*printf ("load_plugins: found a video output plugin: %s\n", - dir_entry->d_name); */ +#ifdef LOG + printf ("load_plugins: found a video output plugin: %s\n", + dir_entry->d_name); +#endif #if IGNORE_DXR3ENC - if (! strncasecmp(dir_entry->d_name, - XINE_VIDEO_OUT_PLUGIN_PREFIXNAME "dxr3enc", - XINE_VIDEO_OUT_PLUGIN_PREFIXNAME_LENGTH + 7)) - { - printf("(ignoring obsolete dxr3enc driver)"); + if (!strncasecmp(dir_entry->d_name, + XINE_VIDEO_OUT_PLUGIN_PREFIXNAME "dxr3enc", + XINE_VIDEO_OUT_PLUGIN_PREFIXNAME_LENGTH + 7)) { + printf ("load_plugins: (ignoring obsolete dxr3enc driver)"); continue; } #endif @@ -698,9 +697,11 @@ char **xine_list_video_output_plugins (int visual_type) { vo_info = getinfo(); if ( (vo_info->visual_type == visual_type) - && (vo_info->interface_version == VIDEO_OUT_IFACE_VERSION) ) { - /* printf("video output plugin found : %s (%s)\n", - vo_info->id, vo_info->description); */ + && (vo_info->interface_version == VIDEO_OUT_DRIVER_IFACE_VERSION) ) { +#ifdef LOG + printf("video output plugin found : %s (%s)\n", + vo_info->id, vo_info->description); +#endif /* sort the list by vo_info->priority */ @@ -721,6 +722,9 @@ char **xine_list_video_output_plugins (int visual_type) { num_plugins++; plugin_ids[num_plugins] = NULL; + } else { + printf ("load_plugins: %s has wrong visual type (%d) or interface version (%d)\n", + str, vo_info->visual_type, vo_info->interface_version); } } else { @@ -740,8 +744,7 @@ char **xine_list_video_output_plugins (int visual_type) { remove_segv_handler(); - if( !num_plugins ) - { + if (!num_plugins) { fprintf(stderr, "load_plugins: no video plugins found, make sure you have them " "installed at %s\n", XINE_PLUGINDIR ); } @@ -812,7 +815,7 @@ vo_driver_t *xine_load_video_output_plugin(config_values_t *config, if (!strcasecmp(id, vo_info->id) ) { - if (vo_info->interface_version == VIDEO_OUT_IFACE_VERSION) { + if (vo_info->interface_version == VIDEO_OUT_DRIVER_IFACE_VERSION) { void *(*initplug) (config_values_t *, void *); @@ -904,14 +907,14 @@ char **xine_list_audio_output_plugins(void) { ao_info_t* (*getinfo) (); ao_info_t *ao_info; -#ifdef LOAD_LOG +#ifdef LOG printf ("load_plugins: plugin %s successfully loaded.\n", str); #endif if ((getinfo = dlsym(plugin, "get_audio_out_plugin_info")) != NULL) { ao_info = getinfo(); -#ifdef LOAD_LOG +#ifdef LOG printf("load_plugins: id=%s, priority=%d, interface_version=%d\n", ao_info->id, ao_info->priority, ao_info->interface_version); #endif @@ -955,8 +958,8 @@ char **xine_list_audio_output_plugins(void) { } closedir(dir); } else { - fprintf (stderr, "load_plugins: %s - cannot access plugin dir: %s", - __XINE_FUNCTION__, strerror(errno)); + printf ("load_plugins: %s - cannot access plugin dir: %s", + __XINE_FUNCTION__, strerror(errno)); } remove_segv_handler(); diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index a75547236..4a7f28644 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.h,v 1.40 2002/02/09 07:13:24 guenter Exp $ + * $Id: video_out.h,v 1.41 2002/02/16 22:43:24 guenter Exp $ * * * xine version of video_out.h @@ -58,8 +58,6 @@ extern "C" { #endif #endif -#define VIDEO_OUT_PLUGIN_IFACE_VERSION 1 - typedef struct vo_frame_s vo_frame_t; typedef struct vo_driver_s vo_driver_t ; typedef struct vo_instance_s vo_instance_t; @@ -233,9 +231,8 @@ struct vo_instance_s { rgb buffers in the private fields of image buffer) */ #define VO_CAP_COPIES_IMAGE 0x00000001 -#define VO_CAP_RGB 0x00000002 /* driver can handle 24bit rgb pictures */ -#define VO_CAP_YV12 0x00000004 /* driver can handle YUV 4:2:0 pictures */ -#define VO_CAP_YUY2 0x00000008 /* driver can handle YUY2 pictures */ +#define VO_CAP_YV12 0x00000002 /* driver can handle YUV 4:2:0 pictures */ +#define VO_CAP_YUY2 0x00000004 /* driver can handle YUY2 pictures */ #define VO_CAP_HUE 0x00000010 /* driver can set HUE value */ #define VO_CAP_SATURATION 0x00000020 /* driver can set SATURATION value */ @@ -253,7 +250,7 @@ struct vo_instance_s { * from generic vo functions. */ -#define VIDEO_OUT_IFACE_VERSION 3 +#define VIDEO_OUT_DRIVER_IFACE_VERSION 4 struct vo_driver_s { -- cgit v1.2.3