From abe5a7d0c0d40422c71bb4bebec73e4833600367 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Tue, 8 May 2001 00:43:57 +0000 Subject: [PATCH] * 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 . --- AUTHORS | 4 + ChangeLog | 18 ++++ plugins/mpeg/input_ps.c | 29 ++++- plugins/mpeg/input_ps.h | 3 +- src/input/input_ext-dec.c | 16 +-- src/video_output/video_output.c | 184 +++++++++++++++++++------------- 6 files changed, 172 insertions(+), 82 deletions(-) diff --git a/AUTHORS b/AUTHORS index cf8ad9fb2b..c942adfe98 100644 --- 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 diff --git a/ChangeLog b/ChangeLog index 19896d59c4..ed10914de4 100644 --- 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 . + * 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. diff --git a/plugins/mpeg/input_ps.c b/plugins/mpeg/input_ps.c index be1f735659..d9df981630 100644 --- a/plugins/mpeg/input_ps.c +++ b/plugins/mpeg/input_ps.c @@ -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 * Cyril Deguet @@ -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 ); } diff --git a/plugins/mpeg/input_ps.h b/plugins/mpeg/input_ps.h index e28bdb5624..4b37119e1b 100644 --- a/plugins/mpeg/input_ps.h +++ b/plugins/mpeg/input_ps.h @@ -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 * Cyril Deguet @@ -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; diff --git a/src/input/input_ext-dec.c b/src/input/input_ext-dec.c index fad6f216e2..006be27000 100644 --- a/src/input/input_ext-dec.c +++ b/src/input/input_ext-dec.c @@ -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 * @@ -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 = diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index bb558f87ad..7010f3dd1d 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -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 * @@ -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 ); -- 2.39.2