/* Display media title in OSD */
static void DisplayTitleOnOSD( vout_thread_t *p_vout );
+/* Time during which the thread will sleep if it has nothing to
+ * display (in micro-seconds) */
+#define VOUT_IDLE_SLEEP ((int)(0.020*CLOCK_FREQ))
+
+/* Maximum lap of time allowed between the beginning of rendering and
+ * display. If, compared to the current date, the next image is too
+ * late, the thread will perform an idle loop. This time should be
+ * at least VOUT_IDLE_SLEEP plus the time required to render a few
+ * images, to avoid trashing of decoded images */
+#define VOUT_DISPLAY_DELAY ((int)(0.200*CLOCK_FREQ))
+
+/* Better be in advance when awakening than late... */
+#define VOUT_MWAIT_TOLERANCE ((mtime_t)(0.020*CLOCK_FREQ))
+
+/* Minimum number of direct pictures the video output will accept without
+ * creating additional pictures in system memory */
+#ifdef OPTIMIZE_MEMORY
+# define VOUT_MIN_DIRECT_PICTURES (VOUT_MAX_PICTURES/2)
+#else
+# define VOUT_MIN_DIRECT_PICTURES (3*VOUT_MAX_PICTURES/4)
+#endif
+
/*****************************************************************************
* Video Filter2 functions
*****************************************************************************/
vout_thread_t *__vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
video_format_t *p_fmt )
{
- const bool b_vout_provided = p_vout != NULL;
if( !p_fmt )
{
/* Video output is no longer used.
vlc_object_detach( p_vout );
vlc_object_attach( p_vout, p_this );
-
- /* Display title if we are not using the vout given to vout_Request.
- * XXX for now b_vout_provided is always true at this stage */
- if( p_vout->p->b_title_show && !b_vout_provided )
- DisplayTitleOnOSD( p_vout );
}
}
vlc_mutex_destroy( &p_vout->p->vfilter_lock );
free( p_vout->p->psz_filter_chain );
+ free( p_vout->p->psz_title );
config_ChainDestroy( p_vout->p_cfg );
vlc_mutex_unlock( &p_vout->picture_lock );
}
+void vout_DisplayTitle( vout_thread_t *p_vout, const char *psz_title )
+{
+ assert( psz_title );
+
+ if( !config_GetInt( p_vout, "osd" ) )
+ return;
+
+ vlc_object_lock( p_vout );
+ free( p_vout->p->psz_title );
+ p_vout->p->psz_title = strdup( psz_title );
+ vlc_object_unlock( p_vout );
+}
/*****************************************************************************
* InitThread: initialize video output thread
vlc_object_lock( p_vout );
- if( p_vout->p->b_title_show )
- DisplayTitleOnOSD( p_vout );
-
/*
* Main loop - it is not executed if an error occurred during
* initialization
picture_t *p_directbuffer;
int i_index;
+ if( p_vout->p->b_title_show && p_vout->p->psz_title )
+ DisplayTitleOnOSD( p_vout );
+
vlc_mutex_lock( &p_vout->picture_lock );
/* Look for the earliest picture but after the last displayed one */
/* Compute FPS rate */
p_vout->p->p_fps_sample[ p_vout->p->c_fps_samples++ % VOUT_FPS_SAMPLES ] = display_date;
- if( display_date > current_date + VOUT_DISPLAY_DELAY && !p_vout->p->b_paused )
+ if( !p_vout->p->b_paused && display_date > current_date + VOUT_DISPLAY_DELAY )
{
/* A picture is ready to be rendered, but its rendering date
* is far from the current one so the thread will perform an
display_date = current_date + p_vout->p->render_time;
}
}
+ else if( p_vout->p->b_paused && display_date > current_date + VOUT_DISPLAY_DELAY )
+ {
+ display_date = current_date + VOUT_DISPLAY_DELAY;
+ }
+
if( p_picture )
{
if( p_picture->date > 1 )
p_filtered_picture = filter_chain_VideoFilter( p_vout->p->p_vf2_chain,
p_picture );
- /* FIXME it is a bit ugly that b_snapshot is not locked but I do not
+ /* FIXME it is ugly that b_snapshot is not locked but I do not
* know which lock to use (here and in the snapshot callback) */
- const bool b_snapshot = p_vout->p->b_snapshot;
- if( b_snapshot )
- p_vout->p->b_snapshot = false;
+ const bool b_snapshot = p_vout->p->b_snapshot && p_picture != NULL;
/*
* Check for subpictures to display
* Take a snapshot if requested
*/
if( p_directbuffer && b_snapshot )
+ {
+ /* FIXME lock (see b_snapshot) */
+ p_vout->p->b_snapshot = false;
+
vout_Snapshot( p_vout, p_directbuffer );
+ }
/*
* Call the plugin-specific rendering method if there is one
}
else
{
- /* Wait until a frame is being sent or a supurious wakeup (not a problem here) */
+ /* Wait until a frame is being sent or a spurious wakeup (not a problem here) */
vlc_mutex_lock( &p_vout->picture_lock );
vlc_cond_timedwait( &p_vout->p->picture_wait, &p_vout->picture_lock, current_date + VOUT_IDLE_SLEEP );
vlc_mutex_unlock( &p_vout->picture_lock );
/* FIXME does that function *really* need to be called inside the thread ? */
- /* Destroy subpicture unit */
+ /* Detach subpicture unit from both input and vout */
spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), false );
+ vlc_object_detach( p_vout->p_spu );
/* Destroy the video filters2 */
filter_chain_Delete( p_vout->p->p_vf2_chain );
VideoFormatImportRgb( &p_chroma->fmt_in.video, &p_vout->render );
VideoFormatImportRgb( &p_chroma->fmt_out.video, &p_vout->output );
- p_chroma->p_module = module_need( p_chroma, "video filter2", NULL, 0 );
+ p_chroma->p_module = module_need( p_chroma, "video filter2", NULL, false );
if( p_chroma->p_module == NULL )
{
static void DisplayTitleOnOSD( vout_thread_t *p_vout )
{
- input_thread_t *p_input;
- mtime_t i_now, i_stop;
+ const mtime_t i_start = mdate();
+ const mtime_t i_stop = i_start + INT64_C(1000) * p_vout->p->i_title_timeout;
- if( !config_GetInt( p_vout, "osd" ) ) return;
+ vlc_object_assert_locked( p_vout );
- p_input = (input_thread_t *)vlc_object_find( p_vout,
- VLC_OBJECT_INPUT, FIND_ANYWHERE );
- if( p_input )
- {
- i_now = mdate();
- i_stop = i_now + (mtime_t)(p_vout->p->i_title_timeout * 1000);
- char *psz_nowplaying =
- input_item_GetNowPlaying( input_GetItem( p_input ) );
- char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
- char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
- if( EMPTY_STR( psz_name ) )
- {
- free( psz_name );
- psz_name = input_item_GetName( input_GetItem( p_input ) );
- }
- if( !EMPTY_STR( psz_nowplaying ) )
- {
- vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
- psz_nowplaying, NULL,
- p_vout->p->i_title_position,
- 30 + p_vout->fmt_in.i_width
- - p_vout->fmt_in.i_visible_width
- - p_vout->fmt_in.i_x_offset,
- 20 + p_vout->fmt_in.i_y_offset,
- i_now, i_stop );
- }
- else if( !EMPTY_STR( psz_artist ) )
- {
- char *psz_string = NULL;
- if( asprintf( &psz_string, "%s - %s", psz_name, psz_artist ) != -1 )
- {
- vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
- psz_string, NULL,
- p_vout->p->i_title_position,
- 30 + p_vout->fmt_in.i_width
- - p_vout->fmt_in.i_visible_width
- - p_vout->fmt_in.i_x_offset,
- 20 + p_vout->fmt_in.i_y_offset,
- i_now, i_stop );
- free( psz_string );
- }
- }
- else
- {
- vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
- psz_name, NULL,
- p_vout->p->i_title_position,
- 30 + p_vout->fmt_in.i_width
- - p_vout->fmt_in.i_visible_width
- - p_vout->fmt_in.i_x_offset,
- 20 + p_vout->fmt_in.i_y_offset,
- i_now, i_stop );
- }
- vlc_object_release( p_input );
- free( psz_artist );
- free( psz_name );
- free( psz_nowplaying );
- }
+ vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
+ p_vout->p->psz_title, NULL,
+ p_vout->p->i_title_position,
+ 30 + p_vout->fmt_in.i_width
+ - p_vout->fmt_in.i_visible_width
+ - p_vout->fmt_in.i_x_offset,
+ 20 + p_vout->fmt_in.i_y_offset,
+ i_start, i_stop );
+
+ free( p_vout->p->psz_title );
+
+ p_vout->p->psz_title = NULL;
}