#include <vlc_sout.h>
#include <vlc_codec.h>
#include <vlc_osd.h>
+#include <vlc_meta.h>
#include <vlc_interface.h>
#include "audio_output/aout_internal.h"
#include "input_internal.h"
#include "clock.h"
#include "decoder.h"
+#include "event.h"
+#include "ressource.h"
-#include "../video_output/vout_internal.h"
+#include "../video_output/vout_control.h"
static decoder_t *CreateDecoder( input_thread_t *, es_format_t *, int, sout_instance_t *p_sout );
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;
+ vlc_meta_t *p_description;
+
/* fifo */
block_fifo_t *p_fifo;
struct
{
mtime_t i_date;
+ int i_ignore;
} pause;
/* Buffering */
aout_buffer_t *p_audio;
aout_buffer_t **pp_audio_next;
+
+ block_t *p_block;
+ block_t **pp_block_next;
} buffer;
/* Flushing */
#define DECODER_MAX_BUFFERING_AUDIO_DURATION (AOUT_MAX_PREPARE_TIME)
#define DECODER_MAX_BUFFERING_VIDEO_DURATION (1*CLOCK_FREQ)
+/* Pictures which are DECODER_BOGUS_VIDEO_DELAY or more in advance probably have
+ * a bogus PTS and won't be displayed */
+#define DECODER_BOGUS_VIDEO_DELAY ((mtime_t)(DEFAULT_PTS_DELAY * 30))
+
+/* */
+#define DECODER_SPU_VOUT_WAIT_DURATION ((int)(0.200*CLOCK_FREQ))
+
+
/*****************************************************************************
* Public functions
*****************************************************************************/
+picture_t *decoder_NewPicture( decoder_t *p_decoder )
+{
+ picture_t *p_picture = p_decoder->pf_vout_buffer_new( p_decoder );
+ if( !p_picture )
+ msg_Warn( p_decoder, "can't get output picture" );
+ return p_picture;
+}
+void decoder_DeletePicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+ p_decoder->pf_vout_buffer_del( p_decoder, p_picture );
+}
+void decoder_LinkPicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+ p_decoder->pf_picture_link( p_decoder, p_picture );
+}
+void decoder_UnlinkPicture( decoder_t *p_decoder, picture_t *p_picture )
+{
+ p_decoder->pf_picture_unlink( p_decoder, p_picture );
+}
-/* decoder_GetInputAttachment:
- */
-input_attachment_t *decoder_GetInputAttachment( decoder_t *p_dec,
- const char *psz_name )
+aout_buffer_t *decoder_NewAudioBuffer( decoder_t *p_decoder, int i_size )
{
- input_attachment_t *p_attachment;
- if( input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENT, &p_attachment, psz_name ) )
+ if( !p_decoder->pf_aout_buffer_new )
return NULL;
- return p_attachment;
+ return p_decoder->pf_aout_buffer_new( p_decoder, i_size );
}
+void decoder_DeleteAudioBuffer( decoder_t *p_decoder, aout_buffer_t *p_buffer )
+{
+ p_decoder->pf_aout_buffer_del( p_decoder, p_buffer );
+}
+
+subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder )
+{
+ subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder );
+ if( !p_subpicture )
+ msg_Warn( p_decoder, "can't get output subpicture" );
+ return p_subpicture;
+}
+void decoder_DeleteSubpicture( decoder_t *p_decoder, subpicture_t *p_subpicture )
+{
+ p_decoder->pf_spu_buffer_del( p_decoder, p_subpicture );
+}
+
/* decoder_GetInputAttachments:
*/
int decoder_GetInputAttachments( decoder_t *p_dec,
input_attachment_t ***ppp_attachment,
int *pi_attachment )
{
- return input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENTS,
- ppp_attachment, pi_attachment );
+ if( !p_dec->pf_get_attachments )
+ return VLC_EGENERIC;
+
+ return p_dec->pf_get_attachments( p_dec, ppp_attachment, pi_attachment );
}
/* decoder_GetDisplayDate:
*/
mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
-
- vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_buffering )
- i_ts = 0;
- vlc_mutex_unlock( &p_owner->lock );
+ if( !p_dec->pf_get_display_date )
+ return 0;
- if( !p_owner->p_clock || !i_ts )
- return i_ts;
-
- return input_clock_GetTS( p_owner->p_clock, NULL, p_owner->p_input->i_pts_delay, i_ts );
+ return p_dec->pf_get_display_date( p_dec, i_ts );
}
/* decoder_GetDisplayRate:
*/
int decoder_GetDisplayRate( decoder_t *p_dec )
{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
-
- if( !p_owner->p_clock )
+ if( !p_dec->pf_get_display_rate )
return INPUT_RATE_DEFAULT;
- return input_clock_GetRate( p_owner->p_clock );
+
+ return p_dec->pf_get_display_rate( p_dec );
}
/**
decoder_t *p_dec = NULL;
int i_priority;
-#ifndef ENABLE_SOUT
- (void)b_force_decoder;
-#else
+#ifdef ENABLE_SOUT
/* If we are in sout mode, search for packetizer module */
if( p_sout )
{
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 );
- /* Make sure the thread leaves the function */
- block_FifoWake( p_owner->p_fifo );
-
vlc_thread_join( p_dec );
-
- /* Don't module_unneed() here because of the dll loader that wants
- * close() in the same thread than open()/decode() */
+ module_unneed( p_dec, p_dec->p_module );
/* */
if( p_dec->p_owner->cc.b_supported )
/**
* Put a block_t in the decoder's fifo.
+ * Thread-safe w.r.t. the decoder. May be a cancellation point.
*
* \param p_dec the decoder object
* \param p_block the data block
if( p_owner->p_input->p->b_out_pace_control )
{
- /* FIXME !!!!! */
- while( vlc_object_alive( p_dec ) && !p_dec->b_error &&
- block_FifoCount( p_owner->p_fifo ) > 10 )
- {
- msleep( 1000 );
- }
+ /* 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 */ )
{
/* FIXME: ideally we would check the time amount of data
- * in the fifo instead of its size. */
+ * in the FIFO instead of its size. */
msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
"consumed quickly enough), resetting fifo!" );
block_FifoEmpty( p_owner->p_fifo );
p_owner->b_paused = b_paused;
p_owner->pause.i_date = i_date;
+ p_owner->pause.i_ignore = 0;
vlc_cond_signal( &p_owner->wait );
DecoderOutputChangePause( p_dec, b_paused, i_date );
p_owner->buffer.b_full = false;
p_owner->buffer.i_count = 0;
- assert( !p_owner->buffer.p_picture && !p_owner->buffer.p_subpic && !p_owner->buffer.p_audio );
+ assert( !p_owner->buffer.p_picture && !p_owner->buffer.p_subpic &&
+ !p_owner->buffer.p_audio && !p_owner->buffer.p_block );
p_owner->buffer.p_picture = NULL;
p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
p_owner->buffer.p_audio = NULL;
p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
+ p_owner->buffer.p_block = NULL;
+ p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
+
+
p_owner->b_buffering = true;
vlc_cond_signal( &p_owner->wait );
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;
+
+ *pi_duration = 0;
+
+ vlc_mutex_lock( &p_owner->lock );
+ if( p_dec->fmt_in.i_cat == VIDEO_ES )
+ {
+ if( p_owner->b_paused && p_owner->p_vout )
+ {
+ vout_NextPicture( p_owner->p_vout, pi_duration );
+ p_owner->pause.i_ignore++;
+ vlc_cond_signal( &p_owner->wait );
+ }
+ }
+ else
+ {
+ /* TODO subtitle should not be flushed */
+ DecoderFlush( p_dec );
+ }
+ vlc_mutex_unlock( &p_owner->lock );
+}
+
+bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_meta_t **pp_meta )
+{
+ 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 );
+
+ if( pp_meta )
+ {
+ *pp_meta = NULL;
+ if( p_owner->p_description )
+ {
+ *pp_meta = vlc_meta_New();
+ if( *pp_meta )
+ vlc_meta_Merge( *pp_meta, p_owner->p_description );
+ }
+ }
+ p_owner->b_fmt_description = false;
+ }
+ vlc_mutex_unlock( &p_owner->lock );
+ return b_changed;
+}
+
/*****************************************************************************
* Internal functions
*****************************************************************************/
+static int DecoderGetInputAttachments( decoder_t *p_dec,
+ input_attachment_t ***ppp_attachment,
+ int *pi_attachment )
+{
+ return input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENTS,
+ ppp_attachment, pi_attachment );
+}
+static mtime_t DecoderGetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ vlc_mutex_lock( &p_owner->lock );
+ if( p_owner->b_buffering || p_owner->b_paused )
+ i_ts = 0;
+ vlc_mutex_unlock( &p_owner->lock );
+
+ if( !p_owner->p_clock || !i_ts )
+ return i_ts;
+
+ return input_clock_GetTS( p_owner->p_clock, NULL, p_owner->p_input->i_pts_delay, i_ts );
+}
+static int DecoderGetDisplayRate( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ if( !p_owner->p_clock )
+ return INPUT_RATE_DEFAULT;
+ return input_clock_GetRate( p_owner->p_clock );
+}
/* */
static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
p_dec->pf_get_cc = NULL;
p_dec->pf_packetize = NULL;
- /* Initialize the decoder fifo */
+ /* Initialize the decoder */
p_dec->p_module = NULL;
memset( &null_es_format, 0, sizeof(es_format_t) );
es_format_Copy( &p_dec->fmt_in, fmt );
es_format_Copy( &p_dec->fmt_out, &null_es_format );
+ p_dec->p_description = NULL;
+
/* Allocate our private structure for the decoder */
p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );
if( p_dec->p_owner == NULL )
p_dec->pf_picture_unlink = vout_unlink_picture;
p_dec->pf_spu_buffer_new = spu_new_buffer;
p_dec->pf_spu_buffer_del = spu_del_buffer;
+ /* */
+ p_dec->pf_get_attachments = DecoderGetInputAttachments;
+ p_dec->pf_get_display_date = DecoderGetDisplayDate;
+ p_dec->pf_get_display_rate = DecoderGetDisplayRate;
vlc_object_attach( p_dec, p_input );
/* Find a suitable decoder/packetizer module */
if( i_object_type == VLC_OBJECT_DECODER )
- p_dec->p_module = module_need( p_dec, "decoder", "$codec", 0 );
+ p_dec->p_module = module_need( p_dec, "decoder", "$codec", false );
else
- p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", 0 );
+ p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", false );
/* Check if decoder requires already packetized data */
if( i_object_type == VLC_OBJECT_DECODER &&
p_dec->p_owner->p_packetizer->p_module =
module_need( p_dec->p_owner->p_packetizer,
- "packetizer", "$packetizer", 0 );
+ "packetizer", "$packetizer", false );
if( !p_dec->p_owner->p_packetizer->p_module )
{
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->p_description = NULL;
+
p_owner->b_paused = false;
p_owner->pause.i_date = 0;
+ p_owner->pause.i_ignore = 0;
p_owner->b_buffering = false;
p_owner->buffer.b_first = true;
p_owner->buffer.p_picture = NULL;
p_owner->buffer.p_subpic = NULL;
p_owner->buffer.p_audio = NULL;
+ p_owner->buffer.p_block = NULL;
p_owner->b_flushing = false;
decoder_t *p_dec = (decoder_t *)p_this;
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- int canc = vlc_savecancel();
-
/* The decoder's main loop */
- while( vlc_object_alive( p_dec ) && !p_dec->b_error )
+ for( ;; )
{
block_t *p_block = block_FifoGet( p_owner->p_fifo );
+ /* Make sure there is no cancellation point other than this one^^.
+ * If you need one, be sure to push cleanup of p_block. */
DecoderSignalBuffering( p_dec, p_block == NULL );
- if( p_block && DecoderProcess( p_dec, p_block ) != VLC_SUCCESS )
- break;
- }
-
- while( vlc_object_alive( p_dec ) )
- {
- block_t *p_block = block_FifoGet( p_owner->p_fifo );
+ if( p_block )
+ {
+ int canc = vlc_savecancel();
- DecoderSignalBuffering( p_dec, p_block == NULL );
+ if( p_dec->b_error )
+ DecoderError( p_dec, p_block );
+ else
+ DecoderProcess( p_dec, p_block );
- /* Trash all received PES packets */
- if( p_block )
- block_Release( p_block );
+ vlc_restorecancel( canc );
+ }
+ /* Ensure fast cancellation in case the fifo is not empty */
+ vlc_testcancel();
}
- DecoderSignalBuffering( p_dec, true );
-
- /* We do it here because of the dll loader that wants close() in the
- * same thread than open()/decode() */
- module_unneed( p_dec, p_dec->p_module );
- vlc_restorecancel( canc );
return NULL;
}
while( !p_owner->b_flushing )
{
- if( p_owner->b_paused && p_owner->b_buffering && !p_owner->buffer.b_full )
- break;
-
- if( !p_owner->b_paused && ( !p_owner->b_buffering || !p_owner->buffer.b_full ) )
- break;
-
+ if( p_owner->b_paused )
+ {
+ if( p_owner->b_buffering && !p_owner->buffer.b_full )
+ break;
+ if( p_owner->pause.i_ignore > 0 )
+ {
+ p_owner->pause.i_ignore--;
+ break;
+ }
+ }
+ else
+ {
+ if( !p_owner->b_buffering || !p_owner->buffer.b_full )
+ break;
+ }
vlc_cond_wait( &p_owner->wait, &p_owner->lock );
}
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 );
{
aout_instance_t *p_aout = p_owner->p_aout;
aout_input_t *p_aout_input = p_owner->p_aout_input;
- int i_lost = 0;
- int i_played;
if( p_dec->b_die )
{
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vout_thread_t *p_vout = p_owner->p_vout;
+ bool b_first_buffered;
if( p_picture->date <= 0 )
{
vlc_cond_signal( &p_owner->wait );
}
}
+ b_first_buffered = p_owner->buffer.p_picture != NULL;
- for( ;; )
+ for( ;; b_first_buffered = false )
{
bool b_has_more = false;
bool b_reject;
+
DecoderWaitUnblock( p_dec, &b_reject );
if( p_owner->b_buffering && !p_owner->buffer.b_first )
}
/* */
- int i_rate = INPUT_RATE_DEFAULT;
- mtime_t i_delay;
-
if( b_buffering_first )
{
assert( p_owner->buffer.b_first );
assert( !p_owner->buffer.i_count );
msg_Dbg( p_dec, "Received first picture" );
p_owner->buffer.b_first = false;
- p_picture->date = mdate();
p_picture->b_force = true;
- i_delay = 0;
- if( p_owner->p_clock )
- i_rate = input_clock_GetRate( p_owner->p_clock );
- }
- else
- {
- DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
- &i_rate, &i_delay, false );
}
+ int i_rate = INPUT_RATE_DEFAULT;
+ mtime_t i_delay;
+ DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
+ &i_rate, &i_delay, false );
+
vlc_mutex_unlock( &p_owner->lock );
/* */
- const mtime_t i_max_date = mdate() + i_delay + VOUT_BOGUS_DELAY;
+ const mtime_t i_max_date = mdate() + i_delay + DECODER_BOGUS_VIDEO_DELAY;
- if( p_picture->date <= 0 || p_picture->date >= i_max_date )
+ if( !p_picture->b_force && ( p_picture->date <= 0 || p_picture->date >= i_max_date ) )
b_reject = true;
if( !b_reject )
{
- if( i_rate != p_owner->i_last_rate )
+ if( i_rate != p_owner->i_last_rate || b_first_buffered )
{
/* Be sure to not display old picture after our own */
vout_Flush( p_vout, p_picture->date );
p_owner->i_last_rate = i_rate;
}
-
- vout_DatePicture( p_vout, p_picture, p_picture->date );
-
vout_DisplayPicture( p_vout, p_picture );
}
else
decoder_owner_sys_t *p_owner = p_dec->p_owner;
assert( p_owner->p_clock );
+ assert( !p_sout_block->p_next );
vlc_mutex_lock( &p_owner->lock );
- bool b_reject;
- DecoderWaitUnblock( p_dec, &b_reject );
+ if( p_owner->b_buffering || p_owner->buffer.p_block )
+ {
+ block_ChainLastAppend( &p_owner->buffer.pp_block_next, p_sout_block );
- DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts, &p_sout_block->i_length,
- &p_sout_block->i_rate, NULL, b_telx );
+ p_owner->buffer.i_count++;
+ /* XXX it is important to be full after the first one */
+ if( p_owner->buffer.i_count > 0 )
+ {
+ p_owner->buffer.b_full = true;
+ vlc_cond_signal( &p_owner->wait );
+ }
+ }
- vlc_mutex_unlock( &p_owner->lock );
+ for( ;; )
+ {
+ bool b_has_more = false;
+ bool b_reject;
+ DecoderWaitUnblock( p_dec, &b_reject );
+
+ if( p_owner->b_buffering )
+ {
+ vlc_mutex_unlock( &p_owner->lock );
+ return;
+ }
+
+ /* */
+ if( p_owner->buffer.p_block )
+ {
+ p_sout_block = p_owner->buffer.p_block;
+
+ p_owner->buffer.p_block = p_sout_block->p_next;
+ p_owner->buffer.i_count--;
+
+ b_has_more = p_owner->buffer.p_block != NULL;
+ if( !b_has_more )
+ p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
+ }
+ p_sout_block->p_next = NULL;
+
+ DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
+ &p_sout_block->i_length,
+ &p_sout_block->i_rate, NULL, b_telx );
+
+ vlc_mutex_unlock( &p_owner->lock );
- sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
+ if( !b_reject )
+ sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
+ else
+ block_Release( p_sout_block );
+
+ if( !b_has_more )
+ break;
+ vlc_mutex_lock( &p_owner->lock );
+ if( !p_owner->buffer.p_block )
+ {
+ vlc_mutex_unlock( &p_owner->lock );
+ break;
+ }
+ }
}
/* */
if( !p_owner->buffer.p_subpic )
p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
}
+ if( p_owner->buffer.p_block )
+ {
+ block_ChainRelease( p_owner->buffer.p_block );
+
+ p_owner->buffer.i_count = 0;
+ p_owner->buffer.p_block = NULL;
+ p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
+ }
}
/* This function process a block for sout
stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
vlc_mutex_unlock( &p_input->p->counters.counters_lock );
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
if( p_vout && p_owner->p_spu_vout == p_vout )
{
/* Preroll does not work very well with subtitle */
if( b_flush && p_owner->p_spu_vout )
{
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
if( p_vout && p_owner->p_spu_vout == p_vout )
spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
}
}
+/* */
+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;
}
#ifdef ENABLE_SOUT
/* */
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 );
- }
+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
*
aout_DecDelete( p_owner->p_aout, p_owner->p_aout_input );
if( p_owner->p_aout )
{
- vlc_object_release( p_owner->p_aout );
+ input_ressource_RequestAout( p_owner->p_input->p->p_ressource,
+ p_owner->p_aout );
+ input_SendEventAout( p_owner->p_input );
p_owner->p_aout = NULL;
}
if( p_owner->p_vout )
{
/* Hack to make sure all the the pictures are freed by the decoder */
- for( int 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 );
- }
+ vout_FixLeaks( p_owner->p_vout, true );
- /* 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_ressource_RequestVout( p_owner->p_input->p->p_ressource, p_owner->p_vout, NULL );
+ input_SendEventVout( p_owner->p_input );
}
#ifdef ENABLE_SOUT
{
vout_thread_t *p_vout;
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
- if( p_vout && p_owner->p_spu_vout == p_vout )
+ p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
+ if( p_vout )
{
- spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
- p_owner->i_spu_channel );
+ if( p_owner->p_spu_vout == p_vout )
+ spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, p_owner->i_spu_channel );
vlc_object_release( p_vout );
}
}
es_format_Clean( &p_dec->fmt_in );
es_format_Clean( &p_dec->fmt_out );
+ if( p_dec->p_description )
+ vlc_meta_Delete( p_dec->p_description );
+ es_format_Clean( &p_owner->fmt_description );
+ if( p_owner->p_description )
+ vlc_meta_Delete( p_owner->p_description );
if( p_owner->p_packetizer )
{
p_owner->p_packetizer->p_module );
es_format_Clean( &p_owner->p_packetizer->fmt_in );
es_format_Clean( &p_owner->p_packetizer->fmt_out );
+ if( p_owner->p_packetizer->p_description )
+ vlc_meta_Delete( p_owner->p_packetizer->p_description );
vlc_object_detach( p_owner->p_packetizer );
vlc_object_release( p_owner->p_packetizer );
}
/*****************************************************************************
* 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 );
+
+ p_owner->b_fmt_description = true;
+
+ /* Copy es_format */
+ es_format_Clean( &p_owner->fmt_description );
+ es_format_Copy( &p_owner->fmt_description, &p_dec->fmt_out );
+
+ /* Move p_description */
+ if( p_owner->p_description && p_dec->p_description )
+ vlc_meta_Delete( p_owner->p_description );
+ p_owner->p_description = p_dec->p_description;
+ p_dec->p_description = NULL;
+}
+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 = input_ressource_RequestVout( p_dec->p_owner->p_input->p->p_ressource, 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;
memcpy( &format, &p_owner->audio, sizeof( audio_sample_format_t ) );
- if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK)
- == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
+ if( i_force_dolby &&
+ (format.i_original_channels&AOUT_CHAN_PHYSMASK) ==
+ (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
{
- if ( i_force_dolby == 1 )
+ if( i_force_dolby == 1 )
{
format.i_original_channels = format.i_original_channels |
AOUT_CHAN_DOLBYSTEREO;
}
}
+ request_vout.pf_request_vout = aout_request_vout;
+ request_vout.p_private = p_dec;
+
p_aout = p_owner->p_aout;
+ if( !p_aout )
+ p_aout = input_ressource_RequestAout( p_owner->p_input->p->p_ressource, NULL );
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 );
+ input_SendEventAout( p_owner->p_input );
+
if( p_owner->p_aout_input == NULL )
{
msg_Err( p_dec, "failed to create audio output" );
p_owner->p_vout = NULL;
vlc_mutex_unlock( &p_owner->lock );
- p_vout = vout_Request( p_dec, p_vout, &p_dec->fmt_out.video );
+ p_vout = input_ressource_RequestVout( p_owner->p_input->p->p_ressource,
+ p_vout, &p_dec->fmt_out.video );
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" );
DecoderSignalBuffering( p_dec, true );
/* Check the decoder doesn't leak pictures */
- vout_FixLeaks( p_owner->p_vout );
+ vout_FixLeaks( p_owner->p_vout, false );
+ /* FIXME add a vout_WaitPictureAvailable (timedwait) */
msleep( VOUT_OUTMEM_SLEEP );
}
}
if( p_dec->b_die || p_dec->b_error )
break;
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
if( p_vout )
break;
- msleep( VOUT_DISPLAY_DELAY );
+ msleep( DECODER_SPU_VOUT_WAIT_DURATION );
}
if( !p_vout )
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vout_thread_t *p_vout = NULL;
- p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
if( !p_vout || p_owner->p_spu_vout != p_vout )
{
if( p_vout )