]> git.sesse.net Git - vlc/commitdiff
. les sous-titres sont affich�s et effac�s � l'heure
authorSam Hocevar <sam@videolan.org>
Thu, 23 Mar 2000 06:27:35 +0000 (06:27 +0000)
committerSam Hocevar <sam@videolan.org>
Thu, 23 Mar 2000 06:27:35 +0000 (06:27 +0000)
 . une petite optimisation de l'affichage
 . attention, config.h.in a chang�, n'oubliez pas de refaire ./configure

include/config.h.in
include/video.h
src/spu_decoder/spu_decoder.c
src/video_output/video_output.c
src/video_output/video_spu.c

index 8779a34fcf11ed78079de978b4dec24c78c99855..16ff948cb2939a29cac42607f857131e743f059e 100644 (file)
  * (~1 Mbyte) before using huge values */
 #define VOUT_MAX_PICTURES               10
 
+/* Number of simultaneous subpictures */
+#define VOUT_MAX_SUBPICTURES            10
+
 /* Maximum number of active areas in a rendering buffer. Active areas are areas
  * of the picture which need to be cleared before re-using the buffer. If a
  * picture, including its many additions such as subtitles, additionnal user
index c9f865b45685e5b0a0b4d5b09144a5ba9791cba0..496baa35a843d43816117375a1c5d8810418e177 100644 (file)
@@ -119,6 +119,7 @@ typedef struct subpicture_s
     int             i_type;                                          /* type */
     int             i_status;                                       /* flags */
     int             i_size;                                     /* data size */
+    struct subpicture_s *   p_next;              /* next SPU to be displayed */
 
     /* Other properties */
     mtime_t         begin_date;                 /* beginning of display date */
index 9c9d130e350a5be32b603ea952ecf9cfac44aa6f..fbae6103fc43ee9d51bb350b5da01b175b6a53fa 100644 (file)
@@ -238,15 +238,16 @@ static void RunThread( spudec_thread_t *p_spudec )
             /* 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 );
-
                 /* 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;
 
+                /* get display time */
+                p_spu->begin_date = p_spu->end_date
+                                = DECODER_FIFO_START(p_spudec->fifo)->i_pts;
+
                 /* getting the RLE part */
                 while( i_index++ < i_rle_size )
                 {
@@ -264,9 +265,10 @@ static void RunThread( spudec_thread_t *p_spudec )
                 {
                     unsigned char i_cmd;
                     unsigned int i_word;
+                    unsigned int i_date;
 
                     /* the date */
-                    GetWord( i_word );
+                    GetWord( i_date );
 
                     /* next offset, no next offset if == i_index-5 */
                     GetWord( i_word );
@@ -280,14 +282,16 @@ static void RunThread( spudec_thread_t *p_spudec )
                         switch( i_cmd )
                         {
                             case 0x00:
-                                /* 00 (display now) */
+                                /* 00 (force displaying) */
                                 break;
                             case 0x01:
                                 /* 01 (start displaying) */
-                                break;
+                                p_spu->begin_date += (i_date * 1000000 / 80);
+                                break;    /* FIXME: 80 is absolutely empiric */
                             case 0x02:
                                 /* 02 (stop displaying) */
-                                break;
+                                p_spu->end_date += (i_date * 1000000 / 80);
+                                break;    /* FIXME: 80 is absolutely empiric */
                             case 0x03:
                                 /* 03xxxx (palette) */
                                 GetWord( i_word );
@@ -299,13 +303,21 @@ static void RunThread( spudec_thread_t *p_spudec )
                             case 0x05:
                                 /* 05xxxyyyxxxyyy (coordinates) */
                                 i_word = GetByte( &p_spudec->bit_stream );
-                                p_spu->type.spu.i_x1 = (i_word << 4) | GetBits( &p_spudec->bit_stream, 4 );
+                                p_spu->type.spu.i_x1 = (i_word << 4)
+                                        | GetBits( &p_spudec->bit_stream, 4 );
+
                                 i_word = GetBits( &p_spudec->bit_stream, 4 );
-                                p_spu->type.spu.i_x2 = (i_word << 8) | GetByte( &p_spudec->bit_stream );
+                                p_spu->type.spu.i_x2 = (i_word << 8)
+                                        | GetByte( &p_spudec->bit_stream );
+
                                 i_word = GetByte( &p_spudec->bit_stream );
-                                p_spu->type.spu.i_y1 = (i_word << 4) | GetBits( &p_spudec->bit_stream, 4 );
+                                p_spu->type.spu.i_y1 = (i_word << 4)
+                                        | GetBits( &p_spudec->bit_stream, 4 );
+
                                 i_word = GetBits( &p_spudec->bit_stream, 4 );
-                                p_spu->type.spu.i_y2 = (i_word << 8) | GetByte( &p_spudec->bit_stream );
+                                p_spu->type.spu.i_y2 = (i_word << 8)
+                                        | GetByte( &p_spudec->bit_stream );
+
                                i_index += 6;
                                 break;
                             case 0x06:
index b2b9c6add7599e218fe5fe584b89a211fe73d44c..a4f2a769e8a0d71d911f66503afc18fa929ddd45 100644 (file)
@@ -171,6 +171,9 @@ vout_thread_t * vout_CreateThread   ( char *psz_display, int i_root_window,
     {
         p_vout->p_picture[i_index].i_type   =   EMPTY_PICTURE;
         p_vout->p_picture[i_index].i_status =   FREE_PICTURE;
+    }
+    for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++)
+    {
         p_vout->p_subpicture[i_index].i_type  = EMPTY_SUBPICTURE;
         p_vout->p_subpicture[i_index].i_status= FREE_SUBPICTURE;
     }
@@ -353,7 +356,7 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
     /*
      * Look for an empty place
      */
-    for( i_subpic = 0; i_subpic < VOUT_MAX_PICTURES; i_subpic++ )
+    for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
     {
         if( p_vout->p_subpicture[i_subpic].i_status == DESTROYED_SUBPICTURE )
         {
@@ -981,8 +984,8 @@ last_display_date = display_date;
 #if 1
             if( display_date < current_date && i_trash_count > 4 )
             {
-                /* Picture is late: it will be destroyed and the thread will sleep and
-                 * go to next picture */
+                /* Picture is late: it will be destroyed and the thread
+                 * will sleep and go to next picture */
 
                 vlc_mutex_lock( &p_vout->picture_lock );
                 if( p_pic->i_refcount )
@@ -1026,16 +1029,16 @@ last_display_date = display_date;
         /*
          * 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
+         * has been selected, display_date will depend on the subpicture.
+         * We get an easily parsable chained list of subpictures which
+         * ends with NULL since p_subpic was initialized to NULL.
          */
-        /* 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++ )
+        for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
         {
             if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
             {
+                p_vout->p_subpicture[i_index].p_next = p_subpic;
                 p_subpic = &p_vout->p_subpicture[i_index];
-                break;
             }
         }
 
@@ -1249,6 +1252,9 @@ static void EndThread( vout_thread_t *p_vout )
         {
             free( p_vout->p_picture[i_index].p_data );
         }
+    }
+    for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
+    {
         if( p_vout->p_subpicture[i_index].i_status != FREE_SUBPICTURE )
         {
             free( p_vout->p_subpicture[i_index].p_data );
@@ -1828,43 +1834,67 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
     p_vout_font_t       p_font;                                 /* text font */
     int                 i_width, i_height;          /* subpicture dimensions */
 
-    switch( p_subpic->i_type )
+    while( p_subpic != NULL )
     {
-    case DVD_SUBPICTURE:                              /* DVD subpicture unit */
-        vout_RenderSPU( p_subpic->p_data, p_subpic->type.spu.i_offset,
-                        p_subpic->type.spu.i_x1, p_subpic->type.spu.i_y1,
-                        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;
-        if( p_font == NULL )
+        switch( p_subpic->i_type )
         {
-            p_font = p_vout->p_default_font;
-        }
+        case DVD_SUBPICTURE:                          /* DVD subpicture unit */
+            /* test if the picture really has to be displayed */
+            if( mdate() < p_subpic->begin_date )
+            {
+                break;
+            }
+            if( mdate() > p_subpic->end_date )
+            {
+                /* too late, destroying the subpic */
+                vout_DestroySubPicture( p_vout, p_subpic );
+                printf( "destroying subpicture\n" );
+                break;
+            }
+            vout_RenderSPU( p_subpic->p_data, p_subpic->type.spu.i_offset,
+                            p_subpic->type.spu.i_x1, p_subpic->type.spu.i_y1,
+                            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;
+            if( p_font == NULL )
+            {
+                p_font = p_vout->p_default_font;
+            }
 
-        /* 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 ) )
-        {
-            vout_Print( p_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
-                        p_subpic->i_x * p_vout->i_bytes_per_pixel +
-                        p_subpic->i_y * p_vout->i_bytes_per_line,
-                        p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
-                        p_subpic->type.text.i_char_color, p_subpic->type.text.i_border_color,
-                        p_subpic->type.text.i_bg_color, p_subpic->type.text.i_style,
-                        p_subpic->p_data );
-            SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y, i_width, i_height );
-        }
-        break;
+            /* 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 ) )
+            {
+                vout_Print( p_font,
+                            p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
+                            p_subpic->i_x * p_vout->i_bytes_per_pixel +
+                            p_subpic->i_y * p_vout->i_bytes_per_line,
+                            p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
+                            p_subpic->type.text.i_char_color,
+                            p_subpic->type.text.i_border_color,
+                            p_subpic->type.text.i_bg_color,
+                            p_subpic->type.text.i_style, p_subpic->p_data );
+                SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y,
+                               i_width, i_height );
+            }
+            break;
 
 #ifdef DEBUG
-    default:
-        intf_DbgMsg("error: unknown subpicture %p type %d\n", p_subpic, p_subpic->i_type );
+        default:
+            intf_DbgMsg( "error: unknown subpicture %p type %d\n",
+                         p_subpic, p_subpic->i_type );
 #endif
+        }
+
+        p_subpic = p_subpic->p_next;
     }
 }
 
index 1d82875ecf6bb6e4d74ccd7a631368e8d3049721..1a98576a10786784da427adc37eab985e40e1f51 100644 (file)
@@ -47,7 +47,6 @@ typedef struct spu_s
 } 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 ) \
@@ -95,6 +94,9 @@ void vout_RenderSPU( byte_t *p_data, int p_offset[2],
     int i_code = 0x00;
     int i_next = 0;
     int i_id = 0;
+    int i_color;
+    static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x0000 };
+
     boolean_t b_aligned = 1;
     byte_t *p_from[2];
     spu_t spu;
@@ -108,15 +110,33 @@ void vout_RenderSPU( byte_t *p_data, int p_offset[2],
     spu.height = 576;
     spu.p_data = p_pic + i_x * i_bytes_per_pixel + i_y * i_bytes_per_line;
 
-    while( p_from[0] < p_data + p_offset[1] + 2 )
+    while( p_from[0] < p_data + p_offset[1] )
     {
         GET_NIBBLE( i_code );
 
         if( i_code >= 0x04 )
         {
             found_code:
-            if( PutPixel( &spu, i_code >> 2, i_code & 3 ) < 0 )
+
+            if( ((i_code >> 2) + spu.x + spu.y * spu.width)
+                    > spu.height * spu.width )
+            {
+                intf_DbgMsg ( "video_spu: invalid draw request ! %d %d\n",
+                              i_code >> 2, spu.height * spu.width
+                               - ( (i_code >> 2) + spu.x
+                                   + spu.y * spu.width ) );
                 return;
+            }
+            else
+            {
+                if( (i_color = i_code & 0x3) )
+                {
+                    u8 *p_target = &spu.p_data[ 2 * 
+                                    ( spu.x + spu.y * spu.width ) ];
+                    memset( p_target, p_palette[i_color], 2 * (i_code >> 2) );
+                }
+                spu.x += i_code >> 2;
+            }
 
             if( spu.x >= spu.width )
             {
@@ -164,45 +184,12 @@ void vout_RenderSPU( byte_t *p_data, int p_offset[2],
 
 static int NewLine( spu_t *p_spu, int *i_id )
 {
-    int i_ret = PutPixel( p_spu, p_spu->width - p_spu->x, 0 );
+    *i_id = 1 - *i_id;
 
     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, 0x5555, 0x0000 };
-
-    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( p_spu->width - p_spu->y );
 
-    return 0;
 }