]> git.sesse.net Git - vlc/commitdiff
* Merged trunk changesets 9185 9204 9205 9273 to 0.8.1 branch.
authorGildas Bazin <gbazin@videolan.org>
Wed, 10 Nov 2004 15:16:51 +0000 (15:16 +0000)
committerGildas Bazin <gbazin@videolan.org>
Wed, 10 Nov 2004 15:16:51 +0000 (15:16 +0000)
include/vlc_video.h
src/video_output/video_widgets.c
src/video_output/vout_subpictures.c

index 10a6644d399ace673b6d7c9c78471804b24cee03..14c497dc4417dc679d676f9f0b07d6a8405d3905 100644 (file)
@@ -244,6 +244,7 @@ struct subpicture_t
     vlc_bool_t      b_ephemer;     /**< If this flag is set to true
                                       the subtitle will be displayed
                                       untill the next one appear */
+    vlc_bool_t      b_fade;        /**< enable fading */
     /**@}*/
 
     subpicture_region_t *p_region;  /**< region list composing this subtitle */
index d7480556aaecc105821965fc28842bfab3b2fb41..27f4e2f278479db15e117578f0b75960b917a510 100644 (file)
 #include <vlc/vout.h>
 #include <osd.h>
 
+#include "vlc_video.h"
+#include "vlc_filter.h"
+
 #define STYLE_EMPTY 0
 #define STYLE_FILLED 1
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static void DrawRect( vout_thread_t *, subpicture_t *, int, int, int, int,
-                      short );
-static void DrawTriangle( vout_thread_t *, subpicture_t *, int, int, int, int,
-                          short );
-static void Render    ( vout_thread_t *, picture_t *, const subpicture_t * );
-static void RenderI420( vout_thread_t *, picture_t *, const subpicture_t *,
-                        int );
-static void RenderYUY2( vout_thread_t *, picture_t *, const subpicture_t *,
-                        int );
-static void RenderRV32( vout_thread_t *, picture_t *, const subpicture_t *,
-                        int );
-static subpicture_t *vout_CreateWidget( vout_thread_t *, int );
-static void FreeWidget( subpicture_t * );
-
-/**
- * Private data in a subpicture.
- */
-struct subpicture_sys_t
-{
-    int     i_x;
-    int     i_y;
-    int     i_width;
-    int     i_height;
-    uint8_t *p_pic;
-};
+static void DrawRect( subpicture_t *, int, int, int, int, short );
+static void DrawTriangle( subpicture_t *, int, int, int, int, short );
+static void CreatePicture( spu_t *, subpicture_t *, int, int, int, int );
+static subpicture_t *vout_CreateWidget( spu_t *, int );
 
 /*****************************************************************************
  * Draws a rectangle at the given position in the subpic.
  * It may be filled (fill == STYLE_FILLED) or empty (fill == STYLE_EMPTY).
  *****************************************************************************/
-static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
-                      int i_x1, int i_y1, int i_x2, int i_y2, short fill )
+static void DrawRect( subpicture_t *p_subpic, int i_x1, int i_y1,
+                      int i_x2, int i_y2, short fill )
 {
     int x, y;
-    subpicture_sys_t *p_widget = p_subpic->p_sys;
+    uint8_t *p_a = p_subpic->p_region->picture.A_PIXELS;
+    int i_pitch = p_subpic->p_region->picture.Y_PITCH;
 
     if( fill == STYLE_FILLED )
     {
@@ -76,7 +59,7 @@ static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
         {
             for( x = i_x1; x <= i_x2; x++ )
             {
-                p_widget->p_pic[ x + p_widget->i_width * y ] = 1;
+                p_a[ x + i_pitch * y ] = 0xff;
             }
         }
     }
@@ -84,13 +67,13 @@ static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
     {
         for( y = i_y1; y <= i_y2; y++ )
         {
-            p_widget->p_pic[ i_x1 + p_widget->i_width * y ] = 1;
-            p_widget->p_pic[ i_x2 + p_widget->i_width * y ] = 1;
+            p_a[ i_x1 + i_pitch * y ] = 0xff;
+            p_a[ i_x2 + i_pitch * y ] = 0xff;
         }
         for( x = i_x1; x <= i_x2; x++ )
         {
-            p_widget->p_pic[ x + p_widget->i_width * i_y1 ] = 1;
-            p_widget->p_pic[ x + p_widget->i_width * i_y2 ] = 1;
+            p_a[ x + i_pitch * i_y1 ] = 0xff;
+            p_a[ x + i_pitch * i_y2 ] = 0xff;
         }
     }
 }
@@ -99,11 +82,12 @@ static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
  * Draws a triangle at the given position in the subpic.
  * It may be filled (fill == STYLE_FILLED) or empty (fill == STYLE_EMPTY).
  *****************************************************************************/
-static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
-                          int i_x1, int i_y1, int i_x2, int i_y2, short fill )
+static void DrawTriangle( subpicture_t *p_subpic, int i_x1, int i_y1,
+                          int i_x2, int i_y2, short fill )
 {
     int x, y, i_mid, h;
-    subpicture_sys_t *p_widget = p_subpic->p_sys;
+    uint8_t *p_a = p_subpic->p_region->picture.A_PIXELS;
+    int i_pitch = p_subpic->p_region->picture.Y_PITCH;
 
     i_mid = i_y1 + ( ( i_y2 - i_y1 ) >> 1 );
 
@@ -116,8 +100,8 @@ static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
                 h = y - i_y1;
                 for( x = i_x1; x <= i_x1 + h && x <= i_x2; x++ )
                 {
-                    p_widget->p_pic[ x + p_widget->i_width * y ] = 1;
-                    p_widget->p_pic[ x + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                    p_a[ x + i_pitch * y ] = 0xff;
+                    p_a[ x + i_pitch * ( i_y2 - h ) ] = 0xff;
                 }
             }
         }
@@ -126,10 +110,10 @@ static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
             for( y = i_y1; y <= i_mid; y++ )
             {
                 h = y - i_y1;
-                p_widget->p_pic[ i_x1 + p_widget->i_width * y ] = 1;
-                p_widget->p_pic[ i_x1 + h + p_widget->i_width * y ] = 1;
-                p_widget->p_pic[ i_x1 + p_widget->i_width * ( i_y2 - h ) ] = 1;
-                p_widget->p_pic[ i_x1 + h + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                p_a[ i_x1 + i_pitch * y ] = 0xff;
+                p_a[ i_x1 + h + i_pitch * y ] = 0xff;
+                p_a[ i_x1 + i_pitch * ( i_y2 - h ) ] = 0xff;
+                p_a[ i_x1 + h + i_pitch * ( i_y2 - h ) ] = 0xff;
             }
         }
     }
@@ -142,8 +126,8 @@ static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
                 h = y - i_y1;
                 for( x = i_x1; x >= i_x1 - h && x >= i_x2; x-- )
                 {
-                    p_widget->p_pic[ x + p_widget->i_width * y ] = 1;
-                    p_widget->p_pic[ x + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                    p_a[ x + i_pitch * y ] = 0xff;
+                    p_a[ x + i_pitch * ( i_y2 - h ) ] = 0xff;
                 }
             }
         }
@@ -152,256 +136,71 @@ static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
             for( y = i_y1; y <= i_mid; y++ )
             {
                 h = y - i_y1;
-                p_widget->p_pic[ i_x1 + p_widget->i_width * y ] = 1;
-                p_widget->p_pic[ i_x1 - h + p_widget->i_width * y ] = 1;
-                p_widget->p_pic[ i_x1 + p_widget->i_width * ( i_y2 - h ) ] = 1;
-                p_widget->p_pic[ i_x1 - h + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                p_a[ i_x1 + i_pitch * y ] = 0xff;
+                p_a[ i_x1 - h + i_pitch * y ] = 0xff;
+                p_a[ i_x1 + i_pitch * ( i_y2 - h ) ] = 0xff;
+                p_a[ i_x1 - h + i_pitch * ( i_y2 - h ) ] = 0xff;
             }
         }
     }
 }
 
 /*****************************************************************************
- * Render: place widget in picture
- *****************************************************************************
- * This function merges the previously drawn widget into a picture
+ * Create Picture: creates subpicture region and picture
  *****************************************************************************/
-static void Render( vout_thread_t *p_vout, picture_t *p_pic,
-                    const subpicture_t *p_subpic )
-{
-    int i_fade_alpha = 255;
-    mtime_t i_fade_start = ( p_subpic->i_stop + p_subpic->i_start ) / 2;
-    mtime_t i_now = mdate();
-
-    if( i_now >= i_fade_start )
-    {
-        i_fade_alpha = 255 * ( p_subpic->i_stop - i_now ) /
-                       ( p_subpic->i_stop - i_fade_start );
-    }
-
-    switch( p_vout->output.i_chroma )
-    {
-        /* I420 target, no scaling */
-        case VLC_FOURCC('I','4','2','0'):
-        case VLC_FOURCC('I','Y','U','V'):
-        case VLC_FOURCC('Y','V','1','2'):
-            RenderI420( p_vout, p_pic, p_subpic, i_fade_alpha );
-            break;
-        /* RV32 target, scaling */
-        case VLC_FOURCC('R','V','2','4'):
-        case VLC_FOURCC('R','V','3','2'):
-            RenderRV32( p_vout, p_pic, p_subpic, i_fade_alpha );
-            break;
-        /* NVidia or BeOS overlay, no scaling */
-        case VLC_FOURCC('Y','U','Y','2'):
-            RenderYUY2( p_vout, p_pic, p_subpic, i_fade_alpha );
-            break;
-
-        default:
-            msg_Err( p_vout, "unknown chroma, can't render SPU" );
-            break;
-    }
-}
-
-/**
- * Draw a widget on a I420 (or similar) picture
- */
-static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
-                    const subpicture_t *p_subpic, int i_fade_alpha )
-{
-    subpicture_sys_t *p_widget = p_subpic->p_sys;
-    int i_plane, x, y, pen_x, pen_y;
-
-    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
-    {
-        uint8_t *p_in = p_pic->p[ i_plane ].p_pixels;
-        int i_pic_pitch = p_pic->p[ i_plane ].i_pitch;
-
-        if ( i_plane == 0 )
-        {
-            pen_x = p_widget->i_x;
-            pen_y = p_widget->i_y;
-#define alpha p_widget->p_pic[ x + y * p_widget->i_width ] * i_fade_alpha
-#define pixel p_in[ ( pen_y + y ) * i_pic_pitch + pen_x + x ]
-            for( y = 0; y < p_widget->i_height; y++ )
-            {
-                for( x = 0; x < p_widget->i_width; x++ )
-                {
-                    if( alpha == 0 ) continue;
-                    pen_y--;
-                    pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                    pen_y++; pen_x--;
-                    pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                    pen_x += 2;
-                    pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                    pen_y++; pen_x--;
-                    pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                    pen_y--;
-                }
-            }
-            for( y = 0; y < p_widget->i_height; y++ )
-            {
-                for( x = 0; x < p_widget->i_width; x++ )
-                {
-                    pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 ) +
-                            ( 255 * alpha >> 8 );
-                 }
-             }
-#undef alpha
-#undef pixel
-        }
-        else
-        {
-            pen_x = p_widget->i_x >> 1;
-            pen_y = p_widget->i_y >> 1;
-#define alpha p_widget->p_pic[ x + y * p_widget->i_width ] * i_fade_alpha
-#define pixel p_in[ ( pen_y + (y >> 1) ) * i_pic_pitch + pen_x + (x >> 1) ]
-            for( y = 0; y < p_widget->i_height; y+=2 )
-            {
-                for( x = 0; x < p_widget->i_width; x+=2 )
-                {
-                    if( alpha == 0 ) continue;
-                    pixel = ( ( pixel * ( 0xFF - alpha ) ) >> 8 ) +
-                        ( 0x80 * alpha >> 8 );
-                }
-            }
-#undef alpha
-#undef pixel
-        }
-    }
-
-}
-
-/**
- * Draw a widget on a YUY2 picture
- */
-static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_subpic, int i_fade_alpha )
+static void CreatePicture( spu_t *p_spu, subpicture_t *p_subpic,
+                           int i_x, int i_y, int i_width, int i_height )
 {
-    subpicture_sys_t *p_widget = p_subpic->p_sys;
-    int x, y, pen_x, pen_y;
-    uint8_t *p_in = p_pic->p[0].p_pixels;
-    int i_pic_pitch = p_pic->p[0].i_pitch;
-
-    pen_x = p_widget->i_x;
-    pen_y = p_widget->i_y;
-#define alpha p_widget->p_pic[ x + y * p_widget->i_width ] * i_fade_alpha
-#define pixel p_in[ ( pen_y + y ) * i_pic_pitch + 2 * ( pen_x + x ) ]
-    for( y = 0; y < p_widget->i_height; y++ )
+    uint8_t *p_y, *p_u, *p_v, *p_a;
+    video_format_t fmt;
+    int i_pitch;
+
+    /* Create a new subpicture region */
+    memset( &fmt, 0, sizeof(video_format_t) );
+    fmt.i_chroma = VLC_FOURCC('Y','U','V','A');
+    fmt.i_aspect = VOUT_ASPECT_FACTOR;
+    fmt.i_width = fmt.i_visible_width = i_width;
+    fmt.i_height = fmt.i_visible_height = i_height;
+    fmt.i_x_offset = fmt.i_y_offset = 0;
+    p_subpic->p_region = p_subpic->pf_create_region( VLC_OBJECT(p_spu), &fmt );
+    if( !p_subpic->p_region )
     {
-        for( x = 0; x < p_widget->i_width; x++ )
-        {
-            pen_y--;
-            pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-            pen_y++; pen_x--;
-            pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-            pen_x += 2;
-            pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-            pen_y++; pen_x--;
-            pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-            pen_y--;
-        }
+        msg_Err( p_spu, "cannot allocate SPU region" );
+        return;
     }
-    for( y = 0; y < p_widget->i_height; y++ )
-    {
-        for( x = 0; x < p_widget->i_width; x++ )
-        {
-            pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 ) +
-                    ( 255 * alpha >> 8 );
-         }
-     }
-#undef alpha
-#undef pixel
-}
-
-/**
- * Draw a widget on a RV32 picture
- */
-static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
-                    const subpicture_t *p_subpic, int i_fade_alpha )
-{
-    subpicture_sys_t *p_widget = p_subpic->p_sys;
-    int x, y, pen_x, pen_y;
-    uint8_t *p_in = p_pic->p[0].p_pixels;
-    int i_pic_pitch = p_pic->p[0].i_pitch;
-
-    pen_x = p_widget->i_x;
-    pen_y = p_widget->i_y;
 
-#define alpha p_widget->p_pic[ x + y * p_widget->i_width ] * i_fade_alpha
-#define pixel( c ) p_in[ ( pen_y + y ) * i_pic_pitch + 4 * ( pen_x + x ) + c ]
-    for(y = 0; y < p_widget->i_height; y++ )
-    {
-        for( x = 0; x < p_widget->i_width; x++ )
-        {
-            pen_y--;
-            pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 2 ) = ( ( pixel( 2 ) * ( 255 - alpha ) ) >> 8 );
-            pen_y++; pen_x--;
-            pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 2 ) = ( ( pixel( 2 ) * ( 255 - alpha ) ) >> 8 );
-            pen_x += 2;
-            pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 2 ) = ( ( pixel( 2 ) * ( 255 - alpha ) ) >> 8 );
-            pen_y++; pen_x--;
-            pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 );
-            pixel( 2 ) = ( ( pixel( 2 ) * ( 255 - alpha ) ) >> 8 );
-            pen_y--;
-        }
-    }
-    for(y = 0; y < p_widget->i_height; y++ )
-    {
-        for( x = 0; x < p_widget->i_width; x++ )
-        {
-            pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 ) +
-                ( 255 * alpha >> 8 );
-            pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 ) +
-                ( 255 * alpha >> 8 );
-            pixel( 2 ) = ( ( pixel( 2 ) * ( 255 - alpha ) ) >> 8 ) +
-                ( 255 * alpha >> 8 );
-        }
-    }
-#undef alpha
-#undef pixel
+    p_subpic->p_region->i_x = i_x;
+    p_subpic->p_region->i_y = i_y;
+    p_y = p_subpic->p_region->picture.Y_PIXELS;
+    p_u = p_subpic->p_region->picture.U_PIXELS;
+    p_v = p_subpic->p_region->picture.V_PIXELS;
+    p_a = p_subpic->p_region->picture.A_PIXELS;
+    i_pitch = p_subpic->p_region->picture.Y_PITCH;
+
+    /* Initialize the region pixels (only the alpha will be changed later) */
+    memset( p_y, 0xff, i_pitch * p_subpic->p_region->fmt.i_height );
+    memset( p_u, 0x80, i_pitch * p_subpic->p_region->fmt.i_height );
+    memset( p_v, 0x80, i_pitch * p_subpic->p_region->fmt.i_height );
+    memset( p_a, 0x00, i_pitch * p_subpic->p_region->fmt.i_height );
 }
 
 /*****************************************************************************
  * Creates and initializes an OSD widget.
  *****************************************************************************/
-subpicture_t *vout_CreateWidget( vout_thread_t *p_vout, int i_channel )
+subpicture_t *vout_CreateWidget( spu_t *p_spu, int i_channel )
 {
     subpicture_t *p_subpic;
-    subpicture_sys_t *p_widget;
     mtime_t i_now = mdate();
 
-    p_subpic = 0;
-    p_widget = 0;
-
     /* Create and initialize a subpicture */
-    p_subpic = spu_CreateSubpicture( p_vout->p_spu );
-    if( p_subpic == NULL )
-    {
-        return NULL;
-    }
+    p_subpic = spu_CreateSubpicture( p_spu );
+    if( p_subpic == NULL ) return NULL;
+
     p_subpic->i_channel = i_channel;
-    p_subpic->pf_render = Render;
-    p_subpic->pf_destroy = FreeWidget;
     p_subpic->i_start = i_now;
     p_subpic->i_stop = i_now + 1200000;
     p_subpic->b_ephemer = VLC_TRUE;
-
-    p_widget = malloc( sizeof(subpicture_sys_t) );
-    if( p_widget == NULL )
-    {
-        FreeWidget( p_subpic );
-        spu_DestroySubpicture( p_vout->p_spu, p_subpic );
-        return NULL;
-    }
-    p_subpic->p_sys = p_widget;
+    p_subpic->b_fade = VLC_TRUE;
 
     return p_subpic;
 }
@@ -416,70 +215,55 @@ void vout_OSDSlider( vlc_object_t *p_caller, int i_channel, int i_position,
     vout_thread_t *p_vout = vlc_object_find( p_caller, VLC_OBJECT_VOUT,
                                              FIND_ANYWHERE );
     subpicture_t *p_subpic;
-    subpicture_sys_t *p_widget;
-    int i_x_margin, i_y_margin;
+    int i_x_margin, i_y_margin, i_x, i_y, i_width, i_height;
 
     if( p_vout == NULL || !config_GetInt( p_caller, "osd" ) || i_position < 0 )
     {
         return;
     }
 
-    p_subpic = vout_CreateWidget( p_vout, i_channel );
+    p_subpic = vout_CreateWidget( p_vout->p_spu, i_channel );
     if( p_subpic == NULL )
     {
         return;
     }
-    p_widget = p_subpic->p_sys;
 
     i_y_margin = p_vout->render.i_height / 10;
     i_x_margin = i_y_margin;
     if( i_type == OSD_HOR_SLIDER )
     {
-        p_widget->i_width = p_vout->render.i_width - 2 * i_x_margin;
-        p_widget->i_height = p_vout->render.i_height / 20;
-        p_widget->i_x = i_x_margin;
-        p_widget->i_y = p_vout->render.i_height - i_y_margin -
-                        p_widget->i_height;
+        i_width = p_vout->render.i_width - 2 * i_x_margin;
+        i_height = p_vout->render.i_height / 20;
+        i_x = i_x_margin;
+        i_y = p_vout->render.i_height - i_y_margin - i_height;
     }
     else
     {
-        p_widget->i_width = p_vout->render.i_width / 40;
-        p_widget->i_height = p_vout->render.i_height - 2 * i_y_margin;
-        p_widget->i_x = p_vout->render.i_width - i_x_margin -
-                        p_widget->i_width;
-        p_widget->i_y = i_y_margin;
+        i_width = p_vout->render.i_width / 40;
+        i_height = p_vout->render.i_height - 2 * i_y_margin;
+        i_x = p_vout->render.i_width - i_x_margin - i_width;
+        i_y = i_y_margin;
     }
 
-    p_widget->p_pic = (uint8_t *)malloc( p_widget->i_width *
-                                         p_widget->i_height );
-    if( p_widget->p_pic == NULL )
-    {
-        FreeWidget( p_subpic );
-        spu_DestroySubpicture( p_vout->p_spu, p_subpic );
-        return;
-    }
-    memset( p_widget->p_pic, 0, p_widget->i_width * p_widget->i_height );
+    /* Create subpicture region and picture */
+    CreatePicture( p_vout->p_spu, p_subpic, i_x, i_y, i_width, i_height );
 
     if( i_type == OSD_HOR_SLIDER )
     {
-        int i_x_pos = ( p_widget->i_width - 2 ) * i_position / 100;
-        DrawRect( p_vout, p_subpic, i_x_pos - 1, 2, i_x_pos + 1,
-                  p_widget->i_height - 3, STYLE_FILLED );
-        DrawRect( p_vout, p_subpic, 0, 0, p_widget->i_width - 1,
-                  p_widget->i_height - 1, STYLE_EMPTY );
+        int i_x_pos = ( i_width - 2 ) * i_position / 100;
+        DrawRect( p_subpic, i_x_pos - 1, 2, i_x_pos + 1,
+                  i_height - 3, STYLE_FILLED );
+        DrawRect( p_subpic, 0, 0, i_width - 1, i_height - 1, STYLE_EMPTY );
     }
     else if( i_type == OSD_VERT_SLIDER )
     {
-        int i_y_pos = p_widget->i_height / 2;
-        DrawRect( p_vout, p_subpic, 2, p_widget->i_height -
-                  ( p_widget->i_height - 2 ) * i_position / 100,
-                  p_widget->i_width - 3, p_widget->i_height - 3,
-                  STYLE_FILLED );
-        DrawRect( p_vout, p_subpic, 1, i_y_pos, 1, i_y_pos, STYLE_FILLED );
-        DrawRect( p_vout, p_subpic, p_widget->i_width - 2, i_y_pos,
-                  p_widget->i_width - 2, i_y_pos, STYLE_FILLED );
-        DrawRect( p_vout, p_subpic, 0, 0, p_widget->i_width - 1,
-                  p_widget->i_height - 1, STYLE_EMPTY );
+        int i_y_pos = i_height / 2;
+        DrawRect( p_subpic, 2, i_height - ( i_height - 2 ) * i_position / 100,
+                  i_width - 3, i_height - 3, STYLE_FILLED );
+        DrawRect( p_subpic, 1, i_y_pos, 1, i_y_pos, STYLE_FILLED );
+        DrawRect( p_subpic, i_width - 2, i_y_pos,
+                  i_width - 2, i_y_pos, STYLE_FILLED );
+        DrawRect( p_subpic, 0, 0, i_width - 1, i_height - 1, STYLE_EMPTY );
     }
 
     spu_DisplaySubpicture( p_vout->p_spu, p_subpic );
@@ -497,72 +281,62 @@ void vout_OSDIcon( vlc_object_t *p_caller, int i_channel, short i_type )
     vout_thread_t *p_vout = vlc_object_find( p_caller, VLC_OBJECT_VOUT,
                                              FIND_ANYWHERE );
     subpicture_t *p_subpic;
-    subpicture_sys_t *p_widget;
-    int i_x_margin, i_y_margin;
+    int i_x_margin, i_y_margin, i_x, i_y, i_width, i_height;
 
     if( p_vout == NULL || !config_GetInt( p_caller, "osd" ) )
     {
         return;
     }
 
-    p_subpic = vout_CreateWidget( p_vout, i_channel );
+    p_subpic = vout_CreateWidget( p_vout->p_spu, i_channel );
     if( p_subpic == NULL )
     {
         return;
     }
-    p_widget = p_subpic->p_sys;
 
     i_y_margin = p_vout->render.i_height / 15;
     i_x_margin = i_y_margin;
-    p_widget->i_width = p_vout->render.i_width / 20;
-    p_widget->i_height = p_widget->i_width;
-    p_widget->i_x = p_vout->render.i_width - i_x_margin -
-                    p_widget->i_width;
-    p_widget->i_y = i_y_margin;
-
-    p_widget->p_pic = (uint8_t *)malloc( p_widget->i_width *
-                                         p_widget->i_height );
-    if( p_widget->p_pic == NULL )
-    {
-        FreeWidget( p_subpic );
-        spu_DestroySubpicture( p_vout->p_spu, p_subpic );
-        return;
-    }
-    memset( p_widget->p_pic, 0, p_widget->i_width * p_widget->i_height );
+    i_width = p_vout->render.i_width / 20;
+    i_height = i_width;
+    i_x = p_vout->render.i_width - i_x_margin - i_width;
+    i_y = i_y_margin;
+
+    /* Create subpicture region and picture */
+    CreatePicture( p_vout->p_spu, p_subpic, i_x, i_y, i_width, i_height );
 
     if( i_type == OSD_PAUSE_ICON )
     {
-        int i_bar_width = p_widget->i_width / 3;
-        DrawRect( p_vout, p_subpic, 0, 0, i_bar_width - 1,
-                  p_widget->i_height - 1, STYLE_FILLED );
-        DrawRect( p_vout, p_subpic, p_widget->i_width - i_bar_width, 0,
-                  p_widget->i_width - 1, p_widget->i_height - 1, STYLE_FILLED );
+        int i_bar_width = i_width / 3;
+        DrawRect( p_subpic, 0, 0, i_bar_width - 1, i_height -1, STYLE_FILLED );
+        DrawRect( p_subpic, i_width - i_bar_width, 0,
+                  i_width - 1, i_height - 1, STYLE_FILLED );
     }
     else if( i_type == OSD_PLAY_ICON )
     {
-        int i_mid = p_widget->i_height >> 1;
-        int i_delta = ( p_widget->i_width - i_mid ) >> 1;
-        int i_y2 = ( ( p_widget->i_height - 1 ) >> 1 ) * 2;
-        DrawTriangle( p_vout, p_subpic, i_delta, 0,
-                      p_widget->i_width - i_delta, i_y2, STYLE_FILLED );
+        int i_mid = i_height >> 1;
+        int i_delta = ( i_width - i_mid ) >> 1;
+        int i_y2 = ( ( i_height - 1 ) >> 1 ) * 2;
+        DrawTriangle( p_subpic, i_delta, 0, i_width - i_delta, i_y2,
+                      STYLE_FILLED );
     }
     else if( i_type == OSD_SPEAKER_ICON || i_type == OSD_MUTE_ICON )
     {
-        int i_mid = p_widget->i_height >> 1;
-        int i_delta = ( p_widget->i_width - i_mid ) >> 1;
-        int i_y2 = ( ( p_widget->i_height - 1 ) >> 1 ) * 2;
-        DrawRect( p_vout, p_subpic, i_delta, i_mid / 2,
-                  p_widget->i_width - i_delta,
-                  p_widget->i_height - 1 - i_mid / 2, STYLE_FILLED );
-        DrawTriangle( p_vout, p_subpic, p_widget->i_width - i_delta, 0,
-                      i_delta, i_y2, STYLE_FILLED );
+        int i_mid = i_height >> 1;
+        int i_delta = ( i_width - i_mid ) >> 1;
+        int i_y2 = ( ( i_height - 1 ) >> 1 ) * 2;
+        DrawRect( p_subpic, i_delta, i_mid / 2, i_width - i_delta,
+                  i_height - 1 - i_mid / 2, STYLE_FILLED );
+        DrawTriangle( p_subpic, i_width - i_delta, 0, i_delta, i_y2,
+                      STYLE_FILLED );
         if( i_type == OSD_MUTE_ICON )
         {
+            uint8_t *p_a = p_subpic->p_region->picture.A_PIXELS;
+            int i_pitch = p_subpic->p_region->picture.Y_PITCH;
             int i;
-            for( i = 1; i < p_widget->i_width; i++ )
+            for( i = 1; i < i_pitch; i++ )
             {
-                int k = i + ( p_widget->i_height - i - 1 ) * p_widget->i_width;
-                p_widget->p_pic[ k ] = 1 - p_widget->p_pic[ k ];
+                int k = i + ( i_height - i - 1 ) * i_pitch;
+                p_a[ k ] = 0xff - p_a[ k ];
             }
         }
     }
@@ -572,19 +346,3 @@ void vout_OSDIcon( vlc_object_t *p_caller, int i_channel, short i_type )
     vlc_object_release( p_vout );
     return;
 }
-
-/**
- * Frees the widget.
- */
-static void FreeWidget( subpicture_t *p_subpic )
-{
-    subpicture_sys_t *p_widget = p_subpic->p_sys;
-
-    if( p_subpic->p_sys == NULL ) return;
-
-    if( p_widget->p_pic != NULL )
-    {
-        free( p_widget->p_pic );
-    }
-    free( p_widget );
-}
index d8ea373375dff850fb7050b142e098fe3171f752..31fe32772c6ff5e1344da9f733eea7aebc214590 100644 (file)
@@ -372,6 +372,7 @@ subpicture_t *spu_CreateSubpicture( spu_t *p_spu )
     memset( p_subpic, 0, sizeof(subpicture_t) );
     p_subpic->i_status   = RESERVED_SUBPICTURE;
     p_subpic->b_absolute = VLC_TRUE;
+    p_subpic->b_fade     = VLC_FALSE;
     p_subpic->pf_render  = 0;
     p_subpic->pf_destroy = 0;
     p_subpic->p_sys      = 0;
@@ -538,6 +539,7 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt,
         else while( p_region && p_spu->p_blend &&
                     p_spu->p_blend->pf_video_blend )
         {
+            int i_fade_alpha = 255;
             int i_x_offset = p_region->i_x + p_subpic->i_x;
             int i_y_offset = p_region->i_y + p_subpic->i_y;
 
@@ -733,8 +735,21 @@ void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt,
                 p_spu->p_blend->fmt_out.video.i_visible_height =
                     p_fmt->i_height;
 
-           p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst,
-                p_pic_src, &p_region->picture, i_x_offset, i_y_offset, 255 );
+            if( p_subpic->b_fade )
+            {
+                mtime_t i_fade_start = ( p_subpic->i_stop +
+                                         p_subpic->i_start ) / 2;
+                mtime_t i_now = mdate();
+                if( i_now >= i_fade_start && p_subpic->i_stop > i_fade_start )
+                {
+                    i_fade_alpha = 255 * ( p_subpic->i_stop - i_now ) /
+                                   ( p_subpic->i_stop - i_fade_start );
+                }
+            }
+
+            p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst,
+                p_pic_src, &p_region->picture, i_x_offset, i_y_offset,
+                i_fade_alpha );
 
             p_region = p_region->p_next;
         }