]> git.sesse.net Git - vlc/commitdiff
NEWS:
authorSam Hocevar <sam@videolan.org>
Tue, 21 Mar 2000 22:36:01 +0000 (22:36 +0000)
committerSam Hocevar <sam@videolan.org>
Tue, 21 Mar 2000 22:36:01 +0000 (22:36 +0000)
 . encore un peu de parsage de sous-titres
 . affichage des sous-titres.

BUGS:
 . �a segfaulte toujours au moment o� on quitte, mais c'est le probl�me
  habituel, �a sera r�gl�.
 . pour le moment ils sont en noir et blanc, parce qu'il faut aller
  chercher cette putain de palette dans les .IFO du dvd et que pour
  l'instant j'ai la flemme
 . les sous-titres ne sont pas affich�s comme il faut si la largeur
  de l'�cran n'est pas 720.
 . dimensions par d�faut mises � 720x576 (format DVD) au lieu de 640x480
  pour la raison �voqu�e ci-dessus. mais �a sera r�gl� bient�t.
 . pas de gestion de transparence, coordonn�es, fade in/fade out
 . pas de gestion de date : le sous-titre est affich� d�s qu'il est re�u
  et n'est pas effac� tant qu'on en a pas re�u un nouveau.

Makefile.in
include/config.h.in
include/video.h
include/video_output.h
src/input/input.c
src/spu_decoder/spu_decoder.c
src/video_output/video_output.c
src/video_output/video_spu.c [new file with mode: 0644]
src/video_output/video_spu.h [new file with mode: 0644]

index eec760652d26dea35bfbe50a204bf2b95da8b719..3b9a0444112644e9aedb72e408c9188829999c86 100644 (file)
@@ -222,6 +222,7 @@ audio_output_obj =          audio_output/audio_output.o
 
 video_output_obj =             video_output/video_output.o \
                                                video_output/video_text.o \
+                                               video_output/video_spu.o \
                                                video_output/video_yuv.o
 
 ac3_decoder_obj =              ac3_decoder/ac3_decoder_thread.o \
index f7c6fd4881f887459458db4bbc0e95c81a75a870..8779a34fcf11ed78079de978b4dec24c78c99855 100644 (file)
  * Decoders FIFO configuration
  */
 
-/* Size of the FIFO. FIFO_SIZE+1 must be a multiple of 2 */
+/* Size of the FIFO. FIFO_SIZE+1 must be a power of 2 */
 #define FIFO_SIZE                       1023
 
 
  * standard width and height broadcasted MPEG-2 streams */
 #define VOUT_WIDTH_VAR                  "vlc_width"
 #define VOUT_HEIGHT_VAR                 "vlc_height"
-#define VOUT_WIDTH_DEFAULT              640
-#define VOUT_HEIGHT_DEFAULT             480
+#define VOUT_WIDTH_DEFAULT              720
+#define VOUT_HEIGHT_DEFAULT             576
 
 /* Maximum width of a scaled source picture - this should be relatively high,
  * since higher stream values will result in no display at all. */
index f2355e2da8639fbb4208c8c95cf788a8209e26ab..941b1ee3585b482b420b8715eda4dd4e244d1ee5 100644 (file)
@@ -147,6 +147,11 @@ typedef struct subpicture_s
             u32                 i_border_color;              /* border color */
             u32                 i_bg_color;              /* background color */
         } text;
+        /* DVD subpicture units properties */
+        struct
+        {
+            int                 i_offset[2];         /* byte offsets to data */
+        } spu;
     } type;
 
     /* Subpicture data, format depends of type - data can always be freely
index ce917e0c71e405680bc5a71c1c43838e80081024..63b7a326f8056ad72cd5f1f21a4cdef6a285f06e 100644 (file)
@@ -57,7 +57,7 @@ typedef struct vout_yuv_s
     vout_yuv_convert_t *        p_Convert422;         /* YUV 4:2:2 converter */
     vout_yuv_convert_t *        p_Convert444;         /* YUV 4:4:4 converter */
 
-    /* Pre-calculated convertion tables */
+    /* Pre-calculated conversion tables */
     void *              p_base;            /* base for all conversion tables */
     union
     {
@@ -69,7 +69,7 @@ typedef struct vout_yuv_s
         u32 *           p_rgb32;                        /* RGB 32 bits table */
     } yuv;
 
-    /* Temporary convertion buffer and offset array */
+    /* Temporary conversion buffer and offset array */
     void *              p_buffer;                       /* convertion buffer */
     int *               p_offset;                            /* offset array */
 } vout_yuv_t;
index 191a83d19c1da505beaf56a33574f8ed69e59565..4f82827d1e9a641daa12c0bf4122d24c4716dab3 100644 (file)
@@ -1226,8 +1226,9 @@ static __inline__ void input_ParsePES( input_thread_t *p_input,
                 break;
 
             case DVD_SPU_ES:
-                /* we skip 4 bytes at the beginning of the subpicture payload */
-                //p_ts->i_payload_start += 4;
+                /* we skip the first byte at the beginning of the
+                 * subpicture payload, it only contains the SPU ID. */
+                p_ts->i_payload_start++;
                 p_fifo = &(((spudec_thread_t *)(p_es_descriptor->p_dec))->fifo);
                 break;
 
index 64cb436b5c34ad0bfe9367483d61d6145d574f1a..c99aa4ecdddb9ec290c20b246c6c769e60c6a272 100644 (file)
@@ -202,141 +202,143 @@ static void RunThread( spudec_thread_t *p_spudec )
      */
     while( (!p_spudec->b_die) && (!p_spudec->b_error) )
     {
-        int i_spu_id;
         int i_packet_size;
         int i_rle_size;
         int i_index;
-       int i_pes_size;
-       boolean_t       b_finished;
+        int i_pes_size;
+        int i_pes_count;
+        boolean_t       b_finished;
         unsigned char * p_spu_data;
-        subpicture_t  * p_spu;
+        subpicture_t  * p_spu = NULL;
 
         while( !DECODER_FIFO_ISEMPTY(p_spudec->fifo) )
         {
-            printf( "*** tracking next SPU PES\n" );
+            /* wait for the next SPU ID.
+             * FIXME: We trash 0xff bytes since they come from
+             * an incomplete previous packet */
             do
             {
-                i_spu_id = GetByte( &p_spudec->bit_stream );
+                i_packet_size = GetByte( &p_spudec->bit_stream );
             }
-            while( (i_spu_id & 0xe0) != 0x20 );
-            i_pes_size = DECODER_FIFO_START(p_spudec->fifo)->i_pes_size;
-            printf( "got it. size = 0x%.4x\n", i_pes_size );
+            while( i_packet_size == 0xff );
 
-            printf( "SPU id: 0x%.2x\n", i_spu_id );
+            /* the total size - should equal the sum of the
+             * PES packet size that form the SPU packet */
+            i_packet_size = ( i_packet_size << 8 )
+                            + GetByte( &p_spudec->bit_stream );
+            i_index = 2;
 
-            i_index = 0;
-
-            GetWord( i_packet_size );
-            printf( "total size:  0x%.4x\n", i_packet_size );
+            /* get the useful PES size (real size - 10) */
+            i_pes_size = DECODER_FIFO_START(p_spudec->fifo)->i_pes_size - 9;
+            i_pes_count = 1;
 
+            /* the RLE stuff size */
             GetWord( i_rle_size );
-            printf( "RLE size:    0x%.4x\n", i_rle_size );
 
-            /* we already read 4 bytes for the total size and the RLE size */
+            /* if the values we got aren't too strange, decode the data */
+            if( i_rle_size < i_packet_size )
+            {
+                /* destroy the previous one */
+                if( p_spu ) vout_DestroySubPicture( p_spudec->p_vout, p_spu );
 
-            p_spu = vout_CreateSubPicture( p_spudec->p_vout,
+                /* allocate the subpicture.
+                 * FIXME: we should check if the allocation failed */
+                p_spu = vout_CreateSubPicture( p_spudec->p_vout,
                                            DVD_SUBPICTURE, i_rle_size );
-            p_spu_data = p_spu->p_data;
+                p_spu_data = p_spu->p_data;
 
-            if( (i_rle_size < i_packet_size)
-                && ((i_spu_id & 0xe0) == 0x20) )
-            {
-                printf( "doing RLE stuff (%i bytes)\n", i_rle_size );
-               printf( "index/size %i/%i\n", i_index, i_pes_size );
-                while( i_index++ <i_rle_size )
+                /* getting the RLE part */
+                while( i_index++ < i_rle_size )
                 {
-                    //*p_spu_data++ = GetByte( &p_spudec->bit_stream );
-                    if (i_index == i_pes_size) printf ("\n **** \n");
-                   /* kludge ??? */
-                    if (i_index == i_pes_size) printf( "%.2x", *p_spu_data++ = GetByte( &p_spudec->bit_stream ) );
-                    printf( "%.2x", *p_spu_data++ = GetByte( &p_spudec->bit_stream ) );
+                    /* skip the leading byte of a PES */
+                    if ( !((i_index + 3) % i_pes_size) )
+                    {
+                        i_pes_count++;
+                    }
+                    *p_spu_data++ = GetByte( &p_spudec->bit_stream );
                 }
-               printf( "\nindex/size %i/%i\n", i_index, i_pes_size );
-                //printf( "\n" );
 
-               b_finished = 0;
-                printf( "control stuff\n" );
-               do
+                /* getting the control part */
+                b_finished = 0;
+                do
                 {
                     unsigned char i_cmd;
                     unsigned int i_word;
 
+                    /* the date */
                     GetWord( i_word );
-                    printf( "date: 0x%.4x\n", i_word );
 
+                    /* next offset, no next offset if == i_index-5 */
                     GetWord( i_word );
-                    printf( "  next: 0x%.4x (i-5: %.4x)\n", i_word, i_index-5 );
-                   b_finished = (i_index - 5 >= i_word );
+                    b_finished = ( i_index - 5 >= i_word );
 
-                   do
-                   {
+                    do
+                    {
                         i_cmd = GetByte( &p_spudec->bit_stream );
-                       i_index++;
+                        i_index++;
 
-                       switch(i_cmd)
-                       {
+                        switch( i_cmd )
+                        {
                             case 0x00:
-                                printf( "  00 (display now)\n" );
+                                /* 00 (display now) */
                                 break;
                             case 0x01:
-                                printf( "  01 (start displaying)\n" );
+                                /* 01 (start displaying) */
                                 break;
                             case 0x02:
-                                printf( "  02 (stop displaying)\n" );
+                                /* 02 (stop displaying) */
                                 break;
                             case 0x03:
-                               GetWord( i_word );
-                                printf( "  03 (palette) - %.4x\n", i_word );
+                                /* 03xxxx (palette) */
+                                GetWord( i_word );
                                 break;
                             case 0x04:
-                               GetWord( i_word );
-                                printf( "  04 (alpha channel) - %.4x\n", i_word );
+                                /* 04xxxx (alpha channel) */
+                                GetWord( i_word );
                                 break;
                             case 0x05:
-                               GetWord( i_word );
-                                printf( "  05 (coordinates) - %.4x", i_word );
-                               GetWord( i_word );
-                                printf( "%.4x", i_word );
-                               GetWord( i_word );
-                                printf( "%.4x\n", i_word );
+                                /* 05xxxyyyxxxyyy (coordinates) */
+                                GetWord( i_word );
+                                GetWord( i_word );
+                                GetWord( i_word );
                                 break;
                             case 0x06:
-                               GetWord( i_word );
-                                printf( "  06 (byte offsets) - %.4x", i_word );
-                               GetWord( i_word );
-                                printf( "%.4x\n", i_word );
+                                /* 06xxxxyyyy (byte offsets) */
+                                GetWord( i_word );
+                                p_spu->type.spu.i_offset[0] = i_word - 4;
+                                GetWord( i_word );
+                                p_spu->type.spu.i_offset[1] = i_word - 4;
                                 break;
                             case 0xff:
-                                printf( "  ff (end)\n" );
+                                /* ff (end) */
                                 break;
-                           default:
-                                printf( "  %.2x (unknown command)\n", i_cmd );
+                            default:
+                                /* ?? (unknown command) */
                                 break;
-                       }
-
-                   }
-                   while( i_cmd != 0xff );
+                        }
+                    }
+                    while( i_cmd != 0xff );
+                }
+                while( !b_finished );
 
-               }
-               while( !b_finished );
-                printf( "control stuff finished\n" );
-                printf( "*** end of PES !\n\n" );
+                /* SPU is finished - we can display it */
+                vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
             }
             else 
             {
-                printf( "*** invalid PES !\n\n" );
-                /* trash the PES packet */
-                /*vlc_mutex_lock( &p_spudec->fifo.data_lock );
+                /* Unexpected PES packet - trash it */
+                vlc_mutex_lock( &p_spudec->fifo.data_lock );
                 input_NetlistFreePES( p_spudec->bit_stream.p_input,
                                       DECODER_FIFO_START(p_spudec->fifo) );
                 DECODER_FIFO_INCSTART( p_spudec->fifo );
-                vlc_mutex_unlock( &p_spudec->fifo.data_lock );*/
+                vlc_mutex_unlock( &p_spudec->fifo.data_lock );
             }
 
         }
         /* Waiting for the input thread to put new PES packets in the fifo */
-        printf( "decoder fifo is empty\n" );
         vlc_cond_wait( &p_spudec->fifo.data_wait, &p_spudec->fifo.data_lock );
+
+        if( p_spu ) vout_DestroySubPicture( p_spudec->p_vout, p_spu );
     }
 
     /*
index 3e520ec8d6ea6dba1809a526bc076e6fe2b2bfcc..7de077c823a9eb26bf295160210ae5eefa6f57d8 100644 (file)
@@ -42,6 +42,7 @@
 #include "video.h"
 #include "video_output.h"
 #include "video_text.h"
+#include "video_spu.h"
 #include "video_yuv.h"
 
 #include "intf_msg.h"
@@ -360,9 +361,10 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
             if( (p_vout->p_subpicture[i_subpic].i_type  == i_type)   &&
                 (p_vout->p_subpicture[i_subpic].i_size  >= i_size) )
             {
-                /* Memory size do match or is smaller : memory will not be reallocated,
-                 * and function can end immediately - this is the best possible case,
-                 * since no memory allocation needs to be done */
+                /* Memory size do match or is smaller : memory will not be
+                 * reallocated, and function can end immediately - this is
+                 * the best possible case, since no memory allocation needs
+                 * to be done */
                 p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE;
 #ifdef DEBUG_VIDEO
                 intf_DbgMsg("subpicture %p (in destroyed subpicture slot)\n",
@@ -389,8 +391,8 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
     /* If no free subpicture is available, use a destroyed subpicture */
     if( (p_free_subpic == NULL) && (p_destroyed_subpic != NULL ) )
     {
-        /* No free subpicture or matching destroyed subpicture has been found, but
-         * a destroyed subpicture is still avalaible */
+        /* No free subpicture or matching destroyed subpicture has been
+         * found, but a destroyed subpicture is still avalaible */
         free( p_destroyed_subpic->p_data );
         p_free_subpic = p_destroyed_subpic;
     }
@@ -1021,11 +1023,20 @@ last_display_date = display_date;
             }
         }
         /*
-         * Find the subpicture to display - this operation does not need lock, since
-         * only READY_SUBPICTURES are handled. If no picture has been selected,
-         * display_date will depend on the subpicture
+         * Find the subpictures to display - this operation does not need
+         * lock, since only READY_SUBPICTURE are handled. If no picture
+         * has been selected, display_date will depend on the subpicture
          */
-        /* XXX?? */
+        /* FIXME: we should find *all* subpictures to display, and
+         * check their displaying date as well */
+        for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
+        {
+            if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
+            {
+                p_subpic = &p_vout->p_subpicture[i_index];
+                break;
+            }
+        }
 
         /*
          * Perform rendering, sleep and display rendered picture
@@ -1075,9 +1086,9 @@ last_display_date = display_date;
                 }
 
                 /* Remove subpicture from heap */
-                vlc_mutex_lock( &p_vout->subpicture_lock );
+                /*vlc_mutex_lock( &p_vout->subpicture_lock );
                 p_subpic->i_status = DESTROYED_SUBPICTURE;
-                vlc_mutex_unlock( &p_vout->subpicture_lock );
+                vlc_mutex_unlock( &p_vout->subpicture_lock );*/
             }
 
         }
@@ -1104,9 +1115,9 @@ last_display_date = display_date;
             }
 
             /* Remove subpicture from heap */
-            vlc_mutex_lock( &p_vout->subpicture_lock );
+            /*vlc_mutex_lock( &p_vout->subpicture_lock );
             p_subpic->i_status = DESTROYED_SUBPICTURE;
-            vlc_mutex_unlock( &p_vout->subpicture_lock );
+            vlc_mutex_unlock( &p_vout->subpicture_lock );*/
         }
         else if( p_vout->b_active )        /* idle or interface screen alone */
         {
@@ -1816,6 +1827,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_subpic->p_data, p_subpic->type.spu.i_offset,
+                        p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
+                        p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line );
+        break;
     case TEXT_SUBPICTURE:                                /* single line text */
         /* Select default font if not specified */
         p_font = p_subpic->type.text.p_font;
@@ -1824,7 +1840,8 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
             p_font = p_vout->p_default_font;
         }
 
-        /* Computes text size (width and height fields are ignored) and print it */
+        /* Compute text size (width and height fields are ignored)
+         * and print it */
         vout_TextSize( p_font, p_subpic->type.text.i_style, p_subpic->p_data, &i_width, &i_height );
         if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y, i_width, i_height,
                     p_subpic->i_horizontal_align, p_subpic->i_vertical_align ) )
diff --git a/src/video_output/video_spu.c b/src/video_output/video_spu.c
new file mode 100644 (file)
index 0000000..5a4b9b7
--- /dev/null
@@ -0,0 +1,207 @@
+/*****************************************************************************
+ * video_spu.h : DVD subpicture units functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ *
+ * Authors:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "defs.h"
+
+#include <stdio.h>
+
+#include "config.h"
+#include "common.h"
+#include "video_spu.h"
+
+#include "intf_msg.h"
+
+typedef struct spu_s
+{
+    int i_id;
+    byte_t *p_data;
+
+    int x;
+    int y;
+    int width;
+    int height;
+
+} spu_t;
+
+static int NewLine  ( spu_t *p_spu, int *i_id );
+static int PutPixel ( spu_t *p_spu, int len, u8 color );
+
+/* i = get_nibble(); */
+#define GET_NIBBLE( i ) \
+    if( b_aligned ) \
+    { \
+        i_next = *p_dest[i_id]; \
+        /*printf("%.1x", i_next >> 4);*/ \
+        p_dest[ i_id ]++; \
+        b_aligned = 0; \
+        i = i_next >> 4; \
+    } \
+    else \
+    { \
+        b_aligned = 1; \
+        /*printf("%.1x", i_next & 0xf);*/ \
+        i = i_next & 0xf; \
+    }
+
+/* i = j + get_nibble(); */
+#define ADD_NIBBLE( i, j ) \
+    if( b_aligned ) \
+    { \
+        i_next = *p_dest[i_id]; \
+        /*printf("%.1x", i_next >> 4);*/ \
+        p_dest[ i_id ]++; \
+        b_aligned = 0; \
+        i = (j) + (i_next >> 4); \
+    } \
+    else \
+    { \
+        b_aligned = 1; \
+        /*printf("%.1x", i_next & 0xf);*/ \
+        i = (j) + (i_next & 0xf); \
+    }
+
+/*****************************************************************************
+ * vout_RenderSPU: draws an SPU on a picture
+ *****************************************************************************
+ * 
+ *****************************************************************************/
+void vout_RenderSPU( byte_t *p_data, int p_offset[2], byte_t *p_pic,
+                     int i_bytes_per_pixel, int i_bytes_per_line )
+{
+    int i_code = 0x00;
+    int i_next = 0;
+    int i_id = 0;
+    boolean_t b_aligned = 1;
+    byte_t *p_dest[2];
+    spu_t spu;
+
+    p_dest[0] = p_data + p_offset[0];
+    p_dest[1] = p_data + p_offset[1];
+
+    spu.x = 0;
+    spu.y = 0;
+    spu.width = 720;
+    spu.height = 576;
+    spu.p_data = p_pic;
+
+    while( p_dest[0] < p_data + p_offset[1] + 2 )
+    {
+        GET_NIBBLE( i_code );
+
+        if( i_code >= 0x04 )
+        {
+            found_code:
+            if( PutPixel( &spu, i_code >> 2, i_code & 3 ) < 0 )
+                return;
+
+            if( spu.x >= spu.width )
+            {
+                /* byte-align the stream */
+                b_aligned = 1;
+                /* finish the line */
+                NewLine( &spu, &i_id );
+            }
+            continue;
+        }
+
+        ADD_NIBBLE( i_code, (i_code << 4) );
+        if( i_code >= 0x10 )       /* 1x .. 3x */
+            goto found_code;
+
+        ADD_NIBBLE( i_code, (i_code << 4) );
+        if( i_code >= 0x40 )       /* 04x .. 0fx */
+            goto found_code;
+
+        ADD_NIBBLE( i_code, (i_code << 4) );
+        if( i_code >= 0x100 )      /* 01xx .. 03xx */
+            goto found_code;
+
+        /* 00xx - should only happen for 00 00 */
+        if( !b_aligned )
+        {
+            ADD_NIBBLE( i_code, (i_code << 4) );
+        }
+
+        if( i_code )
+        {
+            intf_DbgMsg( "video_spu: unknown code 0x%x "
+                         "(dest %x side %x, x=%d, y=%d)\n",
+                         i_code, p_dest[i_id], i_id, spu.x, spu.y );
+            if( NewLine( &spu, &i_id ) < 0 )
+                return;
+            continue;
+        }
+
+        /* aligned 00 00 */
+        if( NewLine( &spu, &i_id ) < 0 )
+            return;
+    }
+}
+
+static int NewLine( spu_t *p_spu, int *i_id )
+{
+    int i_ret = PutPixel( p_spu, p_spu->width - p_spu->x, 0 );
+
+    p_spu->x = 0;
+    p_spu->y++;
+    *i_id = 1 - *i_id;
+
+    return i_ret;
+}
+
+static int PutPixel ( spu_t *p_spu, int i_len, u8 i_color )
+{
+    //static int p_palette[4] = { 0x0000, 0xfef8, 0x7777, 0xffff };
+    static int p_palette[4] = { 0x0000, 0xffff, 0x0000, 0xffff };
+
+    if( (i_len + p_spu->x + p_spu->y * p_spu->width)
+            > p_spu->height * p_spu->width )
+    {
+        intf_DbgMsg ( "video_spu: trying to draw beyond memory area! %d %d\n",
+                      i_len, p_spu->height * p_spu->width
+                             - ( i_len + p_spu->x + p_spu->y * p_spu->width) );
+        p_spu->x += i_len;
+        return -1;
+    }
+    else
+    {
+
+        if( i_color > 0x0f )
+            intf_DbgMsg( "video_spu: invalid color\n" );
+
+        if( i_color )
+        {
+            u8 *p_target
+                = &p_spu->p_data[2 * ( p_spu->x + p_spu->y * p_spu->width ) ];
+
+            memset( p_target, p_palette[i_color], 2 * i_len );
+        }
+        p_spu->x += i_len;
+    }
+
+    return 0;
+}
+
diff --git a/src/video_output/video_spu.h b/src/video_output/video_spu.h
new file mode 100644 (file)
index 0000000..93e4636
--- /dev/null
@@ -0,0 +1,28 @@
+/*****************************************************************************
+ * video_spu.h : DVD subpicture units functions
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ *
+ * Authors:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+void   vout_RenderSPU ( byte_t *p_data, int p_offset[2], byte_t *p_pic,
+                        int i_bytes_per_pixel, int i_bytes_per_line );