]> git.sesse.net Git - vlc/blobdiff - plugins/sdl/vout_sdl.c
* ./extras/MacOSX_dvdioctl: removed outdated files.
[vlc] / plugins / sdl / vout_sdl.c
index 84e91e1a6740693ed2d59c90fc6ecaae58e45600..8a1e4e34741f6d19bdbb813e21a5d746d5b7f9d7 100644 (file)
@@ -2,7 +2,7 @@
  * vout_sdl.c: SDL video output display method
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: vout_sdl.c,v 1.72 2001/12/19 18:14:23 sam Exp $
+ * $Id: vout_sdl.c,v 1.85 2002/03/18 19:14:52 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Pierre Baillet <oct@zoy.org>
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-#define MODULE_NAME sdl
-#include "modules_inner.h"
-
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include "defs.h"
-
 #include <errno.h>                                                 /* ENOMEM */
 #include <stdlib.h>                                                /* free() */
 #include <string.h>                                            /* strerror() */
 
+#include <videolan/vlc.h>
+
 #include <sys/types.h>
 #ifndef WIN32
 #   include <netinet/in.h>                            /* BSD: struct in_addr */
 
 #include SDL_INCLUDE_FILE
 
-#include "common.h"
-#include "intf_msg.h"
-#include "threads.h"
-#include "mtime.h"
 #include "netutils.h"
-#include "tests.h"
 
 #include "video.h"
 #include "video_output.h"
 
 #include "interface.h"
 
-#include "modules.h"
-#include "modules_export.h"
+#include "stream_control.h"                 /* needed by input_ext-intf.h... */
+#include "input_ext-intf.h"
 
-#define SDL_MAX_DIRECTBUFFERS 5
+#define SDL_MAX_DIRECTBUFFERS 10
 #define SDL_DEFAULT_BPP 16
 
 /*****************************************************************************
 typedef struct vout_sys_s
 {
     SDL_Surface *   p_display;                             /* display device */
-    SDL_Overlay *   p_overlay; /* An overlay we keep to grab the XVideo port */
 
     int i_width;
     int i_height;
 
+    /* For YUV output */
+    SDL_Overlay * p_overlay;   /* An overlay we keep to grab the XVideo port */
+
+    /* For RGB output */
+    int i_surfaces;
+
     boolean_t   b_cursor;
     boolean_t   b_cursor_autohidden;
     mtime_t     i_lastmoved;
@@ -92,20 +89,46 @@ typedef struct picture_sys_s
 
 } picture_sys_t;
 
+/*****************************************************************************
+ * Seeking function TODO: put this in a generic location !
+ *****************************************************************************/
+static __inline__ void vout_Seek( off_t i_seek )
+{
+    off_t i_tell;
+
+    vlc_mutex_lock( &p_input_bank->lock );
+    if( p_input_bank->pp_input[0] != NULL )
+    {
+#define S p_input_bank->pp_input[0]->stream
+        i_tell = S.p_selected_area->i_tell + i_seek * (off_t)50 * S.i_mux_rate;
+
+        i_tell = ( i_tell <= 0 /*S.p_selected_area->i_start*/ )
+                   ? 0 /*S.p_selected_area->i_start*/
+                   : ( i_tell >= S.p_selected_area->i_size )
+                       ? S.p_selected_area->i_size
+                       : i_tell;
+
+        input_Seek( p_input_bank->pp_input[0], i_tell );
+#undef S
+    }
+    vlc_mutex_unlock( &p_input_bank->lock );
+}
+
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static int  vout_Probe      ( probedata_t *p_data );
 static int  vout_Create     ( struct vout_thread_s * );
 static int  vout_Init       ( struct vout_thread_s * );
 static void vout_End        ( struct vout_thread_s * );
 static void vout_Destroy    ( struct vout_thread_s * );
 static int  vout_Manage     ( struct vout_thread_s * );
+static void vout_Render     ( struct vout_thread_s *, struct picture_s * );
 static void vout_Display    ( struct vout_thread_s *, struct picture_s * );
 
-static int  SDLOpenDisplay      ( vout_thread_t *p_vout );
-static void SDLCloseDisplay     ( vout_thread_t *p_vout );
-static int  SDLNewPicture       ( vout_thread_t *p_vout, picture_t *p_pic );
+static int  OpenDisplay     ( struct vout_thread_s * );
+static void CloseDisplay    ( struct vout_thread_s * );
+static int  NewPicture      ( struct vout_thread_s *, struct picture_s * );
+static void SetPalette      ( struct vout_thread_s *, u16 *, u16 *, u16 * );
 
 /*****************************************************************************
  * Functions exported as capabilities. They are declared as static so that
@@ -113,35 +136,13 @@ static int  SDLNewPicture       ( vout_thread_t *p_vout, picture_t *p_pic );
  *****************************************************************************/
 void _M( vout_getfunctions )( function_list_t * p_function_list )
 {
-    p_function_list->pf_probe = vout_Probe;
     p_function_list->functions.vout.pf_create     = vout_Create;
     p_function_list->functions.vout.pf_init       = vout_Init;
     p_function_list->functions.vout.pf_end        = vout_End;
     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
     p_function_list->functions.vout.pf_manage     = vout_Manage;
+    p_function_list->functions.vout.pf_render     = vout_Render;
     p_function_list->functions.vout.pf_display    = vout_Display;
-    p_function_list->functions.vout.pf_setpalette = NULL;
-}
-
-/*****************************************************************************
- * vout_Probe: probe the video driver and return a score
- *****************************************************************************
- * This function tries to initialize SDL and returns a score to the
- * plugin manager so that it can select the best plugin.
- *****************************************************************************/
-static int vout_Probe( probedata_t *p_data )
-{
-    if( SDL_WasInit( SDL_INIT_VIDEO ) != 0 )
-    {
-        return( 0 );
-    }
-
-    if( TestMethod( VOUT_METHOD_VAR, "sdl" ) )
-    {
-        return( 999 );
-    }
-
-    return( 100 );
 }
 
 /*****************************************************************************
@@ -153,6 +154,13 @@ static int vout_Probe( probedata_t *p_data )
  *****************************************************************************/
 static int vout_Create( vout_thread_t *p_vout )
 {
+    char *psz_method;
+
+    if( SDL_WasInit( SDL_INIT_VIDEO ) != 0 )
+    {
+        return( 1 );
+    }
+
     /* Allocate structure */
     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
     if( p_vout->p_sys == NULL )
@@ -161,6 +169,20 @@ static int vout_Create( vout_thread_t *p_vout )
         return( 1 );
     }
 
+    psz_method = config_GetPszVariable( "vout" );
+    if( psz_method )
+    {
+        while( *psz_method && *psz_method != ':' )
+        {
+            psz_method++;
+        }
+
+        if( *psz_method )
+        {
+            setenv( "SDL_VIDEODRIVER", psz_method + 1, 1 );
+        }
+    }
+
     /* Initialize library */
     if( SDL_Init( SDL_INIT_VIDEO
 #ifndef WIN32
@@ -179,7 +201,7 @@ static int vout_Create( vout_thread_t *p_vout )
         return( 1 );
     }
 
-    p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */
+    p_vout->p_sys->b_cursor = 1;
     p_vout->p_sys->b_cursor_autohidden = 0;
     p_vout->p_sys->i_lastmoved = mdate();
 
@@ -197,6 +219,7 @@ static int vout_Create( vout_thread_t *p_vout )
             * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
     }
 
+#if 0
     if( p_vout->p_sys->i_width <= 300 && p_vout->p_sys->i_height <= 300 )
     {
         p_vout->p_sys->i_width <<= 1;
@@ -207,8 +230,9 @@ static int vout_Create( vout_thread_t *p_vout )
         p_vout->p_sys->i_width += p_vout->p_sys->i_width >> 1;
         p_vout->p_sys->i_height += p_vout->p_sys->i_height >> 1;
     }
+#endif
 
-    if( SDLOpenDisplay( p_vout ) )
+    if( OpenDisplay( p_vout ) )
     {
         intf_ErrMsg( "vout error: can't set up SDL (%s)", SDL_GetError() );
         SDL_QuitSubSystem( SDL_INIT_VIDEO );
@@ -229,20 +253,27 @@ static int vout_Init( vout_thread_t *p_vout )
     int i_index;
     picture_t *p_pic;
 
+    p_vout->p_sys->i_surfaces = 0;
+
     I_OUTPUTPICTURES = 0;
 
     /* Initialize the output structure */
-    switch( p_vout->render.i_chroma )
+    if( p_vout->p_sys->p_overlay == NULL )
     {
-        case YUV_420_PICTURE:
-            p_vout->output.i_chroma = p_vout->render.i_chroma;
-            p_vout->output.i_width  = p_vout->render.i_width;
-            p_vout->output.i_height = p_vout->render.i_height;
-            p_vout->output.i_aspect = p_vout->render.i_aspect;
-            break;
-
-        default:
-            return( 0 );
+        /* All we have is an RGB image with square pixels */
+        p_vout->output.i_width  = p_vout->p_sys->i_width;
+        p_vout->output.i_height = p_vout->p_sys->i_height;
+        p_vout->output.i_aspect = p_vout->p_sys->i_width
+                                   * VOUT_ASPECT_FACTOR
+                                   / p_vout->p_sys->i_height;
+    }
+    else
+    {
+        /* We may need to convert the chroma, but at least we keep the
+         * aspect ratio */
+        p_vout->output.i_width  = p_vout->render.i_width;
+        p_vout->output.i_height = p_vout->render.i_height;
+        p_vout->output.i_aspect = p_vout->render.i_aspect;
     }
 
     /* Try to initialize SDL_MAX_DIRECTBUFFERS direct buffers */
@@ -261,18 +292,13 @@ static int vout_Init( vout_thread_t *p_vout )
         }
 
         /* Allocate the picture if we found one */
-        if( p_pic == NULL || SDLNewPicture( p_vout, p_pic ) )
+        if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
         {
             break;
         }
 
-        p_pic->i_status        = DESTROYED_PICTURE;
-        p_pic->i_type          = DIRECT_PICTURE;
-
-        p_pic->i_left_margin   =
-        p_pic->i_right_margin  =
-        p_pic->i_top_margin    =
-        p_pic->i_bottom_margin = 0;
+        p_pic->i_status = DESTROYED_PICTURE;
+        p_pic->i_type   = DIRECT_PICTURE;
 
         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
 
@@ -295,8 +321,17 @@ static void vout_End( vout_thread_t *p_vout )
     for( i_index = I_OUTPUTPICTURES ; i_index ; )
     {
         i_index--;
-        SDL_UnlockYUVOverlay( PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
-        SDL_FreeYUVOverlay( PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
+        if( p_vout->p_sys->p_overlay == NULL )
+        {
+            /* RGB picture */
+        }
+        else
+        {
+            SDL_UnlockYUVOverlay(
+                    PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
+            SDL_FreeYUVOverlay(
+                    PP_OUTPUTPICTURE[ i_index ]->p_sys->p_overlay );
+        }
         free( PP_OUTPUTPICTURE[ i_index ]->p_sys );
     }
 }
@@ -308,7 +343,7 @@ static void vout_End( vout_thread_t *p_vout )
  *****************************************************************************/
 static void vout_Destroy( vout_thread_t *p_vout )
 {
-    SDLCloseDisplay( p_vout );
+    CloseDisplay( p_vout );
 
     SDL_QuitSubSystem( SDL_INIT_VIDEO );
 
@@ -333,8 +368,8 @@ static int vout_Manage( vout_thread_t *p_vout )
         case SDL_VIDEORESIZE:                          /* Resizing of window */
             p_vout->p_sys->i_width = event.resize.w;
             p_vout->p_sys->i_height = event.resize.h;
-            SDLCloseDisplay( p_vout );
-            SDLOpenDisplay( p_vout );
+            CloseDisplay( p_vout );
+            OpenDisplay( p_vout );
             break;
 
         case SDL_MOUSEMOTION:
@@ -366,7 +401,19 @@ static int vout_Manage( vout_thread_t *p_vout )
             switch( event.button.button )
             {
             case SDL_BUTTON_LEFT:
-                /* Handle clicks */
+                /* In this part we will eventually manage
+                 * clicks for DVD navigation for instance. For the
+                 * moment just pause the stream. */
+                input_SetStatus( p_input_bank->pp_input[0],
+                                 INPUT_STATUS_PAUSE );
+                break;
+
+            case 4:
+                vout_Seek( 15 );
+                break;
+
+            case 5:
+                vout_Seek( -15 );
                 break;
             }
             break;
@@ -380,7 +427,7 @@ static int vout_Manage( vout_thread_t *p_vout )
             switch( event.key.keysym.sym )
             {
             case SDLK_q:                                             /* quit */
-           case SDLK_ESCAPE:
+            case SDLK_ESCAPE:
                 p_main->p_intf->b_die = 1;
                 break;
 
@@ -411,7 +458,23 @@ static int vout_Manage( vout_thread_t *p_vout )
             case SDLK_MENU:
                 p_main->p_intf->b_menu_change = 1;
                 break;
-                
+
+            case SDLK_LEFT:
+                vout_Seek( -5 );
+                break;
+
+            case SDLK_RIGHT:
+                vout_Seek( 5 );
+                break;
+
+            case SDLK_UP:
+                vout_Seek( 60 );
+                break;
+
+            case SDLK_DOWN:
+                vout_Seek( -60 );
+                break;
+
             case SDLK_F10: network_ChannelJoin( 0 ); break;
             case SDLK_F1:  network_ChannelJoin( 1 ); break;
             case SDLK_F2:  network_ChannelJoin( 2 ); break;
@@ -424,7 +487,6 @@ static int vout_Manage( vout_thread_t *p_vout )
             case SDLK_F9:  network_ChannelJoin( 9 ); break;
 
             default:
-                intf_DbgMsg( "unhandled key %i", event.key.keysym.sym );
                 break;
             }
             break;
@@ -460,6 +522,14 @@ static int vout_Manage( vout_thread_t *p_vout )
     return( 0 );
 }
 
+/*****************************************************************************
+ * vout_Render: render previously calculated output
+ *****************************************************************************/
+static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    ;
+}
+
 /*****************************************************************************
  * vout_Display: displays previously rendered output
  *****************************************************************************
@@ -477,26 +547,35 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
     disp.w = w;
     disp.h = h;
 
-    SDL_UnlockYUVOverlay( p_pic->p_sys->p_overlay);
-    SDL_DisplayYUVOverlay( p_pic->p_sys->p_overlay , &disp );
-    SDL_LockYUVOverlay( p_pic->p_sys->p_overlay);
+    if( p_vout->p_sys->p_overlay == NULL )
+    {
+        /* RGB picture */
+        SDL_Flip( p_vout->p_sys->p_display );
+    }
+    else
+    {
+        /* Overlay picture */
+        SDL_UnlockYUVOverlay( p_pic->p_sys->p_overlay);
+        SDL_DisplayYUVOverlay( p_pic->p_sys->p_overlay , &disp );
+        SDL_LockYUVOverlay( p_pic->p_sys->p_overlay);
+    }
 }
 
 /* following functions are local */
 
 /*****************************************************************************
- * SDLOpenDisplay: open and initialize SDL device
+ * OpenDisplay: open and initialize SDL device
  *****************************************************************************
  * Open and initialize display according to preferences specified in the vout
  * thread fields.
  *****************************************************************************/
-static int SDLOpenDisplay( vout_thread_t *p_vout )
+static int OpenDisplay( vout_thread_t *p_vout )
 {
     Uint32 i_flags;
     int    i_bpp;
 
     /* Initialize flags and cursor */
-    i_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE;
+    i_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
     i_flags |= p_vout->b_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
 
     i_bpp = SDL_VideoModeOK( p_vout->p_sys->i_width, p_vout->p_sys->i_height,
@@ -519,27 +598,110 @@ static int SDLOpenDisplay( vout_thread_t *p_vout )
 
     SDL_LockSurface( p_vout->p_sys->p_display );
 
+    /* Choose the chroma we will try first. */
+    switch( p_vout->render.i_chroma )
+    {
+        case FOURCC_YUY2:
+        case FOURCC_YUNV:
+            p_vout->output.i_chroma = SDL_YUY2_OVERLAY;
+            break;
+        case FOURCC_UYVY:
+        case FOURCC_UYNV:
+        case FOURCC_Y422:
+            p_vout->output.i_chroma = SDL_UYVY_OVERLAY;
+            break;
+        case FOURCC_YVYU:
+            p_vout->output.i_chroma = SDL_YVYU_OVERLAY;
+            break;
+        case FOURCC_YV12:
+        case FOURCC_I420:
+        case FOURCC_IYUV:
+        default:
+            p_vout->output.i_chroma = SDL_YV12_OVERLAY;
+            break;
+    }
+
     p_vout->p_sys->p_overlay =
-        SDL_CreateYUVOverlay( 32, 32, SDL_YV12_OVERLAY,
+        SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
                               p_vout->p_sys->p_display );
+    /* FIXME: if the first overlay we find is software, don't stop,
+     * because we may find a hardware one later ... */
 
+    /* If this best choice failed, fall back to other chromas */
     if( p_vout->p_sys->p_overlay == NULL )
     {
-        intf_ErrMsg( "vout error: cannot set overlay" );
-        SDL_UnlockSurface( p_vout->p_sys->p_display );
-        SDL_FreeSurface( p_vout->p_sys->p_display );
-        return( 1 );
+        p_vout->output.i_chroma = SDL_IYUV_OVERLAY;
+        p_vout->p_sys->p_overlay =
+            SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+                                  p_vout->p_sys->p_display );
     }
 
-    if( p_vout->p_sys->p_overlay->hw_overlay )
+    if( p_vout->p_sys->p_overlay == NULL )
     {
-        SDL_WM_SetCaption( VOUT_TITLE " (hardware SDL output)",
-                           VOUT_TITLE " (hardware SDL output)" );
+        p_vout->output.i_chroma = SDL_YV12_OVERLAY;
+        p_vout->p_sys->p_overlay =
+            SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+                                  p_vout->p_sys->p_display );
+    }
+
+    if( p_vout->p_sys->p_overlay == NULL )
+    {
+        p_vout->output.i_chroma = SDL_YUY2_OVERLAY;
+        p_vout->p_sys->p_overlay =
+            SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+                                  p_vout->p_sys->p_display );
+    }
+
+    if( p_vout->p_sys->p_overlay == NULL )
+    {
+        intf_WarnMsg( 3, "vout warning: no SDL overlay for 0x%.8x (%4.4s)",
+                         p_vout->render.i_chroma,
+                         (char*)&p_vout->render.i_chroma );
+
+        switch( p_vout->p_sys->p_display->format->BitsPerPixel )
+        {
+            case 8:
+                p_vout->output.i_chroma = FOURCC_RGB2;
+                p_vout->output.pf_setpalette = SetPalette;
+                break;
+            case 15:
+                p_vout->output.i_chroma = FOURCC_RV15;
+                break;
+            case 16:
+                p_vout->output.i_chroma = FOURCC_RV16;
+                break;
+            case 24:
+                p_vout->output.i_chroma = FOURCC_RV24;
+                break;
+            case 32:
+                p_vout->output.i_chroma = FOURCC_RV32;
+                break;
+            default:
+                intf_ErrMsg( "vout error: unknown screen depth" );
+                SDL_UnlockSurface( p_vout->p_sys->p_display );
+                SDL_FreeSurface( p_vout->p_sys->p_display );
+                return( -1 );
+        }
+
+        p_vout->output.i_rmask = p_vout->p_sys->p_display->format->Rmask;
+        p_vout->output.i_gmask = p_vout->p_sys->p_display->format->Gmask;
+        p_vout->output.i_bmask = p_vout->p_sys->p_display->format->Bmask;
+
+        SDL_WM_SetCaption( VOUT_TITLE " (software RGB SDL output)",
+                           VOUT_TITLE " (software RGB SDL output)" );
     }
     else
     {
-        SDL_WM_SetCaption( VOUT_TITLE " (software SDL output)",
-                           VOUT_TITLE " (software SDL output)" );
+        if( p_vout->p_sys->p_overlay->hw_overlay )
+        {
+            SDL_WM_SetCaption( VOUT_TITLE " (hardware YUV SDL output)",
+                               VOUT_TITLE " (hardware YUV SDL output)" );
+        }
+        else
+        {
+            SDL_WM_SetCaption( VOUT_TITLE " (software YUV SDL output)",
+                               VOUT_TITLE " (software YUV SDL output)" );
+        }
     }
 
     SDL_EventState( SDL_KEYUP, SDL_IGNORE );               /* ignore keys up */
@@ -548,12 +710,12 @@ static int SDLOpenDisplay( vout_thread_t *p_vout )
 }
 
 /*****************************************************************************
- * SDLCloseDisplay: close and reset SDL device
+ * CloseDisplay: close and reset SDL device
  *****************************************************************************
- * This function returns all resources allocated by SDLOpenDisplay and restore
+ * This function returns all resources allocated by OpenDisplay and restore
  * the original state of the device.
  *****************************************************************************/
-static void SDLCloseDisplay( vout_thread_t *p_vout )
+static void CloseDisplay( vout_thread_t *p_vout )
 {
     SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
     SDL_UnlockSurface ( p_vout->p_sys->p_display );
@@ -561,67 +723,167 @@ static void SDLCloseDisplay( vout_thread_t *p_vout )
 }
 
 /*****************************************************************************
- * SDLNewPicture: allocate a picture
+ * NewPicture: allocate a picture
  *****************************************************************************
  * Returns 0 on success, -1 otherwise
  *****************************************************************************/
-static int SDLNewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
 {
     int i_width  = p_vout->output.i_width;
     int i_height = p_vout->output.i_height;
 
-    switch( p_vout->output.i_chroma )
+    if( p_vout->p_sys->p_overlay == NULL )
     {
-        case YUV_420_PICTURE:
-            /* We know this chroma, allocate a buffer which will be used
-             * directly by the decoder */
-            p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+        /* RGB picture */
+        if( p_vout->p_sys->i_surfaces )
+        {
+            /* We already allocated this surface, return */
+            return -1;
+        }
 
-            if( p_pic->p_sys == NULL )
-            {
-                return -1;
-            }
+        p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
 
-            p_pic->p_sys->p_overlay =
-                SDL_CreateYUVOverlay( i_width, i_height,
-                                      SDL_YV12_OVERLAY,
-                                      p_vout->p_sys->p_display );
+        if( p_pic->p_sys == NULL )
+        {
+            return -1;
+        }
 
-            if( p_pic->p_sys->p_overlay == NULL )
-            {
-                free( p_pic->p_sys );
-                return -1;
-            }
+        switch( p_vout->p_sys->p_display->format->BitsPerPixel )
+        {
+            case 8:
+                p_pic->p->i_pixel_bytes = 1;
+                break;
+            case 15:
+            case 16:
+                p_pic->p->i_pixel_bytes = 2;
+                break;
+            case 24:
+            case 32:
+                p_pic->p->i_pixel_bytes = 4;
+                break;
+            default:
+                return( -1 );
+        }
 
-            SDL_LockYUVOverlay( p_pic->p_sys->p_overlay );
+        p_pic->p->p_pixels = p_vout->p_sys->p_display->pixels;
+        p_pic->p->i_lines = p_vout->p_sys->p_display->h;
+        p_pic->p->i_pitch = p_vout->p_sys->p_display->pitch;
 
-            /* Precalculate some values */
-            p_pic->i_size         = i_width * i_height;
-            p_pic->i_chroma_width = i_width / 2;
-            p_pic->i_chroma_size  = i_height * ( i_width / 2 );
+        if( p_pic->p->i_pitch ==
+                p_pic->p->i_pixel_bytes * p_vout->p_sys->p_display->w )
+        {
+            p_pic->p->b_margin = 0;
+        }
+        else
+        {
+            p_pic->p->b_margin = 1;
+            p_pic->p->b_hidden = 1;
+            p_pic->p->i_visible_bytes =
+                p_pic->p->i_pixel_bytes * p_vout->p_sys->p_display->w;
+        }
 
-            /* FIXME: try to get the right i_bytes value from p_overlay */
-            p_pic->planes[ Y_PLANE ].p_data = p_pic->p_sys->p_overlay->pixels[ 0 ];
-            p_pic->planes[ Y_PLANE ].i_bytes = p_pic->i_size * sizeof( u8 );
-            p_pic->planes[ Y_PLANE ].i_line_bytes = i_width * sizeof( u8 );
+        p_vout->p_sys->i_surfaces++;
 
-            p_pic->planes[ U_PLANE ].p_data = p_pic->p_sys->p_overlay->pixels[ 2 ];
-            p_pic->planes[ U_PLANE ].i_bytes = p_pic->i_size * sizeof( u8 ) / 4;
-            p_pic->planes[ U_PLANE ].i_line_bytes = p_pic->i_chroma_width * sizeof( u8 );
+        p_pic->i_planes = 1;
+    }
+    else
+    {
+        p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+        if( p_pic->p_sys == NULL )
+        {
+            return -1;
+        }
+
+        p_pic->p_sys->p_overlay =
+            SDL_CreateYUVOverlay( i_width, i_height,
+                                  p_vout->output.i_chroma,
+                                  p_vout->p_sys->p_display );
 
-            p_pic->planes[ V_PLANE ].p_data = p_pic->p_sys->p_overlay->pixels[ 1 ];
-            p_pic->planes[ V_PLANE ].i_bytes = p_pic->i_size * sizeof( u8 ) / 4;
-            p_pic->planes[ V_PLANE ].i_line_bytes = p_pic->i_chroma_width * sizeof( u8 );
+        if( p_pic->p_sys->p_overlay == NULL )
+        {
+            free( p_pic->p_sys );
+            return -1;
+        }
+
+        SDL_LockYUVOverlay( p_pic->p_sys->p_overlay );
+
+        p_pic->Y_PIXELS = p_pic->p_sys->p_overlay->pixels[0];
+        p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_overlay->h;
+        p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[0];
+
+        switch( p_vout->output.i_chroma )
+        {
+        case SDL_YV12_OVERLAY:
+            p_pic->p[Y_PLANE].i_pixel_bytes = 1;
+            p_pic->p[Y_PLANE].b_margin = 0;
+
+            p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
+            p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+            p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
+            p_pic->p[U_PLANE].i_pixel_bytes = 1;
+            p_pic->p[U_PLANE].b_margin = 0;
+
+            p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
+            p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+            p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
+            p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            p_pic->p[V_PLANE].b_margin = 0;
 
             p_pic->i_planes = 3;
+            break;
+
+        case SDL_IYUV_OVERLAY:
+            p_pic->p[Y_PLANE].i_pixel_bytes = 1;
+            p_pic->p[Y_PLANE].b_margin = 0;
+
+            p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
+            p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+            p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
+            p_pic->p[U_PLANE].i_pixel_bytes = 1;
+            p_pic->p[U_PLANE].b_margin = 0;
+
+            p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
+            p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+            p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
+            p_pic->p[V_PLANE].i_pixel_bytes = 1;
+            p_pic->p[V_PLANE].b_margin = 0;
 
-            return 0;
+            p_pic->i_planes = 3;
+            break;
 
         default:
-            /* Unknown chroma, tell the guy to get lost */
-            p_pic->i_planes = 0;
+            p_pic->p[Y_PLANE].i_pixel_bytes = 2;
+            p_pic->p[Y_PLANE].b_margin = 0;
+
+            p_pic->i_planes = 1;
+            break;
+        }
+    }
+
+    return 0;
+}
+
+/*****************************************************************************
+ * SetPalette: sets an 8 bpp palette
+ *****************************************************************************/
+static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+{
+    SDL_Color colors[256];
+    int i;
+  
+    /* Fill colors with color information */
+    for( i = 0; i < 256; i++ )
+    {
+        colors[ i ].r = red[ i ] >> 8;
+        colors[ i ].g = green[ i ] >> 8;
+        colors[ i ].b = blue[ i ] >> 8;
+    }
 
-            return 0;
+    /* Set palette */
+    if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
+    {
+        intf_ErrMsg( "vout error: failed setting palette" );
     }
 }