#include "input_internal.h"
#include "clock.h"
#include "decoder.h"
+#include "event.h"
#include "../video_output/vout_control.h"
static void DeleteDecoder( decoder_t * );
static void *DecoderThread( vlc_object_t * );
-static int DecoderProcess( decoder_t *, block_t * );
+static void DecoderProcess( decoder_t *, block_t * );
+static void DecoderError( decoder_t *p_dec, block_t *p_block );
static void DecoderOutputChangePause( decoder_t *, bool b_paused, mtime_t i_date );
static void DecoderFlush( decoder_t * );
static void DecoderSignalBuffering( decoder_t *, bool );
audio_format_t audio;
es_format_t sout;
+ /* */
+ bool b_fmt_description;
+ es_format_t fmt_description;
+
/* fifo */
block_fifo_t *p_fifo;
vlc_object_kill( p_dec );
- /* Make sure we aren't paused anymore */
+ /* Make sure we aren't paused/buffering/waiting anymore */
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_paused || p_owner->b_buffering )
- {
- p_owner->b_paused = false;
- p_owner->b_buffering = false;
- vlc_cond_signal( &p_owner->wait );
- }
+ p_owner->b_paused = false;
+ p_owner->b_buffering = false;
+ p_owner->b_flushing = true;
+ vlc_cond_signal( &p_owner->wait );
vlc_mutex_unlock( &p_owner->lock );
vlc_thread_join( p_dec );
if( p_owner->p_input->p->b_out_pace_control )
{
- block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
+ /* The fifo is not consummed when buffering and so will
+ * deadlock vlc.
+ * There is no need to lock as b_buffering is never modify
+ * inside decoder thread. */
+ if( !p_owner->b_buffering )
+ block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
}
else if( block_FifoSize( p_owner->p_fifo ) > 50000000 /* 50 MB */ )
{
vlc_mutex_unlock( &p_owner->lock );
}
+
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_unlock( &p_owner->lock );
}
+bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+ bool b_changed;
+
+ vlc_mutex_lock( &p_owner->lock );
+ b_changed = p_owner->b_fmt_description;
+ if( b_changed )
+ {
+ if( p_fmt )
+ es_format_Copy( p_fmt, &p_owner->fmt_description );
+ p_owner->b_fmt_description = false;
+ }
+ vlc_mutex_unlock( &p_owner->lock );
+ return b_changed;
+}
+
/*****************************************************************************
* Internal functions
*****************************************************************************/
vlc_mutex_init( &p_owner->lock );
vlc_cond_init( &p_owner->wait );
+ p_owner->b_fmt_description = false;
+ es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 );
+
p_owner->b_paused = false;
p_owner->pause.i_date = 0;
p_owner->pause.i_ignore = 0;
if( p_block )
{
+ int canc = vlc_savecancel();
+
if( p_dec->b_error )
- block_Release( p_block );
+ DecoderError( p_dec, p_block );
else
DecoderProcess( p_dec, p_block );
+
+ vlc_restorecancel( canc );
}
}
i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
b_reject = true;
- if( !b_reject )
+ /* Do not wait against unprotected date */
+ const mtime_t i_deadline = p_audio->start_date - AOUT_MAX_PREPARE_TIME;
+ while( !b_reject && i_deadline > mdate() )
{
- /* Wait if we are too early
- * FIXME that's plain ugly to do it here */
- mwait( p_audio->start_date - AOUT_MAX_PREPARE_TIME );
+ vlc_mutex_lock( &p_owner->lock );
+ if( p_owner->b_flushing || p_dec->b_die )
+ {
+ b_reject = true;
+ vlc_mutex_unlock( &p_owner->lock );
+ break;
+ }
+ vlc_cond_timedwait( &p_owner->wait, &p_owner->lock, i_deadline );
+ vlc_mutex_unlock( &p_owner->lock );
+ }
+ if( !b_reject )
+ {
if( !aout_DecPlay( p_aout, p_aout_input, p_audio, i_rate ) )
*pi_played_sum += 1;
*pi_lost_sum += aout_DecGetResetLost( p_aout, p_aout_input );
}
}
+/* */
+static void DecoderProcessOnFlush( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ vlc_mutex_lock( &p_owner->lock );
+ DecoderFlushBuffering( p_dec );
+ vlc_mutex_unlock( &p_owner->lock );
+
+ DecoderSignalFlushed( p_dec );
+}
/**
* Decode a block
*
* \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 )
+static void DecoderProcess( 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_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);
{
assert( !b_flush_request );
block_Release( p_block );
- return VLC_SUCCESS;
+ return;
}
- int canc = vlc_savecancel();
#ifdef ENABLE_SOUT
if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
{
/* */
if( b_flush_request )
- {
- vlc_mutex_lock( &p_owner->lock );
- DecoderFlushBuffering( p_dec );
- vlc_mutex_unlock( &p_owner->lock );
+ DecoderProcessOnFlush( p_dec );
+}
- DecoderSignalFlushed( p_dec );
- }
- vlc_restorecancel( canc );
+static void DecoderError( decoder_t *p_dec, block_t *p_block )
+{
+ const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);
- return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
+ /* */
+ if( p_block )
+ block_Release( p_block );
+
+ if( b_flush_request )
+ DecoderProcessOnFlush( p_dec );
}
+
/**
* Destroys a decoder object
*
/* We are about to die. Reattach video output to p_vlc. */
vout_Request( p_dec, p_owner->p_vout, NULL );
- var_SetBool( p_owner->p_input, "intf-change-vout", true );
+ input_SendEventVout( p_owner->p_input );
}
#ifdef ENABLE_SOUT
vlc_object_release( p_owner->p_packetizer );
}
+ es_format_Clean( &p_owner->fmt_description );
+
vlc_cond_destroy( &p_owner->wait );
vlc_mutex_destroy( &p_owner->lock );
/*****************************************************************************
* Buffers allocation callbacks for the decoders
*****************************************************************************/
+static void DecoderUpdateFormatLocked( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ vlc_assert_locked( &p_owner->lock );
+
+ es_format_Clean( &p_owner->fmt_description );
+
+ p_owner->b_fmt_description = true;
+ es_format_Copy( &p_owner->fmt_description, &p_dec->fmt_out );
+}
+static vout_thread_t *aout_request_vout( void *p_private,
+ vout_thread_t *p_vout, video_format_t *p_fmt )
+{
+ decoder_t *p_dec = p_private;
+
+ p_vout = vout_Request( p_dec, p_vout, p_fmt );
+ input_SendEventVout( p_dec->p_owner->p_input );
+
+ return p_vout;
+}
+
static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
audio_sample_format_t format;
aout_input_t *p_aout_input;
aout_instance_t *p_aout;
+ aout_request_vout_t request_vout;
p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
p_owner->audio = p_dec->fmt_out.audio;
}
}
+ request_vout.pf_request_vout = aout_request_vout;
+ request_vout.p_private = p_dec;
+
p_aout = p_owner->p_aout;
p_aout_input = aout_DecNew( p_dec, &p_aout,
- &format, &p_dec->fmt_out.audio_replay_gain );
+ &format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
vlc_mutex_lock( &p_owner->lock );
+
p_owner->p_aout = p_aout;
p_owner->p_aout_input = p_aout_input;
+ DecoderUpdateFormatLocked( p_dec );
+
vlc_mutex_unlock( &p_owner->lock );
if( p_owner->p_aout_input == NULL )
vlc_mutex_lock( &p_owner->lock );
p_owner->p_vout = p_vout;
+
+ DecoderUpdateFormatLocked( p_dec );
+
vlc_mutex_unlock( &p_owner->lock );
- var_SetBool( p_owner->p_input, "intf-change-vout", true );
+ input_SendEventVout( p_owner->p_input );
if( p_vout == NULL )
{
msg_Err( p_dec, "failed to create video output" );