Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

sdl.c

00001 /*****************************************************************************
00002  * sdl.c: SDL video output display method
00003  *****************************************************************************
00004  * Copyright (C) 1998-2001 the VideoLAN team
00005  * $Id: sdl.c 12875 2005-10-18 07:12:27Z md $
00006  *
00007  * Authors: Samuel Hocevar <[email protected]>
00008  *          Pierre Baillet <[email protected]>
00009  *          Arnaud de Bossoreille de Ribou <[email protected]>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027  * Preamble
00028  *****************************************************************************/
00029 #include <errno.h>                                                 /* ENOMEM */
00030 #include <stdlib.h>                                                /* free() */
00031 #include <string.h>                                            /* strerror() */
00032 
00033 #include <vlc/vlc.h>
00034 #include <vlc/intf.h>
00035 #include <vlc/vout.h>
00036 #include <vlc/aout.h>
00037 
00038 #include <sys/types.h>
00039 #ifndef WIN32
00040 #   include <netinet/in.h>                            /* BSD: struct in_addr */
00041 #endif
00042 
00043 #include SDL_INCLUDE_FILE
00044 
00045 /* SDL is not able to crop overlays - so use only 1 direct buffer */
00046 #define SDL_MAX_DIRECTBUFFERS 1
00047 #define SDL_DEFAULT_BPP 16
00048 
00049 /*****************************************************************************
00050  * vout_sys_t: video output SDL method descriptor
00051  *****************************************************************************
00052  * This structure is part of the video output thread descriptor.
00053  * It describes the SDL specific properties of an output thread.
00054  *****************************************************************************/
00055 struct vout_sys_t
00056 {
00057     SDL_Surface *   p_display;                             /* display device */
00058 
00059     int i_width;
00060     int i_height;
00061 
00062     /* For YUV output */
00063     SDL_Overlay * p_overlay;   /* An overlay we keep to grab the XVideo port */
00064 
00065     /* For RGB output */
00066     int i_surfaces;
00067 
00068     vlc_bool_t  b_cursor;
00069     vlc_bool_t  b_cursor_autohidden;
00070     mtime_t     i_lastmoved;
00071     mtime_t     i_lastpressed;                        /* to track dbl-clicks */
00072 };
00073 
00074 /*****************************************************************************
00075  * picture_sys_t: direct buffer method descriptor
00076  *****************************************************************************
00077  * This structure is part of the picture descriptor, it describes the
00078  * SDL specific properties of a direct buffer.
00079  *****************************************************************************/
00080 struct picture_sys_t
00081 {
00082     SDL_Overlay *p_overlay;
00083 };
00084 
00085 /*****************************************************************************
00086  * Local prototypes
00087  *****************************************************************************/
00088 static int  Open      ( vlc_object_t * );
00089 static void Close     ( vlc_object_t * );
00090 static int  Init      ( vout_thread_t * );
00091 static void End       ( vout_thread_t * );
00092 static int  Manage    ( vout_thread_t * );
00093 static void Display   ( vout_thread_t *, picture_t * );
00094 
00095 static int  OpenDisplay     ( vout_thread_t * );
00096 static void CloseDisplay    ( vout_thread_t * );
00097 static int  NewPicture      ( vout_thread_t *, picture_t * );
00098 static void SetPalette      ( vout_thread_t *,
00099                               uint16_t *, uint16_t *, uint16_t * );
00100 
00101 /*****************************************************************************
00102  * Module descriptor
00103  *****************************************************************************/
00104 vlc_module_begin();
00105     set_shortname( "SDL" );
00106     set_category( CAT_VIDEO );
00107     set_subcategory( SUBCAT_VIDEO_VOUT );
00108     set_description( _("Simple DirectMedia Layer video output") );
00109     set_capability( "video output", 60 );
00110     add_shortcut( "sdl" );
00111     set_callbacks( Open, Close );
00112     /* XXX: check for conflicts with the SDL audio output */
00113     var_Create( p_module->p_libvlc, "sdl", VLC_VAR_MUTEX );
00114 #if defined( __i386__ ) || defined( __x86_64__ )
00115     /* On i386, SDL is linked against svgalib */
00116     linked_with_a_crap_library_which_uses_atexit();
00117 #endif
00118 vlc_module_end();
00119 
00120 /*****************************************************************************
00121  * OpenVideo: allocate SDL video thread output method
00122  *****************************************************************************
00123  * This function allocate and initialize a SDL vout method. It uses some of the
00124  * vout properties to choose the correct mode, and change them according to the
00125  * mode actually used.
00126  *****************************************************************************/
00127 static int Open ( vlc_object_t *p_this )
00128 {
00129     vout_thread_t * p_vout = (vout_thread_t *)p_this;
00130     vlc_value_t lockval;
00131 
00132 #ifdef HAVE_SETENV
00133     char *psz_method;
00134 #endif
00135 
00136     var_Get( p_this->p_libvlc, "sdl", &lockval );
00137     vlc_mutex_lock( lockval.p_address );
00138 
00139     if( SDL_WasInit( SDL_INIT_VIDEO ) != 0 )
00140     {
00141         vlc_mutex_unlock( lockval.p_address );
00142         return VLC_EGENERIC;
00143     }
00144 
00145     /* Allocate structure */
00146     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00147     if( p_vout->p_sys == NULL )
00148     {
00149         msg_Err( p_vout, "out of memory" );
00150         vlc_mutex_unlock( lockval.p_address );
00151         return VLC_ENOMEM;
00152     }
00153 
00154     p_vout->pf_init = Init;
00155     p_vout->pf_end = End;
00156     p_vout->pf_manage = Manage;
00157     p_vout->pf_render = NULL;
00158     p_vout->pf_display = Display;
00159 
00160 #ifdef HAVE_SETENV
00161     psz_method = config_GetPsz( p_vout, "vout" );
00162     if( psz_method )
00163     {
00164         while( *psz_method && *psz_method != ':' )
00165         {
00166             psz_method++;
00167         }
00168 
00169         if( *psz_method )
00170         {
00171             setenv( "SDL_VIDEODRIVER", psz_method + 1, 1 );
00172         }
00173     }
00174 #endif
00175 
00176     /* Initialize library */
00177     if( SDL_Init( SDL_INIT_VIDEO
00178 #ifndef WIN32
00179     /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
00180                 | SDL_INIT_EVENTTHREAD
00181 #endif
00182 #ifdef DEBUG
00183     /* In debug mode you may want vlc to dump a core instead of staying
00184      * stuck */
00185                 | SDL_INIT_NOPARACHUTE
00186 #endif
00187                 ) < 0 )
00188     {
00189         msg_Err( p_vout, "cannot initialize SDL (%s)", SDL_GetError() );
00190         free( p_vout->p_sys );
00191         vlc_mutex_unlock( lockval.p_address );
00192         return VLC_EGENERIC;
00193     }
00194 
00195     vlc_mutex_unlock( lockval.p_address );
00196 
00197     p_vout->p_sys->b_cursor = 1;
00198     p_vout->p_sys->b_cursor_autohidden = 0;
00199     p_vout->p_sys->i_lastmoved = mdate();
00200 
00201     if( OpenDisplay( p_vout ) )
00202     {
00203         msg_Err( p_vout, "cannot set up SDL (%s)", SDL_GetError() );
00204         SDL_QuitSubSystem( SDL_INIT_VIDEO );
00205         free( p_vout->p_sys );
00206         return VLC_EGENERIC;
00207     }
00208 
00209     return VLC_SUCCESS;
00210 }
00211 
00212 /*****************************************************************************
00213  * Init: initialize SDL video thread output method
00214  *****************************************************************************
00215  * This function initialize the SDL display device.
00216  *****************************************************************************/
00217 static int Init( vout_thread_t *p_vout )
00218 {
00219     int i_index;
00220     picture_t *p_pic;
00221 
00222     p_vout->p_sys->i_surfaces = 0;
00223 
00224     I_OUTPUTPICTURES = 0;
00225 
00226     /* Initialize the output structure */
00227     if( p_vout->p_sys->p_overlay == NULL )
00228     {
00229         /* All we have is an RGB image with square pixels */
00230         p_vout->output.i_width  = p_vout->p_sys->i_width;
00231         p_vout->output.i_height = p_vout->p_sys->i_height;
00232         p_vout->output.i_aspect = p_vout->output.i_width
00233                                    * VOUT_ASPECT_FACTOR
00234                                    / p_vout->output.i_height;
00235     }
00236     else
00237     {
00238         /* We may need to convert the chroma, but at least we keep the
00239          * aspect ratio */
00240         p_vout->output.i_width  = p_vout->render.i_width;
00241         p_vout->output.i_height = p_vout->render.i_height;
00242         p_vout->output.i_aspect = p_vout->render.i_aspect;
00243     }
00244 
00245     /* Try to initialize SDL_MAX_DIRECTBUFFERS direct buffers */
00246     while( I_OUTPUTPICTURES < SDL_MAX_DIRECTBUFFERS )
00247     {
00248         p_pic = NULL;
00249 
00250         /* Find an empty picture slot */
00251         for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00252         {
00253             if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00254             {
00255                 p_pic = p_vout->p_picture + i_index;
00256                 break;
00257             }
00258         }
00259 
00260         /* Allocate the picture if we found one */
00261         if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
00262         {
00263             break;
00264         }
00265 
00266         p_pic->i_status = DESTROYED_PICTURE;
00267         p_pic->i_type   = DIRECT_PICTURE;
00268 
00269         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00270 
00271         I_OUTPUTPICTURES++;
00272     }
00273 
00274     return VLC_SUCCESS;
00275 }
00276 
00277 /*****************************************************************************
00278  * End: terminate Sys video thread output method
00279  *****************************************************************************
00280  * Terminate an output method created by OpenVideo
00281  *****************************************************************************/
00282 static void End( vout_thread_t *p_vout )
00283 {
00284     int i_index;
00285 
00286     /* Free the output buffers we allocated */
00287     for( i_index = I_OUTPUTPICTURES ; i_index ; )
00288     {
00289         i_index--;
00290         if( p_vout->p_sys->p_overlay == NULL )
00291         {
00292             /* RGB picture */
00293         }
00294         else
00295         {
00296             SDL_UnlockYUVOverlay(
00297                     PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
00298             SDL_FreeYUVOverlay(
00299                     PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
00300         }
00301         free( PP_OUTPUTPICTURE[ i_index ]->p_sys );
00302     }
00303 }
00304 
00305 /*****************************************************************************
00306  * CloseVideo: destroy Sys video thread output method
00307  *****************************************************************************
00308  * Terminate an output method created by vout_SDLCreate
00309  *****************************************************************************/
00310 static void Close ( vlc_object_t *p_this )
00311 {
00312     vout_thread_t * p_vout = (vout_thread_t *)p_this;
00313 
00314     CloseDisplay( p_vout );
00315     SDL_QuitSubSystem( SDL_INIT_VIDEO );
00316 
00317     free( p_vout->p_sys );
00318 }
00319 
00320 /*****************************************************************************
00321  * Manage: handle Sys events
00322  *****************************************************************************
00323  * This function should be called regularly by video output thread. It returns
00324  * a non null value if an error occurred.
00325  *****************************************************************************/
00326 static int Manage( vout_thread_t *p_vout )
00327 {
00328     SDL_Event event;                                            /* SDL event */
00329     vlc_value_t val;
00330     int i_width, i_height, i_x, i_y;
00331 
00332     /* Process events */
00333     while( SDL_PollEvent(&event) )
00334     {
00335         switch( event.type )
00336         {
00337         case SDL_VIDEORESIZE:                          /* Resizing of window */
00338             /* Update dimensions */
00339             p_vout->i_changes |= VOUT_SIZE_CHANGE;
00340             p_vout->i_window_width = p_vout->p_sys->i_width = event.resize.w;
00341             p_vout->i_window_height = p_vout->p_sys->i_height = event.resize.h;
00342             break;
00343 
00344         case SDL_MOUSEMOTION:
00345             vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
00346                                p_vout->p_sys->i_height,
00347                                &i_x, &i_y, &i_width, &i_height );
00348 
00349             val.i_int = ( event.motion.x - i_x )
00350                          * p_vout->render.i_width / i_width;
00351             var_Set( p_vout, "mouse-x", val );
00352             val.i_int = ( event.motion.y - i_y )
00353                          * p_vout->render.i_height / i_height;
00354             var_Set( p_vout, "mouse-y", val );
00355 
00356             val.b_bool = VLC_TRUE;
00357             var_Set( p_vout, "mouse-moved", val );
00358 
00359             if( p_vout->p_sys->b_cursor &&
00360                 (abs(event.motion.xrel) > 2 || abs(event.motion.yrel) > 2) )
00361             {
00362                 if( p_vout->p_sys->b_cursor_autohidden )
00363                 {
00364                     p_vout->p_sys->b_cursor_autohidden = 0;
00365                     SDL_ShowCursor( 1 );
00366                 }
00367                 else
00368                 {
00369                     p_vout->p_sys->i_lastmoved = mdate();
00370                 }
00371             }
00372             break;
00373 
00374         case SDL_MOUSEBUTTONUP:
00375             switch( event.button.button )
00376             {
00377             case SDL_BUTTON_LEFT:
00378                 val.b_bool = VLC_TRUE;
00379                 var_Set( p_vout, "mouse-clicked", val );
00380                 break;
00381 
00382             case SDL_BUTTON_RIGHT:
00383                 {
00384                     intf_thread_t *p_intf;
00385                     p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
00386                                                       FIND_ANYWHERE );
00387                     if( p_intf )
00388                     {
00389                         p_intf->b_menu_change = 1;
00390                         vlc_object_release( p_intf );
00391                     }
00392                 }
00393                 break;
00394             }
00395             break;
00396 
00397         case SDL_MOUSEBUTTONDOWN:
00398             switch( event.button.button )
00399             {
00400             case SDL_BUTTON_LEFT:
00401                 /* In this part we will eventually manage
00402                  * clicks for DVD navigation for instance. */
00403 
00404                 /* detect double-clicks */
00405                 if( ( mdate() - p_vout->p_sys->i_lastpressed ) < 300000 )
00406                     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00407 
00408                 p_vout->p_sys->i_lastpressed = mdate();
00409                 break;
00410 
00411             case 4:
00412                 break;
00413 
00414             case 5:
00415                 break;
00416             }
00417             break;
00418 
00419         case SDL_QUIT:
00420             p_vout->p_vlc->b_die = 1;
00421             break;
00422 
00423         case SDL_KEYDOWN:                             /* if a key is pressed */
00424 
00425             switch( event.key.keysym.sym )
00426             {
00427             case SDLK_ESCAPE:
00428                 if( p_vout->b_fullscreen )
00429                 {
00430                     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00431                 }
00432                 else
00433                 {
00434                     p_vout->p_vlc->b_die = 1;
00435                 }
00436                 break;
00437 
00438             case SDLK_q:                                             /* quit */
00439                 p_vout->p_vlc->b_die = 1;
00440                 break;
00441 
00442             case SDLK_f:                             /* switch to fullscreen */
00443                 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00444                 break;
00445 
00446             case SDLK_c:                                 /* toggle grayscale */
00447                 p_vout->b_grayscale = ! p_vout->b_grayscale;
00448                 p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
00449                 break;
00450 
00451             case SDLK_i:                                      /* toggle info */
00452                 p_vout->b_info = ! p_vout->b_info;
00453                 p_vout->i_changes |= VOUT_INFO_CHANGE;
00454                 break;
00455 
00456             case SDLK_s:                                   /* toggle scaling */
00457                 p_vout->b_scale = ! p_vout->b_scale;
00458                 p_vout->i_changes |= VOUT_SCALE_CHANGE;
00459                 break;
00460 
00461             case SDLK_SPACE:                             /* toggle interface */
00462                 p_vout->b_interface = ! p_vout->b_interface;
00463                 p_vout->i_changes |= VOUT_INTF_CHANGE;
00464                 break;
00465 
00466             case SDLK_MENU:
00467                 {
00468                     intf_thread_t *p_intf;
00469                     p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF,
00470                                                       FIND_ANYWHERE );
00471                     if( p_intf != NULL )
00472                     {
00473                         p_intf->b_menu_change = 1;
00474                         vlc_object_release( p_intf );
00475                     }
00476                 }
00477                 break;
00478 
00479             case SDLK_LEFT:
00480                 break;
00481 
00482             case SDLK_RIGHT:
00483                 break;
00484 
00485             case SDLK_UP:
00486                 break;
00487 
00488             case SDLK_DOWN:
00489                 break;
00490 
00491             case SDLK_b:
00492                 {
00493                     audio_volume_t i_volume;
00494                     if ( !aout_VolumeDown( p_vout, 1, &i_volume ) )
00495                     {
00496                         msg_Dbg( p_vout, "audio volume is now %d", i_volume );
00497                     }
00498                     else
00499                     {
00500                         msg_Dbg( p_vout, "audio volume: operation not supported" );
00501                     }
00502                 }
00503                 break;
00504 
00505             case SDLK_n:
00506                 {
00507                     audio_volume_t i_volume;
00508                     if ( !aout_VolumeUp( p_vout, 1, &i_volume ) )
00509                     {
00510                         msg_Dbg( p_vout, "audio volume is now %d", i_volume );
00511                     }
00512                     else
00513                     {
00514                         msg_Dbg( p_vout, "audio volume: operation not supported" );
00515                     }
00516                 }
00517                 break;
00518 
00519              default:
00520                 break;
00521             }
00522             break;
00523 
00524         default:
00525             break;
00526         }
00527     }
00528 
00529     /* Fullscreen change */
00530     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
00531     {
00532         p_vout->b_fullscreen = ! p_vout->b_fullscreen;
00533 
00534         p_vout->p_sys->b_cursor_autohidden = 0;
00535         SDL_ShowCursor( p_vout->p_sys->b_cursor &&
00536                         ! p_vout->p_sys->b_cursor_autohidden );
00537 
00538         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00539         p_vout->i_changes |= VOUT_SIZE_CHANGE;
00540     }
00541 
00542     /*
00543      * Size change
00544      */
00545     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
00546     {
00547         msg_Dbg( p_vout, "video display resized (%dx%d)",
00548                  p_vout->p_sys->i_width, p_vout->p_sys->i_height );
00549 
00550         CloseDisplay( p_vout );
00551         OpenDisplay( p_vout );
00552 
00553         /* We don't need to signal the vout thread about the size change if
00554          * we can handle rescaling ourselves */
00555         if( p_vout->p_sys->p_overlay != NULL )
00556             p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
00557 
00558     }
00559 
00560     /* Pointer change */
00561     if( ! p_vout->p_sys->b_cursor_autohidden &&
00562         ( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) )
00563     {
00564         /* Hide the mouse automatically */
00565         p_vout->p_sys->b_cursor_autohidden = 1;
00566         SDL_ShowCursor( 0 );
00567     }
00568 
00569     return VLC_SUCCESS;
00570 }
00571 
00572 /*****************************************************************************
00573  * Display: displays previously rendered output
00574  *****************************************************************************
00575  * This function sends the currently rendered image to the display.
00576  *****************************************************************************/
00577 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
00578 {
00579     int x, y, w, h;
00580     SDL_Rect disp;
00581 
00582     vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
00583                        &x, &y, &w, &h );
00584     disp.x = x;
00585     disp.y = y;
00586     disp.w = w;
00587     disp.h = h;
00588 
00589     if( p_vout->p_sys->p_overlay == NULL )
00590     {
00591         /* RGB picture */
00592         SDL_Flip( p_vout->p_sys->p_display );
00593     }
00594     else
00595     {
00596         /* Overlay picture */
00597         SDL_UnlockYUVOverlay( p_pic->p_sys->p_overlay);
00598         SDL_DisplayYUVOverlay( p_pic->p_sys->p_overlay , &disp );
00599         SDL_LockYUVOverlay( p_pic->p_sys->p_overlay);
00600     }
00601 }
00602 
00603 /* following functions are local */
00604 
00605 /*****************************************************************************
00606  * OpenDisplay: open and initialize SDL device
00607  *****************************************************************************
00608  * Open and initialize display according to preferences specified in the vout
00609  * thread fields.
00610  *****************************************************************************/
00611 static int OpenDisplay( vout_thread_t *p_vout )
00612 {
00613     uint32_t i_flags;
00614     int i_bpp;
00615 
00616     /* SDL fucked up fourcc definitions on bigendian machines */
00617     uint32_t i_sdl_chroma;
00618 
00619     /* Set main window's size */
00620     p_vout->p_sys->i_width = p_vout->b_fullscreen ? p_vout->output.i_width :
00621                                                     p_vout->i_window_width;
00622     p_vout->p_sys->i_height = p_vout->b_fullscreen ? p_vout->output.i_height :
00623                                                      p_vout->i_window_height;
00624 
00625     /* Initialize flags and cursor */
00626     i_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
00627     i_flags |= p_vout->b_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
00628 
00629     i_bpp = SDL_VideoModeOK( p_vout->p_sys->i_width, p_vout->p_sys->i_height,
00630                              SDL_DEFAULT_BPP, i_flags );
00631     if( i_bpp == 0 )
00632     {
00633         msg_Err( p_vout, "no video mode available" );
00634         return VLC_EGENERIC;
00635     }
00636 
00637     p_vout->p_sys->p_display = SDL_SetVideoMode( p_vout->p_sys->i_width,
00638                                                  p_vout->p_sys->i_height,
00639                                                  i_bpp, i_flags );
00640 
00641     if( p_vout->p_sys->p_display == NULL )
00642     {
00643         msg_Err( p_vout, "cannot set video mode" );
00644         return VLC_EGENERIC;
00645     }
00646 
00647     SDL_LockSurface( p_vout->p_sys->p_display );
00648 
00649     /* Choose the chroma we will try first. */
00650     switch( p_vout->render.i_chroma )
00651     {
00652         case VLC_FOURCC('Y','U','Y','2'):
00653         case VLC_FOURCC('Y','U','N','V'):
00654             p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00655             i_sdl_chroma = SDL_YUY2_OVERLAY;
00656             break;
00657         case VLC_FOURCC('U','Y','V','Y'):
00658         case VLC_FOURCC('U','Y','N','V'):
00659         case VLC_FOURCC('Y','4','2','2'):
00660             p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
00661             i_sdl_chroma = SDL_UYVY_OVERLAY;
00662             break;
00663         case VLC_FOURCC('Y','V','Y','U'):
00664             p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
00665             i_sdl_chroma = SDL_YVYU_OVERLAY;
00666             break;
00667         case VLC_FOURCC('Y','V','1','2'):
00668         case VLC_FOURCC('I','4','2','0'):
00669         case VLC_FOURCC('I','Y','U','V'):
00670         default:
00671             p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00672             i_sdl_chroma = SDL_YV12_OVERLAY;
00673             break;
00674     }
00675 
00676     p_vout->p_sys->p_overlay =
00677         SDL_CreateYUVOverlay( 32, 32, i_sdl_chroma, p_vout->p_sys->p_display );
00678     /* FIXME: if the first overlay we find is software, don't stop,
00679      * because we may find a hardware one later ... */
00680 
00681     /* If this best choice failed, fall back to other chromas */
00682     if( p_vout->p_sys->p_overlay == NULL )
00683     {
00684         p_vout->output.i_chroma = VLC_FOURCC('I','Y','U','V');
00685         p_vout->p_sys->p_overlay =
00686             SDL_CreateYUVOverlay( 32, 32, SDL_IYUV_OVERLAY,
00687                                   p_vout->p_sys->p_display );
00688     }
00689 
00690     if( p_vout->p_sys->p_overlay == NULL )
00691     {
00692         p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00693         p_vout->p_sys->p_overlay =
00694             SDL_CreateYUVOverlay( 32, 32, SDL_YV12_OVERLAY,
00695                                   p_vout->p_sys->p_display );
00696     }
00697 
00698     if( p_vout->p_sys->p_overlay == NULL )
00699     {
00700         p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00701         p_vout->p_sys->p_overlay =
00702             SDL_CreateYUVOverlay( 32, 32, SDL_YUY2_OVERLAY,
00703                                   p_vout->p_sys->p_display );
00704     }
00705 
00706     if( p_vout->p_sys->p_overlay == NULL )
00707     {
00708         msg_Warn( p_vout, "no SDL overlay for 0x%.8x (%4.4s)",
00709                   p_vout->render.i_chroma, (char*)&p_vout->render.i_chroma );
00710 
00711         switch( p_vout->p_sys->p_display->format->BitsPerPixel )
00712         {
00713             case 8:
00714                 p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
00715                 p_vout->output.pf_setpalette = SetPalette;
00716                 break;
00717             case 15:
00718                 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00719                 break;
00720             case 16:
00721                 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00722                 break;
00723             case 24:
00724                 p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
00725                 break;
00726             case 32:
00727                 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00728                 break;
00729             default:
00730                 msg_Err( p_vout, "unknown screen depth %i",
00731                          p_vout->p_sys->p_display->format->BitsPerPixel );
00732                 SDL_UnlockSurface( p_vout->p_sys->p_display );
00733                 SDL_FreeSurface( p_vout->p_sys->p_display );
00734                 return VLC_EGENERIC;
00735         }
00736 
00737         p_vout->output.i_rmask = p_vout->p_sys->p_display->format->Rmask;
00738         p_vout->output.i_gmask = p_vout->p_sys->p_display->format->Gmask;
00739         p_vout->output.i_bmask = p_vout->p_sys->p_display->format->Bmask;
00740 
00741         SDL_WM_SetCaption( VOUT_TITLE " (software RGB SDL output)",
00742                            VOUT_TITLE " (software RGB SDL output)" );
00743     }
00744     else
00745     {
00746         if( p_vout->p_sys->p_overlay->hw_overlay )
00747         {
00748             SDL_WM_SetCaption( VOUT_TITLE " (hardware YUV SDL output)",
00749                                VOUT_TITLE " (hardware YUV SDL output)" );
00750         }
00751         else
00752         {
00753             SDL_WM_SetCaption( VOUT_TITLE " (software YUV SDL output)",
00754                                VOUT_TITLE " (software YUV SDL output)" );
00755         }
00756     }
00757 
00758     SDL_EventState( SDL_KEYUP, SDL_IGNORE );               /* ignore keys up */
00759 
00760     return VLC_SUCCESS;
00761 }
00762 
00763 /*****************************************************************************
00764  * CloseDisplay: close and reset SDL device
00765  *****************************************************************************
00766  * This function returns all resources allocated by OpenDisplay and restore
00767  * the original state of the device.
00768  *****************************************************************************/
00769 static void CloseDisplay( vout_thread_t *p_vout )
00770 {
00771     SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
00772     SDL_UnlockSurface ( p_vout->p_sys->p_display );
00773     SDL_FreeSurface( p_vout->p_sys->p_display );
00774 }
00775 
00776 /*****************************************************************************
00777  * NewPicture: allocate a picture
00778  *****************************************************************************
00779  * Returns 0 on success, -1 otherwise
00780  *****************************************************************************/
00781 static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
00782 {
00783     int i_width  = p_vout->output.i_width;
00784     int i_height = p_vout->output.i_height;
00785 
00786     if( p_vout->p_sys->p_overlay == NULL )
00787     {
00788         /* RGB picture */
00789         if( p_vout->p_sys->i_surfaces )
00790         {
00791             /* We already allocated this surface, return */
00792             return VLC_EGENERIC;
00793         }
00794 
00795         p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00796 
00797         if( p_pic->p_sys == NULL )
00798         {
00799             return VLC_ENOMEM;
00800         }
00801 
00802         switch( p_vout->p_sys->p_display->format->BitsPerPixel )
00803         {
00804             case 8:
00805                 p_pic->p->i_pixel_pitch = 1;
00806                 break;
00807             case 15:
00808             case 16:
00809                 p_pic->p->i_pixel_pitch = 2;
00810                 break;
00811             case 24:
00812             case 32:
00813                 p_pic->p->i_pixel_pitch = 4;
00814                 break;
00815             default:
00816                 return VLC_EGENERIC;
00817         }
00818 
00819         p_pic->p->p_pixels = p_vout->p_sys->p_display->pixels;
00820         p_pic->p->i_lines = p_vout->p_sys->p_display->h;
00821         p_pic->p->i_visible_lines = p_vout->p_sys->p_display->h;
00822         p_pic->p->i_pitch = p_vout->p_sys->p_display->pitch;
00823         p_pic->p->i_visible_pitch =
00824             p_pic->p->i_pixel_pitch * p_vout->p_sys->p_display->w;
00825 
00826         p_vout->p_sys->i_surfaces++;
00827 
00828         p_pic->i_planes = 1;
00829     }
00830     else
00831     {
00832         p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00833 
00834         if( p_pic->p_sys == NULL )
00835         {
00836             return VLC_ENOMEM;
00837         }
00838 
00839         p_pic->p_sys->p_overlay =
00840             SDL_CreateYUVOverlay( i_width, i_height,
00841                                   p_vout->output.i_chroma,
00842                                   p_vout->p_sys->p_display );
00843 
00844         if( p_pic->p_sys->p_overlay == NULL )
00845         {
00846             free( p_pic->p_sys );
00847             return VLC_EGENERIC;
00848         }
00849 
00850         SDL_LockYUVOverlay( p_pic->p_sys->p_overlay );
00851 
00852         p_pic->Y_PIXELS = p_pic->p_sys->p_overlay->pixels[0];
00853         p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_overlay->h;
00854         p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h;
00855         p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[0];
00856 
00857         switch( p_vout->output.i_chroma )
00858         {
00859         case SDL_YV12_OVERLAY:
00860             p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00861             p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w;
00862 
00863             p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
00864             p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00865             p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00866             p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
00867             p_pic->p[U_PLANE].i_pixel_pitch = 1;
00868             p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00869 
00870             p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
00871             p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00872             p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00873             p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
00874             p_pic->p[V_PLANE].i_pixel_pitch = 1;
00875             p_pic->p[V_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00876 
00877             p_pic->i_planes = 3;
00878             break;
00879 
00880         case SDL_IYUV_OVERLAY:
00881             p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00882             p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w;
00883 
00884             p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
00885             p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00886             p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00887             p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
00888             p_pic->p[U_PLANE].i_pixel_pitch = 1;
00889             p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00890 
00891             p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
00892             p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
00893             p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
00894             p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
00895             p_pic->p[V_PLANE].i_pixel_pitch = 1;
00896             p_pic->p[V_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
00897 
00898             p_pic->i_planes = 3;
00899             break;
00900 
00901         default:
00902             p_pic->p[Y_PLANE].i_pixel_pitch = 2;
00903             p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w * 2;
00904 
00905             p_pic->i_planes = 1;
00906             break;
00907         }
00908     }
00909 
00910     return VLC_SUCCESS;
00911 }
00912 
00913 /*****************************************************************************
00914  * SetPalette: sets an 8 bpp palette
00915  *****************************************************************************/
00916 static void SetPalette( vout_thread_t *p_vout,
00917                         uint16_t *red, uint16_t *green, uint16_t *blue )
00918 {
00919     SDL_Color colors[256];
00920     int i;
00921 
00922     /* Fill colors with color information */
00923     for( i = 0; i < 256; i++ )
00924     {
00925         colors[ i ].r = red[ i ] >> 8;
00926         colors[ i ].g = green[ i ] >> 8;
00927         colors[ i ].b = blue[ i ] >> 8;
00928     }
00929 
00930     /* Set palette */
00931     if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
00932     {
00933         msg_Err( p_vout, "failed setting palette" );
00934     }
00935 }
00936 

Generated on Tue Dec 20 10:14:28 2005 for vlc-0.8.4a by  doxygen 1.4.2