|
/**
* Kills a decoder thread and waits until it's finished
*
* \param p_input the input thread
* \param p_es the es descriptor
* \return nothing
*/
void input_DecoderDelete( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_cancel( p_owner->thread );
vlc_fifo_Lock( p_owner->p_fifo );
/* Signal DecoderTimedWait */
/****注意一下这个变量,后面分析问题会用到****/
p_owner->flushing = true;
vlc_cond_signal( &p_owner->wait_timed );
vlc_fifo_Unlock( p_owner->p_fifo );
/* Make sure we aren't waiting/decoding anymore */
vlc_mutex_lock( &p_owner->lock );
p_owner->b_waiting = false;
vlc_cond_signal( &p_owner->wait_request );
/* If the video output is paused or slow, or if the picture pool size was
* under-estimated (e.g. greedy video filter, buggy decoder...), the
* the picture pool may be empty, and the decoder thread or any decoder
* module worker threads may be stuck waiting for free picture buffers.
*
* This unblocks the thread, allowing the decoder module to join all its
* worker threads (if any) and the decoder thread to terminate. */
if( p_owner->p_vout != NULL )
vout_Cancel( p_owner->p_vout, true );
vlc_mutex_unlock( &p_owner->lock );
//这里退出解码线程
vlc_join( p_owner->thread, NULL );
/* */
if( p_dec->p_owner->cc.b_supported )
{
for( int i = 0; i < MAX_CC_DECODERS; i++ )
input_DecoderSetCcState( p_dec, VLC_CODEC_CEA608, i, false );
}
//删除decoder模块
/* Delete decoder */
DeleteDecoder( p_dec );
}
static void DeleteDecoder( decoder_t * p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
msg_Dbg( p_dec, "killing decoder fourcc `%4.4s'",
(char*)&p_dec->fmt_in.i_codec );
const bool b_flush_spu = p_dec->fmt_out.i_cat == SPU_ES;
//释放decoder module
UnloadDecoder( p_dec );
//把解码器队列里的所有待解码的packets全部释放掉了
/* Free all packets still in the decoder fifo. */
block_FifoRelease( p_owner->p_fifo );
/* Cleanup */
//删除对应的aout和vout模块
if( p_owner->p_aout )
{
/* TODO: REVISIT gap-less audio */
aout_DecFlush( p_owner->p_aout, false );
aout_DecDelete( p_owner->p_aout );
input_resource_PutAout( p_owner->p_resource, p_owner->p_aout );
if( p_owner->p_input != NULL )
input_SendEventAout( p_owner->p_input );
}
if( p_owner->p_vout )
{
/* Reset the cancel state that was set before joining the decoder
* thread */
vout_Cancel( p_owner->p_vout, false );
input_resource_RequestVout( p_owner->p_resource, p_owner->p_vout, NULL,
0, true );
if( p_owner->p_input != NULL )
input_SendEventVout( p_owner->p_input );
}
es_format_Clean( &p_owner->fmt );
if( b_flush_spu )
{
vout_thread_t *p_vout = input_resource_HoldVout( p_owner->p_resource );
if( p_vout )
{
if( p_owner->p_spu_vout == p_vout )
vout_FlushSubpictureChannel( p_vout, p_owner->i_spu_channel );
vlc_object_release( p_vout );
}
}
if( p_owner->p_description )
vlc_meta_Delete( p_owner->p_description );
if( p_owner->p_packetizer )
{
UnloadDecoder( p_owner->p_packetizer );
vlc_object_release( p_owner->p_packetizer );
}
vlc_cond_destroy( &p_owner->wait_timed );
vlc_cond_destroy( &p_owner->wait_fifo );
vlc_cond_destroy( &p_owner->wait_acknowledge );
vlc_cond_destroy( &p_owner->wait_request );
vlc_mutex_destroy( &p_owner->lock );
vlc_object_release( p_dec );
free( p_owner );
}
|