* 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>
*
{
vout_DestroyThread(
p_vout_bank->pp_vout[ --p_vout_bank->i_count ], NULL );
- }
+ }
vlc_mutex_destroy( &p_vout_bank->lock );
}
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;
}
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];
}
}
/* Initialize mutex */
vlc_mutex_init( &(p_free_picture->lock_deccount) );
-
+
return( p_free_picture );
}
/* destroy the lock that had been initialized in CreatePicture */
vlc_mutex_destroy( &(p_pic->lock_deccount) );
-
+
vlc_mutex_unlock( &p_vout->picture_lock );
}
p_vout->b_active = 1;
*p_vout->pi_status = THREAD_READY;
-
+
intf_DbgMsg("thread ready");
return( 0 );
}
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
/* Initialize loop variables */
p_pic = NULL;
p_subpic = NULL;
+ p_ephemer = NULL;
+ ephemer_date = 0;
display_date = 0;
current_date = mdate();
#ifdef STATS
* 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.
*/
{
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;
}
}
}
}
- 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 */
* 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
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 );
#ifdef TRACE_VOUT
render_time = mdate();
#endif
-
-
+
+
/*
* Choose appropriate rendering function and render picture
*/
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 */
&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,
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 );
}
{
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 );