Commit 7e8ca640 authored by Laurent Aimar's avatar Laurent Aimar

Moved vout helpers out of decoder.c.

parent db7ba956
...@@ -1160,47 +1160,6 @@ static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ) ...@@ -1160,47 +1160,6 @@ static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
} }
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
} }
static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->picture_lock );
if( p_pic->i_status == READY_PICTURE )
{
/* Grr cannot destroy ready picture by myself so be sure vout won't like it */
p_pic->date = 1;
}
else if( p_pic->i_refcount > 0 )
{
p_pic->i_status = DISPLAYED_PICTURE;
}
else
{
p_pic->i_status = DESTROYED_PICTURE;
picture_CleanupQuant( p_pic );
p_vout->i_heap_size--;
}
vlc_mutex_unlock( &p_vout->picture_lock );
}
static void VoutFlushPicture( vout_thread_t *p_vout, mtime_t i_max_date )
{
int i;
vlc_mutex_lock( &p_vout->picture_lock );
for( 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_max_date )
p_pic->date = i_max_date;
}
}
vlc_mutex_unlock( &p_vout->picture_lock );
}
static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
int *pi_played_sum, int *pi_lost_sum ) int *pi_played_sum, int *pi_lost_sum )
...@@ -1212,7 +1171,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, ...@@ -1212,7 +1171,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
{ {
msg_Warn( p_vout, "non-dated video buffer received" ); msg_Warn( p_vout, "non-dated video buffer received" );
*pi_lost_sum += 1; *pi_lost_sum += 1;
VoutDisplayedPicture( p_vout, p_picture ); vout_DropPicture( p_vout, p_picture );
return; return;
} }
...@@ -1297,7 +1256,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, ...@@ -1297,7 +1256,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
if( i_rate != p_owner->i_last_rate ) if( i_rate != p_owner->i_last_rate )
{ {
/* Be sure to not display old picture after our own */ /* Be sure to not display old picture after our own */
VoutFlushPicture( p_vout, p_picture->date ); vout_Flush( p_vout, p_picture->date );
p_owner->i_last_rate = i_rate; p_owner->i_last_rate = i_rate;
} }
...@@ -1317,7 +1276,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, ...@@ -1317,7 +1276,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
p_picture->date - mdate() ); p_picture->date - mdate() );
} }
*pi_lost_sum += 1; *pi_lost_sum += 1;
VoutDisplayedPicture( p_vout, p_picture ); vout_DropPicture( p_vout, p_picture );
} }
int i_tmp_display; int i_tmp_display;
int i_tmp_lost; int i_tmp_lost;
...@@ -1353,7 +1312,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) ...@@ -1353,7 +1312,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
if( p_dec->b_die ) if( p_dec->b_die )
{ {
/* It prevent freezing VLC in case of broken decoder */ /* It prevent freezing VLC in case of broken decoder */
VoutDisplayedPicture( p_vout, p_pic ); vout_DropPicture( p_vout, p_pic );
if( p_block ) if( p_block )
block_Release( p_block ); block_Release( p_block );
break; break;
...@@ -1363,7 +1322,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) ...@@ -1363,7 +1322,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
if( p_pic->date < p_owner->i_preroll_end ) if( p_pic->date < p_owner->i_preroll_end )
{ {
VoutDisplayedPicture( p_vout, p_pic ); vout_DropPicture( p_vout, p_pic );
continue; continue;
} }
...@@ -1371,7 +1330,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) ...@@ -1371,7 +1330,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{ {
msg_Dbg( p_dec, "End of video preroll" ); msg_Dbg( p_dec, "End of video preroll" );
if( p_vout ) if( p_vout )
VoutFlushPicture( p_vout, 1 ); vout_Flush( p_vout, 1 );
/* */ /* */
p_owner->i_preroll_end = -1; p_owner->i_preroll_end = -1;
} }
...@@ -1513,7 +1472,7 @@ static void DecoderFlushBuffering( decoder_t *p_dec ) ...@@ -1513,7 +1472,7 @@ static void DecoderFlushBuffering( decoder_t *p_dec )
p_owner->buffer.i_count--; p_owner->buffer.i_count--;
if( p_owner->p_vout ) if( p_owner->p_vout )
VoutDisplayedPicture( p_owner->p_vout, p_picture ); vout_DropPicture( p_owner->p_vout, p_picture );
if( !p_owner->buffer.p_picture ) if( !p_owner->buffer.p_picture )
p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture; p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
...@@ -1655,7 +1614,7 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flus ...@@ -1655,7 +1614,7 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flus
} }
if( b_flush && p_owner->p_vout ) if( b_flush && p_owner->p_vout )
VoutFlushPicture( p_owner->p_vout, 1 ); vout_Flush( p_owner->p_vout, 1 );
} }
/* This function process a audio block /* This function process a audio block
...@@ -2106,7 +2065,6 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2106,7 +2065,6 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
for( ;; ) for( ;; )
{ {
picture_t *p_picture; picture_t *p_picture;
int i_pic, i_ready_pic;
if( p_dec->b_die || p_dec->b_error ) if( p_dec->b_die || p_dec->b_error )
return NULL; return NULL;
...@@ -2130,47 +2088,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2130,47 +2088,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
DecoderSignalBuffering( p_dec, true ); DecoderSignalBuffering( p_dec, true );
/* Check the decoder doesn't leak pictures */ /* Check the decoder doesn't leak pictures */
for( i_pic = 0, i_ready_pic = 0; i_pic < p_owner->p_vout->render.i_pictures; i_pic++ ) vout_FixLeaks( p_owner->p_vout );
{
const picture_t *p_pic = p_owner->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_owner->p_vout->render.i_pictures )
{
/* Too many pictures are still referenced, there is probably a bug
* with the decoder */
msg_Err( p_dec, "decoder is leaking pictures, resetting the heap" );
/* Just free all the pictures */
for( i_pic = 0; i_pic < p_owner->p_vout->render.i_pictures; i_pic++ )
{
picture_t *p_pic = p_owner->p_vout->render.pp_picture[i_pic];
if( p_pic->i_status == RESERVED_PICTURE )
vout_DestroyPicture( p_owner->p_vout, p_pic );
if( p_pic->i_refcount > 0 )
vout_UnlinkPicture( p_owner->p_vout, p_pic );
}
}
msleep( VOUT_OUTMEM_SLEEP ); msleep( VOUT_OUTMEM_SLEEP );
} }
...@@ -2178,7 +2096,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2178,7 +2096,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic ) static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
{ {
VoutDisplayedPicture( p_dec->p_owner->p_vout, p_pic ); vout_DropPicture( p_dec->p_owner->p_vout, p_pic );
} }
static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic ) static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic )
......
...@@ -375,7 +375,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) ...@@ -375,7 +375,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
p_vout->p->i_par_den = 1; p_vout->p->i_par_den = 1;
/* Initialize locks */ /* Initialize locks */
vlc_mutex_init( &p_vout->picture_lock ); vlc_mutex_init_recursive( &p_vout->picture_lock );
vlc_mutex_init( &p_vout->change_lock ); vlc_mutex_init( &p_vout->change_lock );
vlc_mutex_init( &p_vout->p->vfilter_lock ); vlc_mutex_init( &p_vout->p->vfilter_lock );
...@@ -628,6 +628,58 @@ void vout_Flush( vout_thread_t *p_vout, mtime_t i_date ) ...@@ -628,6 +628,58 @@ void vout_Flush( vout_thread_t *p_vout, mtime_t i_date )
} }
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
void vout_FixLeaks( vout_thread_t *p_vout )
{
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; 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 )
{
vlc_mutex_unlock( &p_vout->picture_lock );
return;
}
/* Too many pictures are still referenced, there is probably a bug
* with the decoder */
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];
if( p_pic->i_status == RESERVED_PICTURE )
vout_DestroyPicture( p_vout, p_pic );
if( p_pic->i_refcount > 0 )
vout_UnlinkPicture( p_vout, p_pic );
}
vlc_mutex_unlock( &p_vout->picture_lock );
}
/***************************************************************************** /*****************************************************************************
* InitThread: initialize video output thread * InitThread: initialize video output thread
***************************************************************************** *****************************************************************************
...@@ -659,10 +711,6 @@ static int InitThread( vout_thread_t *p_vout ) ...@@ -659,10 +711,6 @@ static int InitThread( vout_thread_t *p_vout )
{ {
int i, i_aspect_x, i_aspect_y; int i, i_aspect_x, i_aspect_y;
#ifdef STATS
p_vout->c_loops = 0;
#endif
/* Initialize output method, it allocates direct buffers for us */ /* Initialize output method, it allocates direct buffers for us */
if( p_vout->pf_init( p_vout ) ) if( p_vout->pf_init( p_vout ) )
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -843,7 +891,7 @@ static void* RunThread( vlc_object_t *p_this ) ...@@ -843,7 +891,7 @@ static void* RunThread( vlc_object_t *p_this )
bool b_drop_late; bool b_drop_late;
int canc = vlc_savecancel (); int canc = vlc_savecancel();
/* /*
* Initialize thread * Initialize thread
...@@ -860,7 +908,7 @@ static void* RunThread( vlc_object_t *p_this ) ...@@ -860,7 +908,7 @@ static void* RunThread( vlc_object_t *p_this )
{ {
EndThread( p_vout ); EndThread( p_vout );
vlc_mutex_unlock( &p_vout->change_lock ); vlc_mutex_unlock( &p_vout->change_lock );
vlc_restorecancel (canc); vlc_restorecancel( canc );
return NULL; return NULL;
} }
...@@ -883,15 +931,6 @@ static void* RunThread( vlc_object_t *p_this ) ...@@ -883,15 +931,6 @@ static void* RunThread( vlc_object_t *p_this )
picture_t *p_directbuffer; picture_t *p_directbuffer;
int i_index; int i_index;
#if 0
p_vout->c_loops++;
if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) )
{
msg_Dbg( p_vout, "picture heap: %d/%d",
I_RENDERPICTURES, p_vout->i_heap_size );
}
#endif
/* /*
* Find the picture to display (the one with the earliest date). * Find the picture to display (the one with the earliest date).
* This operation does not need lock, since only READY_PICTUREs * This operation does not need lock, since only READY_PICTUREs
...@@ -1236,7 +1275,7 @@ static void* RunThread( vlc_object_t *p_this ) ...@@ -1236,7 +1275,7 @@ static void* RunThread( vlc_object_t *p_this )
vlc_mutex_unlock( &p_vout->change_lock ); vlc_mutex_unlock( &p_vout->change_lock );
vlc_object_unlock( p_vout ); vlc_object_unlock( p_vout );
vlc_restorecancel (canc); vlc_restorecancel( canc );
return NULL; return NULL;
} }
......
...@@ -53,13 +53,6 @@ struct vout_thread_sys_t ...@@ -53,13 +53,6 @@ struct vout_thread_sys_t
/* Statistics */ /* Statistics */
int i_picture_lost; int i_picture_lost;
int i_picture_displayed; int i_picture_displayed;
#if 0
count_t c_loops;
count_t c_pictures, c_late_pictures;
mtime_t display_jitter; /**< average deviation from the PTS */
count_t c_jitter_samples; /**< number of samples used
for the calculation of the jitter */
#endif
/* Pause */ /* Pause */
bool b_paused; bool b_paused;
...@@ -111,5 +104,18 @@ void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_l ...@@ -111,5 +104,18 @@ void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_l
*/ */
void vout_Flush( vout_thread_t *p_vout, mtime_t i_date ); void vout_Flush( vout_thread_t *p_vout, mtime_t i_date );
/**
* This function will try to detect if pictures are being leaked. If so it
* will release them.
*
* XXX This function is there to workaround bugs in decoder
*/
void vout_FixLeaks( vout_thread_t *p_vout );
/**
* This functions will drop a picture retreived by vout_CreatePicture.
*/
void vout_DropPicture( vout_thread_t *p_vout, picture_t * );
#endif #endif
...@@ -268,6 +268,30 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -268,6 +268,30 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
/* */
void vout_DropPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->picture_lock );
if( p_pic->i_status == READY_PICTURE )
{
/* Grr cannot destroy ready picture by myself so be sure vout won't like it */
p_pic->date = 1;
}
else if( p_pic->i_refcount > 0 )
{
p_pic->i_status = DISPLAYED_PICTURE;
}
else
{
p_pic->i_status = DESTROYED_PICTURE;
p_vout->i_heap_size--;
picture_CleanupQuant( p_pic );
}
vlc_mutex_unlock( &p_vout->picture_lock );
}
/** /**
* Increment reference counter of a picture * Increment reference counter of a picture
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment