* Speed optimization in the handling of the unusual ephemer DVD subtitles.
authorSam Hocevar <sam@videolan.org>
Tue, 8 May 2001 00:43:57 +0000 (00:43 +0000)
committerSam Hocevar <sam@videolan.org>
Tue, 8 May 2001 00:43:57 +0000 (00:43 +0000)
  * Little optimization to bozo's UnalignedShowBits fix.
  * Race fix in the packet cache by Jon Lech Johansen <jon-vl@nanocrew.net>.

AUTHORS
ChangeLog
plugins/mpeg/input_ps.c
plugins/mpeg/input_ps.h
src/input/input_ext-dec.c
src/video_output/video_output.c

diff --git a/AUTHORS b/AUTHORS
index cf8ad9f..c942adf 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -112,6 +112,10 @@ E: bbp@via.ecp.fr
 C: bbp
 D: Bug fixes
 
+N: Jon Lech Johansen
+E: jon-vl@nanocrew.net
+D: PS input fixes
+
 N: Michel Kaempf
 E: maxx@via.ecp.fr
 C: maxx
index 19896d5..ed10914 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,24 @@
 #===================#
 
 HEAD
+  * 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>.
+  * Fixed a bug in UnalignedShowBits that makes some unaligned streams
+    not wotk correctly (for instance VLS' generated TS streams)
+  * Added support for some terribly braindead DVD subtitles in Kenshin
+    which do not have a "stop display" command. Anime fans rejoice!
+  * Fixed the BeOS interface to use p_aout_bank instead of p_main->p_aout.
+  * Coding-style butchery (mostly tabs).
+  * Changed the level arg in intf_WarnMsg so that it makes more sense.
+  * Beginning of the backport of Gnome to Gtk.
+  * Improved ac3 spdif output ( and made it work again :)).
+  * Added p_input->stream.p_selected_area->i_tell in input TS so that the
+    slider work with Transport Stream files.
+  * Moved b_fullscreen from p_vout->p_sys to p_vout and unified way of
+    toggling fullscreen.
+  * Tuned the Gnome interface appearance, added a Preferences window and
+    a Jump window, added Oct's playlist.
   * Fixed a few warnings with gcc 3.0.
   * aout and vout are now allocated in banks, making it possible to have
     several of them at the same time.
index be1f735..d9df981 100644 (file)
@@ -2,7 +2,7 @@
  * input_ps.c: PS demux and packet management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input_ps.c,v 1.22 2001/05/07 04:42:42 sam Exp $
+ * $Id: input_ps.c,v 1.23 2001/05/08 00:43:57 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Cyril Deguet <asmax@via.ecp.fr>
@@ -166,6 +166,9 @@ static void PSInit( input_thread_t * p_input )
         return;
     }
     p_input->p_method_data = (void *)p_packet_cache;
+
+    /* Initialize packet cache mutex */
+    vlc_mutex_init( &p_packet_cache->lock );
     
     /* allocates the data cache */
     p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE * 
@@ -362,6 +365,7 @@ static void PSInit( input_thread_t * p_input )
  *****************************************************************************/
 static void PSEnd( input_thread_t * p_input )
 {
+    vlc_mutex_destroy( &((packet_cache_t *)p_input->p_plugin_data)->lock );
     free( p_input->p_plugin_data );
 }
 
@@ -571,6 +575,8 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
         return NULL;
     }
 
+    vlc_mutex_lock( &p_cache->lock );
+
     /* Checks whether the data cache is empty */
     if( p_cache->data.l_index == 0 )
     {
@@ -578,6 +584,7 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
         if ( (p_data = malloc( sizeof(data_packet_t) )) == NULL )
         {
             intf_ErrMsg( "Out of memory" );
+            vlc_mutex_unlock( &p_cache->lock );
             return NULL;
         }
 #ifdef TRACE_INPUT
@@ -591,6 +598,7 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
             == NULL )
         {
             intf_ErrMsg( "NULL packet in the data cache" );
+            vlc_mutex_unlock( &p_cache->lock );
             return NULL;
         }
     }
@@ -607,6 +615,7 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
             {
                 intf_DbgMsg( "Out of memory" );
                 free( p_data );
+                vlc_mutex_unlock( &p_cache->lock );
                 return NULL;
             }
 #ifdef TRACE_INPUT
@@ -623,6 +632,7 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
             {
                 intf_ErrMsg( "NULL packet in the small buffer cache" );
                 free( p_data );
+                vlc_mutex_unlock( &p_cache->lock );
                 return NULL;
             }
             /* Reallocates the packet if it is too small or too large */
@@ -650,6 +660,7 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
             {
                 intf_ErrMsg( "Out of memory" );
                 free( p_data );
+                vlc_mutex_unlock( &p_cache->lock );
                 return NULL;
             }
 #ifdef TRACE_INPUT
@@ -666,6 +677,7 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
             {
                 intf_ErrMsg( "NULL packet in the small buffer cache" );
                 free( p_data );
+                vlc_mutex_unlock( &p_cache->lock );
                 return NULL;
             }
             /* Reallocates the packet if it is too small or too large */
@@ -682,6 +694,8 @@ static struct data_packet_s * NewPacket( void * p_packet_cache,
         }
     }
 
+    vlc_mutex_unlock( &p_cache->lock );
+
     /* Initialize data */
     p_data->p_next = NULL;
     p_data->b_discard_payload = 0;
@@ -711,6 +725,8 @@ static pes_packet_t * NewPES( void * p_packet_cache )
     }
 #endif
 
+    vlc_mutex_lock( &p_cache->lock );  
+
     /* Checks whether the PES cache is empty */
     if( p_cache->pes.l_index == 0 )
     {
@@ -718,6 +734,7 @@ static pes_packet_t * NewPES( void * p_packet_cache )
         if ( (p_pes = malloc( sizeof(pes_packet_t) )) == NULL )
         {
             intf_DbgMsg( "Out of memory" );
+            vlc_mutex_unlock( &p_cache->lock );        
             return NULL;
         }
 #ifdef TRACE_INPUT
@@ -731,10 +748,13 @@ static pes_packet_t * NewPES( void * p_packet_cache )
             == NULL )
         {
             intf_ErrMsg( "NULL packet in the data cache" );
+            vlc_mutex_unlock( &p_cache->lock );
             return NULL;
         }
     }
 
+    vlc_mutex_unlock( &p_cache->lock );
+
     p_pes->b_data_alignment = p_pes->b_discontinuity =
         p_pes->i_pts = p_pes->i_dts = 0;
     p_pes->i_pes_size = 0;
@@ -764,6 +784,8 @@ static void DeletePacket( void * p_packet_cache,
 
     ASSERT( p_data );
 
+    vlc_mutex_lock( &p_cache->lock );
+
     /* Checks whether the data cache is full */
     if ( p_cache->data.l_index < DATA_CACHE_SIZE )
     {
@@ -819,6 +841,7 @@ static void DeletePacket( void * p_packet_cache,
 #endif
     }
 
+    vlc_mutex_unlock( &p_cache->lock );
 }
 
 /*****************************************************************************
@@ -851,6 +874,8 @@ static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
         p_data = p_next;
     }
 
+    vlc_mutex_lock( &p_cache->lock );
+
     /* Checks whether the PES cache is full */
     if ( p_cache->pes.l_index < PES_CACHE_SIZE )
     {
@@ -865,5 +890,7 @@ static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
         intf_DbgMsg( "PS input: PES packet freed" );
 #endif
     }
+
+    vlc_mutex_unlock( &p_cache->lock );
 }
 
index e28bdb5..4b37119 100644 (file)
@@ -2,7 +2,7 @@
  * input_ps.h: thread structure of the PS plugin
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ps.h,v 1.5 2001/04/16 12:34:28 asmax Exp $
+ * $Id: input_ps.h,v 1.6 2001/05/08 00:43:57 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Cyril Deguet <asmax@via.ecp.fr>
@@ -75,6 +75,7 @@ typedef struct
 
 typedef struct
 {
+    vlc_mutex_t             lock;
     data_packet_cache_t     data;
     pes_packet_cache_t      pes;
     small_buffer_cache_t    small;
index fad6f21..006be27 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-dec.c: services to the decoders
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: input_ext-dec.c,v 1.15 2001/05/07 13:52:39 bozo Exp $
+ * $Id: input_ext-dec.c,v 1.16 2001/05/08 00:43:57 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -181,20 +181,19 @@ u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
                      * of the packet in a temporary buffer, and we'll see
                      * later. */
                     int     i;
-                    /* number of bytes to trash from the last payload */
+
+                    /* sizeof(WORD_TYPE) - number of bytes to trash
+                     * from the last payload */
                     int     j;
 
                     p_bit_stream->i_showbits_buffer = 0;
 
-                    /* is this initialization really usefull ? -- bozo */
-                    j = sizeof(WORD_TYPE);
-
-                    for( i = 0; i < sizeof(WORD_TYPE) ; i++ )
+                    for( j = i = 0 ; i < sizeof(WORD_TYPE) ; i++ )
                     {
                         if( p_bit_stream->p_byte >= p_bit_stream->p_end )
                         {
+                            j = i;
                             p_bit_stream->pf_next_data_packet( p_bit_stream );
-                            j = sizeof(WORD_TYPE) - i;
                         }
                         ((byte_t *)&p_bit_stream->i_showbits_buffer)[i] =
                             * p_bit_stream->p_byte;
@@ -202,7 +201,8 @@ u32 UnalignedShowBits( bit_stream_t * p_bit_stream, unsigned int i_bits )
                     }
 
                     /* This is kind of kludgy. */
-                    p_bit_stream->p_data->p_payload_start += j;
+                    p_bit_stream->p_data->p_payload_start +=
+                                                         sizeof(WORD_TYPE) - j;
                     p_bit_stream->p_byte =
                         (byte_t *)&p_bit_stream->i_showbits_buffer;
                     p_bit_stream->p_end =
index bb558f8..7010f3d 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.126 2001/05/07 04:42:42 sam Exp $
+ * $Id: video_output.c,v 1.127 2001/05/08 00:43:57 sam Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -108,7 +108,7 @@ void vout_EndBank ( void )
     {
         vout_DestroyThread(
                 p_vout_bank->pp_vout[ --p_vout_bank->i_count ], NULL );
-    }                       
+    }
 
     vlc_mutex_destroy( &p_vout_bank->lock );
 }
@@ -181,11 +181,11 @@ vout_thread_t * vout_CreateThread   ( int *pi_status )
     p_vout->i_screen_depth        = main_GetIntVariable( VOUT_DEPTH_VAR,
                                                          VOUT_DEPTH_DEFAULT );
     p_vout->i_bytes_per_pixel     = 2;
-    p_vout->f_gamma               = VOUT_GAMMA_DEFAULT; // FIXME: replace with 
+    p_vout->f_gamma               = VOUT_GAMMA_DEFAULT; // FIXME: replace with
                                                         // variable
     p_vout->b_need_render         = 1;
     p_vout->b_YCbr                = 0;
-    
+
     p_vout->b_grayscale           = main_GetIntVariable( VOUT_GRAYSCALE_VAR,
                                                      VOUT_GRAYSCALE_DEFAULT );
     p_vout->b_info                = 0;
@@ -415,8 +415,8 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
             }
             else if( p_destroyed_subpic == NULL )
             {
-                /* Memory size do not match, but subpicture index will be kept in
-                 * case no other place are left */
+                /* Memory size do not match, but subpicture index will be kept
+                 * in case we find no other place */
                 p_destroyed_subpic = &p_vout->p_subpicture[i_subpic];
             }
         }
@@ -731,7 +731,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
 
         /* Initialize mutex */
         vlc_mutex_init( &(p_free_picture->lock_deccount) );
-        
+
         return( p_free_picture );
     }
 
@@ -771,7 +771,7 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
 
     /* destroy the lock that had been initialized in CreatePicture */
     vlc_mutex_destroy( &(p_pic->lock_deccount) );
-   
+
     vlc_mutex_unlock( &p_vout->picture_lock );
 }
 
@@ -966,7 +966,7 @@ static int InitThread( vout_thread_t *p_vout )
     p_vout->b_active =          1;
     *p_vout->pi_status =        THREAD_READY;
 
-    
+
     intf_DbgMsg("thread ready");
     return( 0 );
 }
@@ -984,8 +984,12 @@ static void RunThread( vout_thread_t *p_vout)
     mtime_t         current_date;                            /* current date */
     mtime_t         display_date;                            /* display date */
     boolean_t       b_display;                               /* display flag */
+
     picture_t *     p_pic;                                /* picture pointer */
+
     subpicture_t *  p_subpic;                          /* subpicture pointer */
+    subpicture_t *  p_ephemer;        /* youngest ephemer subpicture pointer */
+    mtime_t         ephemer_date;                /* earliest subpicture date */
 
     /*
      * Initialize thread
@@ -1006,6 +1010,8 @@ static void RunThread( vout_thread_t *p_vout)
         /* Initialize loop variables */
         p_pic =         NULL;
         p_subpic =      NULL;
+        p_ephemer =     NULL;
+        ephemer_date =  0;
         display_date =  0;
         current_date =  mdate();
 #ifdef STATS
@@ -1073,6 +1079,11 @@ static void RunThread( vout_thread_t *p_vout)
          * 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.
+         *
+         * We also check for ephemer DVD subpictures (subpictures that have
+         * to be removed if a newer one is available), which makes it a lot
+         * more difficult to guess if a subpicture has to be rendered or not.
+         *
          * We get an easily parsable chained list of subpictures which
          * ends with NULL since p_subpic was initialized to NULL.
          */
@@ -1080,8 +1091,86 @@ static void RunThread( vout_thread_t *p_vout)
         {
             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];
+                /* If it is a DVD subpicture, check its date */
+                if( p_vout->p_subpicture[i_index].i_type == DVD_SUBPICTURE )
+                {
+                    if( display_date > p_vout->p_subpicture[i_index].i_stop )
+                    {
+                        /* Too late, destroy the subpic */
+                        vout_DestroySubPicture( p_vout,
+                                        &p_vout->p_subpicture[i_index] );
+                        continue;
+                    }
+
+                    if( display_date < p_vout->p_subpicture[i_index].i_start )
+                    {
+                        /* Too early, come back next monday */
+                        continue;
+                    }
+
+                    /* If this is an ephemer subpic, see if it's the
+                     * youngest we have */
+                    if( p_vout->p_subpicture[i_index].b_ephemer )
+                    {
+                        if( p_ephemer == NULL )
+                        {
+                            p_ephemer = &p_vout->p_subpicture[i_index];
+                            continue;
+                        }
+
+                        if( p_vout->p_subpicture[i_index].i_start
+                                                         < p_ephemer->i_start )
+                        {
+                            /* Link the previous ephemer subpicture and
+                             * replace it with the current one */
+                            p_ephemer->p_next = p_subpic;
+                            p_subpic = p_ephemer;
+                            p_ephemer = &p_vout->p_subpicture[i_index];
+
+                            /* If it's the 2nd youngest subpicture,
+                             * register its date */
+                            if( !ephemer_date
+                                  || ephemer_date > p_subpic->i_start )
+                            {
+                                ephemer_date = p_subpic->i_start;
+                            }
+
+                            continue;
+                        }
+                    }
+
+                    p_vout->p_subpicture[i_index].p_next = p_subpic;
+                    p_subpic = &p_vout->p_subpicture[i_index];
+
+                    /* If it's the 2nd youngest subpicture, register its date */
+                    if( !ephemer_date || ephemer_date > p_subpic->i_start )
+                    {
+                        ephemer_date = p_subpic->i_start;
+                    }
+                }
+                /* If it's not a DVD subpicture, just register it */
+                else
+                {
+                    p_vout->p_subpicture[i_index].p_next = p_subpic;
+                    p_subpic = &p_vout->p_subpicture[i_index];
+                }
+            }
+        }
+
+        /* If we found an ephemer subpicture, check if it has to be
+         * displayed */
+        if( p_ephemer != NULL )
+        {
+            if( p_ephemer->i_start < ephemer_date )
+            {
+                /* Ephemer subpicture has lived too long */
+                vout_DestroySubPicture( p_vout, p_ephemer );
+            }
+            else
+            {
+                /* Ephemer subpicture can still live a bit */
+                p_ephemer->p_next = p_subpic;
+                p_subpic = p_ephemer;
             }
         }
 
@@ -1122,7 +1211,7 @@ static void RunThread( vout_thread_t *p_vout)
             }
 
         }
-        else if( p_vout->b_active && p_vout->b_need_render 
+        else if( p_vout->b_active && p_vout->b_need_render
                   && p_vout->init_display_date == 0)
         {
             /* Idle or interface screen alone */
@@ -1157,21 +1246,21 @@ static void RunThread( vout_thread_t *p_vout)
          * Check for the current time and
          * display splash screen if everything is on time
          */
-        if( p_vout->init_display_date > 0 && p_vout->b_need_render ) 
+        if( p_vout->init_display_date > 0 && p_vout->b_need_render )
         {
-            if( p_vout->b_active && 
+            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;
             }
         }
-            
+
 
         /*
          * Sleep, wake up and display rendered picture
@@ -1342,7 +1431,7 @@ static void DestroyThread( vout_thread_t *p_vout, int i_status )
     vlc_mutex_destroy( &p_vout->picture_lock );
     vlc_mutex_destroy( &p_vout->subpicture_lock );
     vlc_mutex_destroy( &p_vout->change_lock );
-                
+
     /* Release the module */
     module_Unneed( p_vout->p_module );
 
@@ -1705,9 +1794,9 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
 #ifdef TRACE_VOUT
     render_time = mdate();
 #endif
 
-    
+
+
     /*
      * Choose appropriate rendering function and render picture
      */
@@ -1869,8 +1958,8 @@ int RenderIdle( vout_thread_t *p_vout )
 
 
     current_date = mdate();
-    if( (current_date - p_vout->last_display_date) > VOUT_IDLE_DELAY 
-//            && (current_date - p_vout->last_idle_date) > VOUT_IDLE_DELAY 
+    if( (current_date - p_vout->last_display_date) > VOUT_IDLE_DELAY
+//            && (current_date - p_vout->last_idle_date) > VOUT_IDLE_DELAY
     )
     {
         /* FIXME: idle screen disabled */
@@ -1880,7 +1969,7 @@ int RenderIdle( vout_thread_t *p_vout )
                        &i_width, &i_height );
         if( !Align( p_vout, &i_x, &i_y, i_width, i_height * 2, CENTER_RALIGN, CENTER_RALIGN ) )
         {
-            i_amount = (int) ((current_date - p_vout->last_display_date ) / 5000LL);            
+            i_amount = (int) ((current_date - p_vout->last_display_date ) / 5000LL);
             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 * p_vout->i_bytes_per_line,
@@ -1894,7 +1983,7 @@ int RenderIdle( vout_thread_t *p_vout )
                     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_wtext,  (i_amount/5)%110 );
-            
+
 
             SetBufferArea( p_vout, i_x, i_y, i_width, i_height * 2 );
         }
@@ -1952,61 +2041,12 @@ 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 */
-    mtime_t             i_date = mdate();
-
-    subpicture_t       *p_ephemer = NULL;
-    subpicture_t       *p_tmp = p_subpic;
-
-    /* Look for the youngest ephemer */
-    while( p_tmp != NULL )
-    {
-        if( p_tmp->i_type == DVD_SUBPICTURE && p_tmp->b_ephemer
-             && i_date >= p_tmp->i_start && i_date <= p_tmp->i_stop )
-       {
-            if( p_ephemer == NULL || p_tmp->i_start < p_ephemer->i_start )
-           {
-                p_ephemer = p_tmp;
-           }
-        }
-
-        p_tmp = p_tmp->p_next;
-    }
-
-    /* If we found an ephemer, kill it if we find a more recent one */
-    if( p_ephemer != NULL )
-    {
-        p_tmp = p_subpic;
-
-        while( p_tmp != NULL )
-        {
-            if( p_tmp->i_type == DVD_SUBPICTURE
-                 && i_date >= p_tmp->i_start && i_date >= p_tmp->i_start
-                 && p_tmp != p_ephemer && p_tmp->i_start > p_ephemer->i_start )
-            {
-                p_ephemer->i_stop = 0;
-            }
-
-            p_tmp = p_tmp->p_next;
-        }
-    }
 
     while( p_subpic != NULL )
     {
         switch( p_subpic->i_type )
         {
         case DVD_SUBPICTURE:                          /* DVD subpicture unit */
-            /* test if the picture really has to be displayed */
-            if( i_date < p_subpic->i_start )
-            {
-                /* not yet, see you later */
-                break;
-            }
-            if( i_date > p_subpic->i_stop )
-            {
-                /* too late, destroying the subpic */
-                vout_DestroySubPicture( p_vout, p_subpic );
-                break;
-            }
             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 );