+ vlc_mutex_unlock( &p_vout->change_lock );
+}
+
+void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_lost )
+{
+ vlc_mutex_lock( &p_vout->change_lock );
+
+ *pi_displayed = p_vout->p->i_picture_displayed;
+ *pi_lost = p_vout->p->i_picture_lost;
+
+ p_vout->p->i_picture_displayed = 0;
+ p_vout->p->i_picture_lost = 0;
+
+ vlc_mutex_unlock( &p_vout->change_lock );
+}
+
+void vout_Flush( vout_thread_t *p_vout, mtime_t i_date )
+{
+ vlc_mutex_lock( &p_vout->picture_lock );
+ p_vout->p->i_picture_displayed_date = 0;
+ for( int i = 0; i < p_vout->render.i_pictures; i++ )
+ {
+ picture_t *p_pic = p_vout->render.pp_picture[i];
+
+ if( p_pic->i_status == READY_PICTURE ||
+ p_pic->i_status == DISPLAYED_PICTURE )
+ {
+ /* We cannot change picture status if it is in READY_PICTURE state,
+ * Just make sure they won't be displayed */
+ if( p_pic->date > i_date )
+ p_pic->date = i_date;
+ }
+ }
+ vlc_cond_signal( &p_vout->p->picture_wait );
+ vlc_mutex_unlock( &p_vout->picture_lock );
+}
+
+void vout_FixLeaks( vout_thread_t *p_vout, bool b_forced )
+{
+ int i_pic, i_ready_pic;
+
+ vlc_mutex_lock( &p_vout->picture_lock );
+
+ for( i_pic = 0, i_ready_pic = 0; i_pic < p_vout->render.i_pictures && !b_forced; i_pic++ )
+ {
+ const picture_t *p_pic = p_vout->render.pp_picture[i_pic];
+
+ if( p_pic->i_status == READY_PICTURE )
+ {
+ i_ready_pic++;
+ /* If we have at least 2 ready pictures, wait for the vout thread to
+ * process one */
+ if( i_ready_pic >= 2 )
+ break;
+
+ continue;
+ }
+
+ if( p_pic->i_status == DISPLAYED_PICTURE )
+ {
+ /* If at least one displayed picture is not referenced
+ * let vout free it */
+ if( p_pic->i_refcount == 0 )
+ break;
+ }
+ }
+ if( i_pic < p_vout->render.i_pictures && !b_forced )
+ {
+ vlc_mutex_unlock( &p_vout->picture_lock );
+ return;
+ }
+
+ /* Too many pictures are still referenced, there is probably a bug
+ * with the decoder */
+ if( !b_forced )
+ msg_Err( p_vout, "pictures leaked, resetting the heap" );
+
+ /* Just free all the pictures */
+ for( i_pic = 0; i_pic < p_vout->render.i_pictures; i_pic++ )
+ {
+ picture_t *p_pic = p_vout->render.pp_picture[i_pic];
+
+ msg_Dbg( p_vout, "[%d] %d %d", i_pic, p_pic->i_status, p_pic->i_refcount );
+ p_pic->i_refcount = 0;
+
+ switch( p_pic->i_status )
+ {
+ case READY_PICTURE:
+ case DISPLAYED_PICTURE:
+ case RESERVED_PICTURE:
+ if( p_pic != p_vout->p->p_picture_displayed )
+ vout_UsePictureLocked( p_vout, p_pic );
+ break;
+ }
+ }
+ vlc_cond_signal( &p_vout->p->picture_wait );
+ vlc_mutex_unlock( &p_vout->picture_lock );
+}
+void vout_NextPicture( vout_thread_t *p_vout, mtime_t *pi_duration )
+{
+ vlc_mutex_lock( &p_vout->picture_lock );
+
+ const mtime_t i_displayed_date = p_vout->p->i_picture_displayed_date;
+
+ p_vout->p->b_picture_displayed = false;
+ p_vout->p->b_picture_empty = false;
+ if( p_vout->p->p_picture_displayed )
+ {
+ p_vout->p->p_picture_displayed->date = 1;
+ vlc_cond_signal( &p_vout->p->picture_wait );
+ }
+
+ while( !p_vout->p->b_picture_displayed && !p_vout->p->b_picture_empty )
+ vlc_cond_wait( &p_vout->p->picture_wait, &p_vout->picture_lock );
+
+ *pi_duration = __MAX( p_vout->p->i_picture_displayed_date - i_displayed_date, 0 );
+
+ /* TODO advance subpicture by the duration ... */
+
+ 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_mutex_lock( &p_vout->change_lock );
+ free( p_vout->p->psz_title );
+ p_vout->p->psz_title = strdup( psz_title );
+ vlc_mutex_unlock( &p_vout->change_lock );