diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/video_out/Makefile.am | 11 | ||||
-rw-r--r-- | src/video_out/video_out_sdl.c | 325 |
2 files changed, 187 insertions, 149 deletions
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 2700996d0..733bab373 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -39,11 +39,8 @@ endif # all xine video out plugins should be named # "xineplug_vo_out_*" -# FIXME: temporarily disabled until they're adapted to new interface -# $(sdl_module) $(opengl_module) - lib_LTLIBRARIES = $(xshm_module) $(xv_module) $(directfb_module) $(aa_module) \ - $(syncfb_module) $(fb_module) $(opengl_module) + $(syncfb_module) $(fb_module) $(opengl_module) $(sdl_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 \ @@ -78,9 +75,9 @@ xineplug_vo_out_directfb_la_SOURCES = alphablend.c video_out_directfb.c xineplug_vo_out_directfb_la_LIBADD = $(DIRECTFB_LIBS) xineplug_vo_out_directfb_la_LDFLAGS = -avoid-version -module -#xineplug_vo_out_sdl_la_SOURCES = alphablend.c video_out_sdl.c -#xineplug_vo_out_sdl_la_LIBADD = $(SDL_LIBS) -#xineplug_vo_out_sdl_la_LDFLAGS = -avoid-version -module +xineplug_vo_out_sdl_la_SOURCES = alphablend.c video_out_sdl.c +xineplug_vo_out_sdl_la_LIBADD = $(SDL_LIBS) +xineplug_vo_out_sdl_la_LDFLAGS = -avoid-version -module noinst_HEADERS = yuv2rgb.h video_out_syncfb.h alphablend.h deinterlace.h diff --git a/src/video_out/video_out_sdl.c b/src/video_out/video_out_sdl.c index 4d96e8c66..313e133e2 100644 --- a/src/video_out/video_out_sdl.c +++ b/src/video_out/video_out_sdl.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: video_out_sdl.c,v 1.6 2002/03/07 13:26:16 jcdutton Exp $ + * $Id: video_out_sdl.c,v 1.7 2002/05/13 02:42:12 miguelfreitas Exp $ * * video_out_sdl.c, Simple DirectMedia Layer * @@ -28,9 +28,10 @@ * xine version by Miguel Freitas (Jan/2002) * Missing features: * - mouse position translation - * - logo state aware * - fullscreen * - stability, testing, etc?? ;) + * Known bugs: + * - without X11, a resize is need to show image (?) * * BIG WARNING HERE: if you use RedHat SDL packages you will probably * get segfault when no hwaccel is available. more info at: @@ -45,6 +46,7 @@ #include <stdlib.h> #include <string.h> #include <inttypes.h> +#include <math.h> #include <SDL/SDL.h> #include "video_out.h" @@ -93,23 +95,53 @@ struct sdl_driver_s { Drawable drawable; #endif - /* size / aspect ratio calculations */ - /* delivered images */ - int delivered_width; /* everything is set up for - these frame dimensions */ - int delivered_height; /* the dimension as they come - from the decoder */ + /* + * "delivered" size: + * frame dimension / aspect as delivered by the decoder + * used (among other things) to detect frame size changes + */ + int delivered_width; + int delivered_height; int delivered_ratio_code; + + /* + * displayed part of delivered images, + * taking zoom into account + */ + + int displayed_xoffset; + int displayed_yoffset; + int displayed_width; + int displayed_height; + + /* + * "ideal" size : + * displayed width/height corrected by aspect ratio + */ + + int ideal_width, ideal_height; double ratio_factor; /* output frame must fullfill: height = width * ratio_factor */ - - /* Window */ - int window_width; - int window_height; + + /* + * "gui" size / offset: + * what gui told us about where to display the video + */ - /* output screen area */ - int output_width; /* frames will appear in this - size (pixels) on screen */ + int gui_x, gui_y; + int gui_width, gui_height; + int gui_win_x, gui_win_y; + + /* + * "output" size: + * + * this is finally the ideal size "fitted" into the + * gui size while maintaining the aspect ratio + * + */ + + /* Window */ + int output_width; int output_height; int output_xoffset; int output_yoffset; @@ -122,10 +154,11 @@ struct sdl_driver_s { /* gui callback */ - 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, + int *win_x, int *win_y); }; static uint32_t sdl_get_capabilities (vo_driver_t *this_gen) { @@ -172,87 +205,67 @@ static vo_frame_t *sdl_alloc_frame (vo_driver_t *this_gen) { return (vo_frame_t *) frame; } +/* + * make ideal width/height "fit" into the gui + */ -static void sdl_adapt_to_output_area (sdl_driver_t *this, - int dest_x, int dest_y, - int dest_width, int dest_height) { +static void sdl_compute_output_size (sdl_driver_t *this) { + + double x_factor, y_factor; -#ifdef SDL_LOG - printf ("video_out_sdl: dest_width %d, dest_height %d\n", - dest_width, dest_height ); -#endif - - /* - * make the frames fit into the given destination area - */ - if ( ((double) dest_width / this->ratio_factor) < dest_height ) { - this->output_width = dest_width; - this->output_height = (double) dest_width / this->ratio_factor ; - this->output_xoffset = 0; - this->output_yoffset = (dest_height - this->output_height) / 2; - } else { - this->output_width = (double) dest_height * this->ratio_factor ; - this->output_height = dest_height; - this->output_xoffset = (dest_width - this->output_width) / 2; - this->output_yoffset = 0; - } + x_factor = (double) this->gui_width / (double) this->ideal_width; + y_factor = (double) this->gui_height / (double) this->ideal_height; - if( dest_width != this->window_width || dest_height != this->window_height ) { - this->window_width = dest_width; - this->window_height = dest_height; - this->surface = SDL_SetVideoMode (this->window_width, this->window_height, - this->bpp, this->sdlflags); + if ( x_factor < y_factor ) { + this->output_width = (double) this->gui_width; + this->output_height = (double) this->ideal_height * x_factor ; + } else { + this->output_width = (double) this->ideal_width * y_factor ; + this->output_height = (double) this->gui_height; } -} - -static void sdl_calc_format (sdl_driver_t *this, - int width, int height, int ratio_code) { + this->output_xoffset = (this->gui_width - this->output_width) / 2 + this->gui_x; + this->output_yoffset = (this->gui_height - this->output_height) / 2 + this->gui_y; - double image_ratio, desired_ratio; - double corr_factor; - int ideal_width, ideal_height; - int dest_x, dest_y, dest_width, dest_height; +#ifdef LOG + printf ("video_out_sdl: frame source %d x %d => screen output %d x %d\n", + this->delivered_width, this->delivered_height, + this->output_width, this->output_height); +#endif +} - this->delivered_width = width; - this->delivered_height = height; - this->delivered_ratio_code = ratio_code; +static void sdl_compute_ideal_size (sdl_driver_t *this) { - if ( (!width) || (!height) ) - return; + double image_ratio, desired_ratio, corr_factor; + + this->displayed_xoffset = (this->delivered_width - this->displayed_width) / 2; + this->displayed_yoffset = (this->delivered_height - this->displayed_height) / 2; - /* - * aspect ratio calculation + /* + * aspect ratio */ - image_ratio = - (double) this->delivered_width / (double) this->delivered_height; - -#ifdef SDL_LOG - printf ("video_out_sdl: display_ratio : %f\n", this->display_ratio); - printf ("video_out_sdl: stream aspect ratio : %f , code : %d\n", - image_ratio, ratio_code); -#endif - + image_ratio = (double) this->delivered_width / (double) this->delivered_height; + switch (this->user_ratio) { case ASPECT_AUTO: - switch (ratio_code) { + switch (this->delivered_ratio_code) { case XINE_ASPECT_RATIO_ANAMORPHIC: /* anamorphic */ desired_ratio = 16.0 /9.0; break; - case XINE_ASPECT_RATIO_211_1: /* 2.11:1 */ + case XINE_ASPECT_RATIO_211_1: /* 2.11:1 */ desired_ratio = 2.11/1.0; break; - case XINE_ASPECT_RATIO_SQUARE: /* "square" source pels */ - case XINE_ASPECT_RATIO_DONT_TOUCH: /* probably non-mpeg stream => don't touch aspect ratio */ + case XINE_ASPECT_RATIO_SQUARE: /* square pels */ + case XINE_ASPECT_RATIO_DONT_TOUCH: /* probably non-mpeg stream => don't touch aspect ratio */ desired_ratio = image_ratio; break; - case 0: /* forbidden */ - fprintf (stderr, "invalid ratio, using 4:3\n"); + case 0: /* forbidden -> 4:3 */ + printf ("video_out_sdl: invalid ratio, using 4:3\n"); default: printf ("video_out_sdl: unknown aspect ratio (%d) in stream => using 4:3\n", - ratio_code); - case XINE_ASPECT_RATIO_4_3: /* 4:3 */ + this->delivered_ratio_code); + case XINE_ASPECT_RATIO_4_3: /* 4:3 */ desired_ratio = 4.0 / 3.0; break; } @@ -271,47 +284,27 @@ static void sdl_calc_format (sdl_driver_t *this, desired_ratio = 4.0 / 3.0; } - /* this->ratio_factor = display_ratio * desired_ratio / image_ratio ; */ this->ratio_factor = this->display_ratio * desired_ratio; - /* - * calc ideal output frame size - */ - corr_factor = this->ratio_factor / image_ratio ; - if (corr_factor >= 1.0) { - ideal_width = this->delivered_width * corr_factor; - ideal_height = this->delivered_height ; - } - else { - ideal_width = this->delivered_width; - ideal_height = this->delivered_height / corr_factor; - } - - /* little hack to zoom mpeg1 / other small streams by default*/ - if ( ideal_width<400 ) { - ideal_width *=2; - ideal_height *=2; - } + if (fabs(corr_factor - 1.0) < 0.005) { + this->ideal_width = this->delivered_width; + this->ideal_height = this->delivered_height; - /* - * ask gui to adapt to this size - */ -#ifdef HAVE_X11 - this->request_dest_size (this->user_data, - ideal_width, ideal_height, - &dest_x, &dest_y, &dest_width, &dest_height); -#else - dest_x = 0; - dest_y = 0; - dest_width = ideal_width; - dest_height = ideal_height; -#endif + } else { - sdl_adapt_to_output_area (this, dest_x, dest_y, dest_width, dest_height); + if (corr_factor >= 1.0) { + this->ideal_width = this->delivered_width * corr_factor + 0.5; + this->ideal_height = this->delivered_height; + } else { + this->ideal_width = this->delivered_width; + this->ideal_height = this->delivered_height / corr_factor + 0.5; + } + } } + static void sdl_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, @@ -351,10 +344,6 @@ static void sdl_update_frame_format (vo_driver_t *this_gen, if (frame->overlay == NULL) return; -#ifdef SDL_LOG - printf ("[%p %p %p]\n", frame->overlay->pixels[0], frame->overlay->pixels[1], - frame->overlay->pixels[2] ); -#endif frame->vo_frame.base[0] = frame->overlay->pixels[0]; frame->vo_frame.base[1] = frame->overlay->pixels[2]; frame->vo_frame.base[2] = frame->overlay->pixels[1]; @@ -390,15 +379,66 @@ static void sdl_check_events (sdl_driver_t * this) SDL_Event event; while (SDL_PollEvent (&event)) { - if (event.type == SDL_VIDEORESIZE) - sdl_adapt_to_output_area(this, 0, 0, event.resize.w, event.resize.h); - /* - this->surface = SDL_SetVideoMode (event.resize.w, event.resize.h, - this->bpp, this->sdlflags); - */ + if (event.type == SDL_VIDEORESIZE) { + if( event.resize.w != this->gui_width || event.resize.h != this->gui_height ) { + this->gui_width = event.resize.w; + this->gui_height = event.resize.h; + + sdl_compute_output_size(this); + + this->surface = SDL_SetVideoMode (this->gui_width, this->gui_height, + this->bpp, this->sdlflags); + } + } + } +} + +static int sdl_redraw_needed (vo_driver_t *this_gen) { + sdl_driver_t *this = (sdl_driver_t *) this_gen; + int ret = 0; +#ifdef HAVE_X11 + int gui_x, gui_y, gui_width, gui_height, gui_win_x, gui_win_y; + + this->frame_output_cb (this->user_data, + this->ideal_width, this->ideal_height, + &gui_x, &gui_y, &gui_width, &gui_height, + &gui_win_x, &gui_win_y ); + + if ( (gui_x != this->gui_x) || (gui_y != this->gui_y) + || (gui_width != this->gui_width) || (gui_height != this->gui_height) + || (gui_win_x != this->gui_win_x) || (gui_win_y != this->gui_win_y) ) { + + this->gui_x = gui_x; + this->gui_y = gui_y; + this->gui_width = gui_width; + this->gui_height = gui_height; + this->gui_win_x = gui_win_x; + this->gui_win_y = gui_win_y; + + sdl_compute_output_size (this); + + ret = 1; + } + + return ret; +#else + static int last_gui_width, last_gui_height; + + if( last_gui_width != this->gui_width || + last_gui_height != this->gui_height ) { + + last_gui_width = this->gui_width; + last_gui_height = this->gui_height; + + sdl_compute_output_size (this); + + ret = 1; } + return 0; +#endif } + static void sdl_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { sdl_driver_t *this = (sdl_driver_t *) this_gen; @@ -411,9 +451,21 @@ static void sdl_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { || (frame->height != this->delivered_height) || (frame->ratio_code != this->delivered_ratio_code) ) { printf("video_out_sdl: change frame format\n"); - sdl_calc_format (this, frame->width, frame->height, frame->ratio_code); + + this->delivered_width = frame->width; + this->delivered_height = frame->height; + this->delivered_ratio_code = frame->ratio_code; + + sdl_compute_ideal_size( this ); } + /* + * tell gui that we are about to display a frame, + * ask for offset and output size + */ + sdl_check_events (this); + sdl_redraw_needed (this_gen); + SDL_UnlockYUVOverlay (frame->overlay); /* SDL_DisplayYUVOverlay (frame->overlay, &(this->surface->clip_rect)); @@ -424,7 +476,6 @@ static void sdl_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { clip_rect.h = this->output_height; SDL_DisplayYUVOverlay (frame->overlay, &clip_rect); - sdl_check_events (this); frame->vo_frame.displayed (&frame->vo_frame); pthread_mutex_unlock(&this->mutex); @@ -471,9 +522,7 @@ static int sdl_set_property (vo_driver_t *this_gen, printf("video_out_sdl: aspect ratio changed to %s\n", aspect_ratio_name(value)); - sdl_calc_format (this, this->delivered_width, this->delivered_height, - this->delivered_ratio_code) ; - + sdl_compute_ideal_size (this); } return value; @@ -497,19 +546,10 @@ static int sdl_gui_data_exchange (vo_driver_t *this_gen, int ret = 0; #ifdef HAVE_X11 sdl_driver_t *this = (sdl_driver_t *) this_gen; - x11_rectangle_t *area; pthread_mutex_lock(&this->mutex); switch (data_type) { - case GUI_DATA_EX_DEST_POS_SIZE_CHANGED: -#ifdef SDL_LOG - printf ("video_out_sdl: GUI_DATA_EX_DEST_POS_SIZE_CHANGED\n"); -#endif - - area = (x11_rectangle_t *) data; - sdl_adapt_to_output_area (this, area->x, area->y, area->w, area->h); - break; case GUI_DATA_EX_DRAWABLE_CHANGED: #ifdef SDL_LOG @@ -575,7 +615,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->screen = visual->screen; this->display_ratio = visual->display_ratio; this->drawable = visual->d; - this->request_dest_size = visual->request_dest_size; + this->frame_output_cb = visual->frame_output_cb; this->user_data = visual->user_data; /* set SDL to use our existing X11 window */ @@ -617,14 +657,14 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { #ifdef HAVE_X11 XGetWindowAttributes(this->display, this->drawable, &window_attributes); - this->window_width = window_attributes.width; - this->window_height = window_attributes.height; + this->gui_width = window_attributes.width; + this->gui_height = window_attributes.height; #else - this->window_width = 320; - this->window_height = 240; + this->gui_width = 320; + this->gui_height = 240; #endif - this->surface = SDL_SetVideoMode (this->window_width, this->window_height, + this->surface = SDL_SetVideoMode (this->gui_width, this->gui_height, this->bpp, this->sdlflags); this->vo_driver.get_capabilities = sdl_get_capabilities; @@ -637,6 +677,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->vo_driver.get_property_min_max = sdl_get_property_min_max; this->vo_driver.gui_data_exchange = sdl_gui_data_exchange; this->vo_driver.exit = sdl_exit; + this->vo_driver.redraw_needed = sdl_redraw_needed; printf ("video_out_sdl: warning, xine's SDL driver is EXPERIMENTAL\n"); printf ("video_out_sdl: fullscreen mode is NOT supported\n"); @@ -644,7 +685,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { } static vo_info_t vo_info_sdl = { - 3, + 5, "sdl", "xine video output plugin using Simple DirectMedia Layer", VISUAL_TYPE_X11, |