]> git.sesse.net Git - vlc/commitdiff
* Fixed an aspect ratio issue in the SPU decoder, and optimized the
authorSam Hocevar <sam@videolan.org>
Tue, 8 May 2001 20:38:25 +0000 (20:38 +0000)
committerSam Hocevar <sam@videolan.org>
Tue, 8 May 2001 20:38:25 +0000 (20:38 +0000)
    SPU renderer.

ChangeLog
src/spu_decoder/spu_decoder.c
src/video_output/video_output.c
src/video_output/video_spu.c
src/video_output/video_spu.h
src/video_parser/video_fifo.c

index ed10914de4f3475897f88dfb93ed88a786c97afa..f40bc557e2e01e7078462e7dd3a27b1093430b22 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,8 @@
 #===================#
 
 HEAD
+  * Fixed an aspect ratio issue in the SPU decoder, and optimized the
+    SPU renderer.
   * Speed optimization in the handling of the unusual ephemer DVD subtitles.
   * Little optimization to bozo's UnalignedShowBits fix.
   * Race fix in the packet cache by Jon Lech Johansen <jon-vl@nanocrew.net>.
index 9e2faf4a23ecf87e8ac103ab46cbc65da9e8c9db..95dee601dc2edaeb28c745ee6434e42576ef213c 100644 (file)
@@ -2,7 +2,7 @@
  * spu_decoder.c : spu decoder thread
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
- * $Id: spu_decoder.c,v 1.42 2001/05/07 04:42:42 sam Exp $
+ * $Id: spu_decoder.c,v 1.43 2001/05/08 20:38:25 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -504,17 +504,16 @@ static int ParseControlSequences( spudec_thread_t *p_spudec,
     /* Get rid of padding bytes */
     switch( p_spudec->i_spu_size - i_index )
     {
+        /* Zero or one padding byte, quite usual */
         case 1:
             RemoveBits( &p_spudec->bit_stream, 8 );
             i_index++;
         case 0:
-            /* Zero or one padding byte, quite usual */
             break;
 
+        /* More than one padding byte - this is very strange, but
+         * we can deal with it */
         default:
-
-            /* More than one padding byte - this is very strange, but
-             * we can deal with it */
             intf_WarnMsg( 2, "spudec warning: %i padding bytes, we usually "
                              "get 1 or none",
                           p_spudec->i_spu_size - i_index );
@@ -542,7 +541,6 @@ static int ParseControlSequences( spudec_thread_t *p_spudec,
 static int ParseRLE( u8 *p_src, subpicture_t * p_spu )
 {
     unsigned int i_code;
-    unsigned int i_id = 0;
 
     unsigned int i_width = p_spu->i_width;
     unsigned int i_height = p_spu->i_height;
@@ -551,6 +549,7 @@ static int ParseRLE( u8 *p_src, subpicture_t * p_spu )
     u16 *p_dest = (u16 *)p_spu->p_data;
 
     /* The subtitles are interlaced, we need two offsets */
+    unsigned int  i_id = 0;                   /* Start on the even SPU layer */
     unsigned int  pi_table[ 2 ];
     unsigned int *pi_offset;
 
index 7010f3dd1d6827232a1d91ebb66f9b7774816f8a..7abe3ab4da080b51bec67b2ac5b548d21d0fa9bd 100644 (file)
@@ -5,7 +5,7 @@
  * thread, and destroy a previously oppened video output thread.
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
- * $Id: video_output.c,v 1.127 2001/05/08 00:43:57 sam Exp $
+ * $Id: video_output.c,v 1.128 2001/05/08 20:38:25 sam Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -72,11 +72,9 @@ static void     SetBufferArea     ( vout_thread_t *p_vout, int i_x, int i_y,
 static void     SetBufferPicture  ( vout_thread_t *p_vout, picture_t *p_pic );
 static void     RenderPicture     ( vout_thread_t *p_vout, picture_t *p_pic );
 static void     RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic );
-static void     RenderSubPicture  ( vout_thread_t *p_vout,
+static void     RenderSubPicture  ( vout_thread_t *p_vout, picture_t *p_pic,
                                     subpicture_t *p_subpic );
-static void     RenderInterface   ( vout_thread_t *p_vout );
 static int      RenderIdle        ( vout_thread_t *p_vout );
-static int      RenderSplash      ( vout_thread_t *p_vout );
 static void     RenderInfo        ( vout_thread_t *p_vout );
 static int      Manage            ( vout_thread_t *p_vout );
 static int      Align             ( vout_thread_t *p_vout, int *pi_x,
@@ -1198,18 +1196,14 @@ static void RunThread( vout_thread_t *p_vout)
                     RenderPictureInfo( p_vout, p_pic );
                     RenderInfo( p_vout );
                 }
+            }
+            if( b_display ) /* XXX: quick HACK */
+            {
                 if( p_subpic )
                 {
-                    RenderSubPicture( p_vout, p_subpic );
+                    RenderSubPicture( p_vout, p_pic, p_subpic );
                 }
             }
-
-            /* Render interface and subpicture */
-            if( b_display && p_vout->b_interface && p_vout->b_need_render )
-            {
-                RenderInterface( p_vout );
-            }
-
         }
         else if( p_vout->b_active && p_vout->b_need_render
                   && p_vout->init_display_date == 0)
@@ -1229,10 +1223,6 @@ static void RunThread( vout_thread_t *p_vout)
             if( b_display )
             {
                 p_vout->last_idle_date = current_date;
-                if( p_vout->b_interface )
-                {
-                    RenderInterface( p_vout );
-                }
             }
 
         }
@@ -1248,17 +1238,7 @@ static void RunThread( vout_thread_t *p_vout)
          */
         if( p_vout->init_display_date > 0 && p_vout->b_need_render )
         {
-            if( p_vout->b_active &&
-                    mdate()-p_vout->init_display_date < 5000000)
-            {
-                /* there is something to display ! */
-                    b_display = 1;
-                    RenderSplash( p_vout );
-
-            } else {
-                /* no splash screen ! */
-                p_vout->init_display_date=0;
-            }
+            p_vout->init_display_date = 0;
         }
 
 
@@ -1895,42 +1875,6 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic )
 #endif
 }
 
-/*****************************************************************************
- * RenderSplash: render splash picture
- *****************************************************************************
- * This function will print something on the screen. It will return 0 if
- * nothing has been rendered, or 1 if something has been changed on the screen.
- * Note that if you absolutely want something to be printed, you will have
- * to force it by setting the last idle date to 0.
- * Unlike other rendering functions, this one calls the SetBufferPicture
- * function when needed.
- *****************************************************************************/
-int RenderSplash( vout_thread_t *p_vout )
-{
-    int         i_x = 0, i_y = 0;                           /* text position */
-    int         i_width, i_height;                              /* text size */
-    char *psz_text =    "VideoLAN Client (" VERSION ")";  /* text to display */
-
-    memset( p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
-                  p_vout->i_bytes_per_line * p_vout->i_height, 12);
-
- //   SetBufferPicture( p_vout, NULL );
-    vout_TextSize( p_vout->p_large_font, WIDE_TEXT | OUTLINED_TEXT, psz_text,
-                   &i_width, &i_height );
-    if( !Align( p_vout, &i_x, &i_y, i_width, i_height, CENTER_RALIGN, CENTER_RALIGN ) )
-    {
-        vout_Print( p_vout->p_large_font,
-                    p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
-                    i_x * p_vout->i_bytes_per_pixel + (i_y - 16 ) * p_vout->i_bytes_per_line,
-                    p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
-                    p_vout->i_white_pixel, p_vout->i_gray_pixel, 0,
-                    WIDE_TEXT | OUTLINED_TEXT, psz_text, 100);
-        SetBufferArea( p_vout, i_x, i_y, i_width, i_height);
-    }
-    return( 1 );
-}
-
-
 /*****************************************************************************
  * RenderIdle: render idle picture
  *****************************************************************************
@@ -2037,7 +1981,8 @@ static void RenderInfo( vout_thread_t *p_vout )
  *****************************************************************************
  * This function renders a sub picture unit.
  *****************************************************************************/
-static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
+static void RenderSubPicture( vout_thread_t *p_vout, picture_t *p_pic,
+                              subpicture_t *p_subpic )
 {
     p_vout_font_t       p_font;                                 /* text font */
     int                 i_width, i_height;          /* subpicture dimensions */
@@ -2047,9 +1992,11 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
         switch( p_subpic->i_type )
         {
         case DVD_SUBPICTURE:                          /* DVD subpicture unit */
-            vout_RenderSPU( &p_vout->p_buffer[ p_vout->i_buffer_index ],
-                            p_subpic, p_vout->i_bytes_per_pixel,
-                            p_vout->i_bytes_per_line );
+            vout_RenderRGBSPU( p_pic, p_subpic,
+                               &p_vout->p_buffer[ p_vout->i_buffer_index ],
+                               p_vout->i_bytes_per_pixel,
+                               p_vout->i_bytes_per_line );
+            /* vout_RenderYUVSPU( p_pic, p_subpic ); */
             break;
 
         case TEXT_SUBPICTURE:                            /* single line text */
@@ -2094,55 +2041,6 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
     }
 }
 
-/*****************************************************************************
- * RenderInterface: render the interface
- *****************************************************************************
- * This function renders the interface, if any.
- *****************************************************************************/
-static void RenderInterface( vout_thread_t *p_vout )
-{
-    int         i_height, i_text_height;            /* total and text height */
-    int         i_width_1, i_width_2;                          /* text width */
-    int         i_byte;                                        /* byte index */
-    const char *psz_text_1 = "[1-9] Channel   [i]nfo   [c]olor     [g/G]amma";
-    const char *psz_text_2 = "[+/-] Volume    [m]ute   [s]caling   [Q]uit";
-
-    /* Get text size */
-    vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_1, &i_width_1, &i_height );
-    vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_2, &i_width_2, &i_text_height );
-    i_height += i_text_height;
-
-    /* Render background */
-    for( i_byte = (p_vout->i_height - i_height) * p_vout->i_bytes_per_line;
-         i_byte < p_vout->i_height * p_vout->i_bytes_per_line;
-         i_byte++ )
-    {
-        /* XXX?? noooo ! */
-        p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = p_vout->i_blue_pixel;
-    }
-
-    /* Render text, if not larger than screen */
-    if( i_width_1 < p_vout->i_width )
-    {
-        vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
-                    (p_vout->i_height - i_height) * p_vout->i_bytes_per_line,
-                    p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
-                    p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
-                    OUTLINED_TEXT, psz_text_1, 100 );
-    }
-    if( i_width_2 < p_vout->i_width )
-    {
-        vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
-                    (p_vout->i_height - i_height + i_text_height) * p_vout->i_bytes_per_line,
-                    p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
-                    p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
-                    OUTLINED_TEXT, psz_text_2, 100 );
-    }
-
-    /* Activate modified area */
-    SetBufferArea( p_vout, 0, p_vout->i_height - i_height, p_vout->i_width, i_height );
-}
-
 /*****************************************************************************
  * Manage: manage thread
  *****************************************************************************
index 52cb742d09f445dcb3391040dacbf9f01e1067de..d21dcadf3debaecc9557cbc64976104d3f9ad3d0 100644 (file)
@@ -2,7 +2,7 @@
  * video_spu.c : DVD subpicture units functions
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_spu.c,v 1.20 2001/04/06 09:15:48 sam Exp $
+ * $Id: video_spu.c,v 1.21 2001/05/08 20:38:25 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  * 
 static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x8888 };
 
 /*****************************************************************************
- * vout_RenderSPU: draw an SPU on a picture
+ * vout_RenderRGBSPU: draw an SPU on a picture
  *****************************************************************************
  * This is a fast implementation of the subpicture drawing code. The data
  * has been preprocessed once in spu_decoder.c, so we don't need to parse the
  * RLE buffer again and again. Most sanity checks are done in spu_decoder.c
  * so that this routine can be as fast as possible.
  *****************************************************************************/
-void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
-                     int i_bytes_per_pixel, int i_bytes_per_line )
+void   vout_RenderRGBSPU( picture_t *p_pic, const subpicture_t *p_spu,
+                          vout_buffer_t *p_buffer,
+                          int i_bytes_per_pixel, int i_bytes_per_line )
 {
     int  i_len, i_color;
     u16 *p_source = (u16 *)p_spu->p_data;
 
-    /* FIXME: we need a way to get 720 and 576 from the stream */
-    int i_xscale = ( p_buffer->i_pic_width << 6 ) / 720;
-    int i_yscale = ( p_buffer->i_pic_height << 6 ) / 576;
+    int i_xscale = ( p_buffer->i_pic_width << 6 ) / p_pic->i_width;
+    int i_yscale = ( p_buffer->i_pic_height << 6 ) / p_pic->i_height;
 
     int i_width  = p_spu->i_width  * i_xscale;
     int i_height = p_spu->i_height * i_yscale;
 
-    int i_x = 0, i_y = 0, i_ytmp, i_yreal, i_ynext;
+    int i_x, i_y, i_ytmp, i_yreal, i_ynext;
 
-    u8 *p_dest = p_buffer->p_data
+    u8 *p_dest = p_buffer->p_data + ( i_width >> 6 ) * i_bytes_per_pixel
                   /* Add the picture coordinates and the SPU coordinates */
                   + ( p_buffer->i_pic_x + ((p_spu->i_x * i_xscale) >> 6))
                        * i_bytes_per_pixel
@@ -72,7 +72,9 @@ void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
                        * i_bytes_per_line;
 
     /* Draw until we reach the bottom of the subtitle */
-    for( i_y = 0 ; i_y < i_height ; /* i_y incremented below */ )
+    i_y = 0;
+
+    while( i_y < i_height )
     {
         i_ytmp = i_y >> 6;
         i_y += i_yscale;
@@ -84,20 +86,28 @@ void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
             i_yreal = i_bytes_per_line * i_ytmp;
 
             /* Draw until we reach the end of the line */
-            for( i_x = 0 ; i_x < i_width ; i_x += i_len )
+           i_x = i_width;
+
+            while( i_x )
             {
-                /* Get RLE information */
-                i_len = i_xscale * ( *p_source >> 2 );
-                i_color = *p_source++ & 0x3;
+                /* Get the RLE part */
+                i_color = *p_source & 0x3;
 
                 /* Draw the line */
                 if( i_color )
                 {
-                    memset( p_dest + i_bytes_per_pixel * ( i_x >> 6 )
+                    i_len = i_xscale * ( *p_source++ >> 2 );
+
+                    memset( p_dest - i_bytes_per_pixel * ( i_x >> 6 )
                                    + i_yreal,
                             p_palette[ i_color ],
                             i_bytes_per_pixel * ( ( i_len >> 6 ) + 1 ) );
+
+                    i_x -= i_len;
+                    continue;
                 }
+
+                i_x -= i_xscale * ( *p_source++ >> 2 );
             }
         }
         else
@@ -106,27 +116,81 @@ void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
             i_ynext = i_bytes_per_line * i_y >> 6;
 
             /* Draw until we reach the end of the line */
-            for( i_x = 0 ; i_x < i_width ; i_x += i_len )
+            i_x = i_width;
+
+            while( i_x )
             {
-                /* Get RLE information */
-                i_len = i_xscale * ( *p_source >> 2 );
-                i_color = *p_source++ & 0x3;
+                /* Get the RLE part */
+                i_color = *p_source & 0x3;
 
                 /* Draw as many lines as needed */
                 if( i_color )
                 {
+                    i_len = i_xscale * ( *p_source++ >> 2 );
+
                     for( i_ytmp = i_yreal ;
                          i_ytmp < i_ynext ;
                          i_ytmp += i_bytes_per_line )
                     {
-                        memset( p_dest + i_bytes_per_pixel * ( i_x >> 6 )
+                        memset( p_dest - i_bytes_per_pixel * ( i_x >> 6 )
                                        + i_ytmp,
                                 p_palette[ i_color ],
                                 i_bytes_per_pixel * ( ( i_len >> 6 ) + 1 ) );
                     }
+
+                    i_x -= i_len;
+                    continue;
                 }
+
+                i_x -= i_xscale * ( *p_source++ >> 2 );
+            }
+        }
+    }
+}
+
+/*****************************************************************************
+ * vout_RenderYUVSPU: draw an SPU on an YUV overlay
+ *****************************************************************************
+ * This is a fast implementation of the subpicture drawing code. The data
+ * has been preprocessed once in spu_decoder.c, so we don't need to parse the
+ * RLE buffer again and again. Most sanity checks are done in spu_decoder.c
+ * so that this routine can be as fast as possible.
+ *****************************************************************************/
+void vout_RenderYUVSPU( picture_t *p_pic, const subpicture_t *p_spu )
+{
+    int  i_len, i_color;
+    u16 *p_source = (u16 *)p_spu->p_data;
+
+    int i_x, i_y;
+
+    u8 *p_dest = p_pic->p_y + p_spu->i_x + p_spu->i_width
+                        + p_pic->i_width * ( p_spu->i_y + p_spu->i_height );
+
+    /* Draw until we reach the bottom of the subtitle */
+    i_y = p_spu->i_height * p_pic->i_width;
+
+    while( i_y )
+    {
+        /* Draw until we reach the end of the line */
+        i_x = p_spu->i_width;
+
+        while( i_x )
+        {
+            /* Draw the line if needed */
+            i_color = *p_source & 0x3;
+
+            if( i_color )
+            {
+                i_len = *p_source++ >> 2;
+                memset( p_dest - i_x - i_y, p_palette[ i_color ], i_len );
+                i_x -= i_len;
+                continue;
             }
+
+            i_x -= *p_source++ >> 2;
         }
+
+        i_y -= p_pic->i_width;
     }
 }
 
index 19e81c5d2f6754d6804918e0fba61f7891a8895a..6823a526b1db03c749aee05e6cf7da5612aed44d 100644 (file)
@@ -2,7 +2,7 @@
  * video_spu.h : DVD subpicture units functions
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_spu.h,v 1.8 2001/03/21 13:42:35 sam Exp $
+ * $Id: video_spu.h,v 1.9 2001/05/08 20:38:25 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Henri Fallon <henri@via.ecp.fr>
@@ -25,6 +25,8 @@
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-void   vout_RenderSPU ( vout_buffer_t *p_buffer, subpicture_t *p_subpic,
-                        int i_bytes_per_pixel, int i_bytes_per_line );
+void   vout_RenderRGBSPU( picture_t *p_pic, const subpicture_t *p_spu,
+                          vout_buffer_t *p_buffer,
+                          int i_bytes_per_pixel, int i_bytes_per_line );
+void   vout_RenderYUVSPU( picture_t *p_pic, const subpicture_t *p_spu );
 
index d93c64adf709aad4f71a6ea242171986ddc26123..eb5aee930de75cc7e523b52d0272e693eccef9c8 100644 (file)
@@ -2,7 +2,7 @@
  * video_fifo.c : video FIFO management
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: video_fifo.c,v 1.31 2001/05/06 04:32:02 sam Exp $
+ * $Id: video_fifo.c,v 1.32 2001/05/08 20:38:25 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -80,3 +80,4 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
     }
 #endif
 }
+