static void DeleteDecoder( decoder_t * );
static void *DecoderThread( vlc_object_t * );
-static int DecoderDecode( decoder_t * p_dec, block_t *p_block );
+static int DecoderProcess( decoder_t * p_dec, block_t *p_block );
static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date );
/* Buffers allocation callbacks for the decoders */
vout_thread_t *p_vout;
/* -- Theses variables need locking on read *and* write -- */
+ /* */
/* Pause */
bool b_paused;
mtime_t i_pause_date;
/* CC */
- bool b_cc_supported;
- bool pb_cc_present[4];
- decoder_t *pp_cc[4];
+ struct
+ {
+ bool b_supported;
+ bool pb_present[4];
+ decoder_t *pp_decoder[4];
+ } cc;
/* Delay */
mtime_t i_ts_delay;
}
/* */
- if( p_dec->p_owner->b_cc_supported )
+ if( p_dec->p_owner->cc.b_supported )
{
int i;
for( i = 0; i < 4; i++ )
}
else
{
- DecoderDecode( p_dec, p_block );
+ DecoderProcess( p_dec, p_block );
}
}
}
vlc_mutex_lock( &p_owner->lock );
for( i = 0; i < 4; i++ )
- pb_present[i] = p_owner->pb_cc_present[i];
+ pb_present[i] = p_owner->cc.pb_present[i];
vlc_mutex_unlock( &p_owner->lock );
}
int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel )
//msg_Warn( p_dec, "input_DecoderSetCcState: %d @%d", b_decode, i_channel );
- if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )
+ if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
return VLC_EGENERIC;
if( b_decode )
p_cc->p_owner->p_clock = p_owner->p_clock;
vlc_mutex_lock( &p_owner->lock );
- p_owner->pp_cc[i_channel] = p_cc;
+ p_owner->cc.pp_decoder[i_channel] = p_cc;
vlc_mutex_unlock( &p_owner->lock );
}
else
decoder_t *p_cc;
vlc_mutex_lock( &p_owner->lock );
- p_cc = p_owner->pp_cc[i_channel];
- p_owner->pp_cc[i_channel] = NULL;
+ p_cc = p_owner->cc.pp_decoder[i_channel];
+ p_owner->cc.pp_decoder[i_channel] = NULL;
vlc_mutex_unlock( &p_owner->lock );
if( p_cc )
decoder_owner_sys_t *p_owner = p_dec->p_owner;
*pb_decode = false;
- if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )
+ if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
return VLC_EGENERIC;
vlc_mutex_lock( &p_owner->lock );
- *pb_decode = p_owner->pp_cc[i_channel] != NULL;
+ *pb_decode = p_owner->cc.pp_decoder[i_channel] != NULL;
vlc_mutex_unlock( &p_owner->lock );
return VLC_EGENERIC;
}
}
}
/* */
- p_owner->b_cc_supported = false;
+ p_owner->cc.b_supported = false;
if( i_object_type == VLC_OBJECT_DECODER )
{
if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )
- p_owner->b_cc_supported = true;
+ p_owner->cc.b_supported = true;
if( p_dec->pf_get_cc )
- p_owner->b_cc_supported = true;
+ p_owner->cc.b_supported = true;
}
vlc_mutex_init( &p_owner->lock );
p_owner->i_pause_date = 0;
for( i = 0; i < 4; i++ )
{
- p_owner->pb_cc_present[i] = false;
- p_owner->pp_cc[i] = NULL;
+ p_owner->cc.pb_present[i] = false;
+ p_owner->cc.pp_decoder[i] = NULL;
}
p_owner->i_ts_delay = 0;
return p_dec;
{
if( ( p_block = block_FifoGet( p_owner->p_fifo ) ) == NULL )
{
- p_dec->b_error = 1;
+ p_dec->b_error = true;
break;
}
- if( DecoderDecode( p_dec, p_block ) != VLC_SUCCESS )
+ if( DecoderProcess( p_dec, p_block ) != VLC_SUCCESS )
break;
}
if( !p_buffer->start_date && !p_buffer->end_date )
*pi_rate = input_clock_GetRate( p_clock );
- if( p_buffer->start_date )
+ if( p_buffer->start_date > 0 )
p_buffer->start_date =
input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_buffer->start_date + i_es_delay );
- if( p_buffer->end_date )
+ if( p_buffer->end_date > 0 )
p_buffer->end_date =
input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_buffer->end_date + i_es_delay );
if( !p_clock )
return;
- if( p_picture->date )
+ if( p_picture->date > 0 )
p_picture->date =
input_clock_GetTS( p_clock, pi_rate,
i_ts_delay, p_picture->date + i_es_delay );
if( !p_clock )
return;
- if( p_subpic->i_start )
+ if( p_subpic->i_start > 0 )
p_subpic->i_start =
input_clock_GetTS( p_clock, NULL,
i_ts_delay, p_subpic->i_start + i_es_delay );
- if( p_subpic->i_stop )
+ if( p_subpic->i_stop > 0 )
p_subpic->i_stop =
input_clock_GetTS( p_clock, NULL,
i_ts_delay, p_subpic->i_stop + i_es_delay );
assert( p_dec_cc->pf_get_cc != NULL );
/* Do not try retreiving CC if not wanted (sout) or cannot be retreived */
- if( !p_owner->b_cc_supported )
+ if( !p_owner->cc.b_supported )
return;
p_cc = p_dec_cc->pf_get_cc( p_dec_cc, pb_present );
vlc_mutex_lock( &p_owner->lock );
for( i = 0, i_cc_decoder = 0; i < 4; i++ )
{
- p_owner->pb_cc_present[i] |= pb_present[i];
- if( p_owner->pp_cc[i] )
+ p_owner->cc.pb_present[i] |= pb_present[i];
+ if( p_owner->cc.pp_decoder[i] )
i_cc_decoder++;
}
for( i = 0; i < 4; i++ )
{
- if( !p_owner->pp_cc[i] )
+ if( !p_owner->cc.pp_decoder[i] )
continue;
if( i_cc_decoder > 1 )
- DecoderDecode( p_owner->pp_cc[i], block_Duplicate( p_cc ) );
+ DecoderProcess( p_owner->cc.pp_decoder[i], block_Duplicate( p_cc ) );
else
- DecoderDecode( p_owner->pp_cc[i], p_cc );
+ DecoderProcess( p_owner->cc.pp_decoder[i], p_cc );
i_cc_decoder--;
}
vlc_mutex_unlock( &p_owner->lock );
}
}
-/**
- * Decode a block
- *
- * \param p_dec the decoder object
- * \param p_block the block to decode
- * \return VLC_SUCCESS or an error code
+/* This function process a block for sout
*/
-static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
+static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
{
decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
const bool b_telx = p_dec->fmt_in.i_codec == VLC_FOURCC('t','e','l','x');
+ block_t *p_sout_block;
- if( p_block && p_block->i_buffer <= 0 )
+ while( ( p_sout_block =
+ p_dec->pf_packetize( p_dec, p_block ? &p_block : NULL ) ) )
{
- block_Release( p_block );
- return VLC_SUCCESS;
- }
-
-#ifdef ENABLE_SOUT
- if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
- {
- block_t *p_sout_block;
-
- while( ( p_sout_block =
- p_dec->pf_packetize( p_dec, p_block ? &p_block : NULL ) ) )
+ if( !p_owner->p_sout_input )
{
- if( !p_owner->p_sout_input )
+ es_format_Copy( &p_owner->sout, &p_dec->fmt_out );
+
+ p_owner->sout.i_group = p_dec->fmt_in.i_group;
+ p_owner->sout.i_id = p_dec->fmt_in.i_id;
+ if( p_dec->fmt_in.psz_language )
{
- es_format_Copy( &p_owner->sout, &p_dec->fmt_out );
+ if( p_owner->sout.psz_language )
+ free( p_owner->sout.psz_language );
+ p_owner->sout.psz_language =
+ strdup( p_dec->fmt_in.psz_language );
+ }
- p_owner->sout.i_group = p_dec->fmt_in.i_group;
- p_owner->sout.i_id = p_dec->fmt_in.i_id;
- if( p_dec->fmt_in.psz_language )
- {
- if( p_owner->sout.psz_language )
- free( p_owner->sout.psz_language );
- p_owner->sout.psz_language =
- strdup( p_dec->fmt_in.psz_language );
- }
+ p_owner->p_sout_input =
+ sout_InputNew( p_owner->p_sout,
+ &p_owner->sout );
- p_owner->p_sout_input =
- sout_InputNew( p_owner->p_sout,
- &p_owner->sout );
+ if( p_owner->p_sout_input == NULL )
+ {
+ msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
+ (char *)&p_owner->sout.i_codec );
+ p_dec->b_error = true;
- if( p_owner->p_sout_input == NULL )
+ while( p_sout_block )
{
- msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
- (char *)&p_owner->sout.i_codec );
- p_dec->b_error = true;
-
- while( p_sout_block )
- {
- block_t *p_next = p_sout_block->p_next;
- block_Release( p_sout_block );
- p_sout_block = p_next;
- }
- break;
+ block_t *p_next = p_sout_block->p_next;
+ block_Release( p_sout_block );
+ p_sout_block = p_next;
}
+ break;
}
+ }
- while( p_sout_block )
- {
- block_t *p_next = p_sout_block->p_next;
+ while( p_sout_block )
+ {
+ block_t *p_next = p_sout_block->p_next;
- p_sout_block->p_next = NULL;
+ p_sout_block->p_next = NULL;
- DecoderWaitUnpause( p_dec );
+ DecoderWaitUnpause( p_dec );
- mtime_t i_ts_delay;
- mtime_t i_es_delay;
- DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
+ mtime_t i_ts_delay;
+ mtime_t i_es_delay;
+ DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
- DecoderSoutBufferFixTs( p_sout_block, p_owner->p_clock,
- i_ts_delay, i_es_delay, b_telx );
+ DecoderSoutBufferFixTs( p_sout_block, p_owner->p_clock,
+ i_ts_delay, i_es_delay, b_telx );
- sout_InputSendBuffer( p_owner->p_sout_input,
- p_sout_block );
+ sout_InputSendBuffer( p_owner->p_sout_input,
+ p_sout_block );
- p_sout_block = p_next;
- }
+ p_sout_block = p_next;
+ }
- /* For now it's enough, as only sout impact on this flag */
- if( p_owner->p_sout->i_out_pace_nocontrol > 0 &&
- p_owner->p_input->p->b_out_pace_control )
- {
- msg_Dbg( p_dec, "switching to sync mode" );
- p_owner->p_input->p->b_out_pace_control = false;
- }
- else if( p_owner->p_sout->i_out_pace_nocontrol <= 0 &&
- !p_owner->p_input->p->b_out_pace_control )
- {
- msg_Dbg( p_dec, "switching to async mode" );
- p_owner->p_input->p->b_out_pace_control = true;
- }
+ /* For now it's enough, as only sout impact on this flag */
+ if( p_owner->p_sout->i_out_pace_nocontrol > 0 &&
+ p_owner->p_input->p->b_out_pace_control )
+ {
+ msg_Dbg( p_dec, "switching to sync mode" );
+ p_owner->p_input->p->b_out_pace_control = false;
+ }
+ else if( p_owner->p_sout->i_out_pace_nocontrol <= 0 &&
+ !p_owner->p_input->p->b_out_pace_control )
+ {
+ msg_Dbg( p_dec, "switching to async mode" );
+ p_owner->p_input->p->b_out_pace_control = true;
}
}
- else
-#endif
- if( p_dec->fmt_in.i_cat == AUDIO_ES )
+}
+
+/* This function process a video block
+ */
+static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block )
+{
+ decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
+
+ if( p_block )
+ DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
+
+ if( p_owner->p_packetizer )
{
- if( p_block )
- DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
+ block_t *p_packetized_block;
+ decoder_t *p_packetizer = p_owner->p_packetizer;
- if( p_owner->p_packetizer )
+ while( (p_packetized_block =
+ p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
{
- block_t *p_packetized_block;
- decoder_t *p_packetizer = p_owner->p_packetizer;
-
- while( (p_packetized_block =
- p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
+ if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
{
- if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
- {
- es_format_Clean( &p_dec->fmt_in );
- es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
- }
+ es_format_Clean( &p_dec->fmt_in );
+ es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
+ }
+ if( p_packetizer->pf_get_cc )
+ DecoderGetCc( p_dec, p_packetizer );
- while( p_packetized_block )
- {
- block_t *p_next = p_packetized_block->p_next;
- p_packetized_block->p_next = NULL;
+ while( p_packetized_block )
+ {
+ block_t *p_next = p_packetized_block->p_next;
+ p_packetized_block->p_next = NULL;
- DecoderDecodeAudio( p_dec, p_packetized_block );
+ DecoderDecodeVideo( p_dec, p_packetized_block );
- p_packetized_block = p_next;
- }
+ p_packetized_block = p_next;
}
}
- else if( p_block )
- {
- DecoderDecodeAudio( p_dec, p_block );
- }
}
- else if( p_dec->fmt_in.i_cat == VIDEO_ES )
+ else if( p_block )
{
- if( p_block )
- DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
+ DecoderDecodeVideo( p_dec, p_block );
+ }
+}
- if( p_owner->p_packetizer )
- {
- block_t *p_packetized_block;
- decoder_t *p_packetizer = p_owner->p_packetizer;
+/* This function process a audio block
+ */
+static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block )
+{
+ decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
+ if( p_block )
+ DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
+
+ if( p_owner->p_packetizer )
+ {
+ block_t *p_packetized_block;
+ decoder_t *p_packetizer = p_owner->p_packetizer;
- while( (p_packetized_block =
- p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
+ while( (p_packetized_block =
+ p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
+ {
+ if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
{
- if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
- {
- es_format_Clean( &p_dec->fmt_in );
- es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
- }
- if( p_packetizer->pf_get_cc )
- DecoderGetCc( p_dec, p_packetizer );
+ es_format_Clean( &p_dec->fmt_in );
+ es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
+ }
- while( p_packetized_block )
- {
- block_t *p_next = p_packetized_block->p_next;
- p_packetized_block->p_next = NULL;
+ while( p_packetized_block )
+ {
+ block_t *p_next = p_packetized_block->p_next;
+ p_packetized_block->p_next = NULL;
- DecoderDecodeVideo( p_dec, p_packetized_block );
+ DecoderDecodeAudio( p_dec, p_packetized_block );
- p_packetized_block = p_next;
- }
+ p_packetized_block = p_next;
}
}
- else if( p_block )
- {
- DecoderDecodeVideo( p_dec, p_block );
- }
}
- else if( p_dec->fmt_in.i_cat == SPU_ES )
+ else if( p_block )
{
- input_thread_t *p_input = p_owner->p_input;
- vout_thread_t *p_vout;
- subpicture_t *p_spu;
- bool b_flushing = p_owner->i_preroll_end == INT64_MAX;
- bool b_flush = false;
+ DecoderDecodeAudio( p_dec, p_block );
+ }
+}
- if( p_block )
- {
- DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
- b_flush = (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH) != 0;
- }
+/* This function process a subtitle block
+ */
+static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block )
+{
+ decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
+ const bool b_telx = p_dec->fmt_in.i_codec == VLC_FOURCC('t','e','l','x');
- if( !b_flushing && b_flush && p_owner->p_spu_vout )
- {
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ input_thread_t *p_input = p_owner->p_input;
+ vout_thread_t *p_vout;
+ subpicture_t *p_spu;
+ bool b_flushing = p_owner->i_preroll_end == INT64_MAX;
+ bool b_flush = false;
- if( p_vout && p_owner->p_spu_vout == p_vout )
- spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
- p_owner->i_spu_channel );
+ if( p_block )
+ {
+ DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
+ b_flush = (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH) != 0;
+ }
- if( p_vout )
- vlc_object_release( p_vout );
- }
+ if( !b_flushing && b_flush && p_owner->p_spu_vout )
+ {
+ p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
- while( (p_spu = p_dec->pf_decode_sub( p_dec, p_block ? &p_block : NULL ) ) )
- {
- vlc_mutex_lock( &p_input->p->counters.counters_lock );
- stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
- vlc_mutex_unlock( &p_input->p->counters.counters_lock );
+ if( p_vout && p_owner->p_spu_vout == p_vout )
+ spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
+ p_owner->i_spu_channel );
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
- if( p_vout && p_owner->p_spu_vout == p_vout )
- {
- /* Preroll does not work very well with subtitle */
- if( p_spu->i_start > 0 &&
- p_spu->i_start < p_owner->i_preroll_end &&
- ( p_spu->i_stop <= 0 || p_spu->i_stop < p_owner->i_preroll_end ) )
- {
- subpicture_Delete( p_spu );
- }
- else
- {
- DecoderWaitUnpause( p_dec );
+ if( p_vout )
+ vlc_object_release( p_vout );
+ }
- mtime_t i_ts_delay;
- mtime_t i_es_delay;
- DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
+ while( (p_spu = p_dec->pf_decode_sub( p_dec, p_block ? &p_block : NULL ) ) )
+ {
+ vlc_mutex_lock( &p_input->p->counters.counters_lock );
+ stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
+ vlc_mutex_unlock( &p_input->p->counters.counters_lock );
- DecoderSpuBufferFixTs( p_spu, p_owner->p_clock, i_ts_delay, i_es_delay, b_telx );
- spu_DisplaySubpicture( p_vout->p_spu, p_spu );
- }
+ p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ if( p_vout && p_owner->p_spu_vout == p_vout )
+ {
+ /* Preroll does not work very well with subtitle */
+ if( p_spu->i_start > 0 &&
+ p_spu->i_start < p_owner->i_preroll_end &&
+ ( p_spu->i_stop <= 0 || p_spu->i_stop < p_owner->i_preroll_end ) )
+ {
+ subpicture_Delete( p_spu );
}
else
{
- msg_Warn( p_dec, "no vout found, leaking subpicture" );
+ DecoderWaitUnpause( p_dec );
+
+ mtime_t i_ts_delay;
+ mtime_t i_es_delay;
+ DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
+
+ DecoderSpuBufferFixTs( p_spu, p_owner->p_clock, i_ts_delay, i_es_delay, b_telx );
+ spu_DisplaySubpicture( p_vout->p_spu, p_spu );
}
- if( p_vout )
- vlc_object_release( p_vout );
}
+ else
+ {
+ msg_Warn( p_dec, "no vout found, leaking subpicture" );
+ }
+ if( p_vout )
+ vlc_object_release( p_vout );
+ }
+}
+
+/**
+ * Decode a block
+ *
+ * \param p_dec the decoder object
+ * \param p_block the block to decode
+ * \return VLC_SUCCESS or an error code
+ */
+static int DecoderProcess( decoder_t *p_dec, block_t *p_block )
+{
+ if( p_block && p_block->i_buffer <= 0 )
+ {
+ block_Release( p_block );
+ return VLC_SUCCESS;
+ }
+
+#ifdef ENABLE_SOUT
+ if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
+ {
+ DecoderProcessSout( p_dec, p_block );
+ }
+ else
+#endif
+ if( p_dec->fmt_in.i_cat == AUDIO_ES )
+ {
+ DecoderProcessAudio( p_dec, p_block );
+ }
+ else if( p_dec->fmt_in.i_cat == VIDEO_ES )
+ {
+ DecoderProcessVideo( p_dec, p_block );
+ }
+ else if( p_dec->fmt_in.i_cat == SPU_ES )
+ {
+ DecoderProcessSpu( p_dec, p_block );
}
else
{
msg_Err( p_dec, "unknown ES format" );
- p_dec->b_error = 1;
+ p_dec->b_error = true;
}
return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;