#include "../video_output/vout_control.h"
static decoder_t *CreateDecoder( vlc_object_t *, input_thread_t *,
- es_format_t *, bool, input_resource_t *,
+ const es_format_t *, bool, input_resource_t *,
sout_instance_t *p_sout );
static void DeleteDecoder( decoder_t * );
static void *DecoderThread( void * );
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 );
-static void DecoderFlushBuffering( decoder_t * );
+static void DecoderSignalWait( decoder_t * );
static void DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t );
/* Buffers allocation callbacks for the decoders */
+static int vout_update_format( decoder_t * );
static picture_t *vout_new_buffer( decoder_t * );
-static void vout_del_buffer( decoder_t *, picture_t * );
-static void vout_link_picture( decoder_t *, picture_t * );
-static void vout_unlink_picture( decoder_t *, picture_t * );
static int aout_update_format( decoder_t * );
static subpicture_t *spu_new_buffer( decoder_t *, const subpicture_updater_t * );
-static void spu_del_buffer( decoder_t *, subpicture_t * );
struct decoder_owner_sys_t
{
bool b_packetizer;
/* Current format in use by the output */
- video_format_t video;
- audio_format_t audio;
- es_format_t sout;
+ es_format_t fmt;
/* */
bool b_fmt_description;
- es_format_t fmt_description;
vlc_meta_t *p_description;
/* fifo */
int i_ignore;
} pause;
- /* Buffering */
- bool b_buffering;
- struct
- {
- bool b_first;
- bool b_full;
- int i_count;
-
- picture_t *p_picture;
- picture_t **pp_picture_next;
-
- subpicture_t *p_subpic;
- subpicture_t **pp_subpic_next;
-
- block_t *p_audio;
- block_t **pp_audio_next;
-
- block_t *p_block;
- block_t **pp_block_next;
- } buffer;
+ /* Waiting */
+ bool b_woken;
+ bool b_waiting;
+ bool b_first;
+ bool b_has_data;
/* Flushing */
bool b_flushing;
mtime_t i_ts_delay;
};
-#define DECODER_MAX_BUFFERING_COUNT (4)
-#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))
*****************************************************************************/
picture_t *decoder_NewPicture( decoder_t *p_decoder )
{
+ if( decoder_UpdateVideoFormat( p_decoder ) )
+ return NULL;
+
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 );
-}
block_t *decoder_NewAudioBuffer( decoder_t *dec, int samples )
{
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,
/* TODO: pass p_sout through p_resource? -- Courmisch */
static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
- es_format_t *fmt, input_clock_t *p_clock,
+ const es_format_t *fmt, input_clock_t *p_clock,
input_resource_t *p_resource,
sout_instance_t *p_sout )
{
/**
* Spawn a decoder thread outside of the input thread.
*/
-decoder_t *input_DecoderCreate( vlc_object_t *p_parent, es_format_t *fmt,
+decoder_t *input_DecoderCreate( vlc_object_t *p_parent, const es_format_t *fmt,
input_resource_t *p_resource )
{
return decoder_New( p_parent, NULL, fmt, NULL, p_resource, NULL );
vlc_cancel( p_owner->thread );
- /* Make sure we aren't paused/buffering/waiting/decoding anymore */
+ /* Make sure we aren't paused/waiting/decoding anymore */
vlc_mutex_lock( &p_owner->lock );
- const bool b_was_paused = p_owner->b_paused;
p_owner->b_paused = false;
- p_owner->b_buffering = false;
+ p_owner->b_waiting = false;
p_owner->b_flushing = true;
p_owner->b_exit = true;
vlc_cond_signal( &p_owner->wait_request );
vlc_mutex_unlock( &p_owner->lock );
vlc_join( p_owner->thread, NULL );
- p_owner->b_paused = b_was_paused;
module_unneed( p_dec, p_dec->p_module );
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- if( b_do_pace )
- {
- /* 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 );
- }
-#ifdef __arm__
- else if( block_FifoSize( p_owner->p_fifo ) > 50*1024*1024 /* 50 MiB */ )
-#else
- else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ )
-#endif
+ vlc_fifo_Lock( p_owner->p_fifo );
+ if( !b_do_pace )
{
/* FIXME: ideally we would check the time amount of data
* 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 );
+ /* 400 MiB, i.e. ~ 50mb/s for 60s */
+ if( vlc_fifo_GetBytes( p_owner->p_fifo ) > 400*1024*1024 )
+ {
+ msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
+ "consumed quickly enough), resetting fifo!" );
+ block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo ) );
+ }
+ }
+ else
+ if( !p_owner->b_waiting )
+ { /* The FIFO is not consumed when waiting, so pacing would deadlock VLC.
+ * Locking is not necessary as b_waiting is only read, not written by
+ * the decoder thread. */
+ while( vlc_fifo_GetCount( p_owner->p_fifo ) >= 10 )
+ vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_acknowledge );
}
- block_FifoPut( p_owner->p_fifo, p_block );
+ vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
+ vlc_fifo_Unlock( p_owner->p_fifo );
}
bool input_DecoderIsEmpty( decoder_t * p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- assert( !p_owner->b_buffering );
+ assert( !p_owner->b_waiting );
bool b_empty = block_FifoCount( p_dec->p_owner->p_fifo ) <= 0;
- if (p_owner->buffer.i_count) /* buffered frames */
- b_empty = false;
if( b_empty )
{
vlc_mutex_lock( &p_owner->lock );
/* TODO subtitles support */
- if( p_dec->fmt_out.i_cat == VIDEO_ES && p_owner->p_vout )
+ if( p_owner->fmt.i_cat == VIDEO_ES && p_owner->p_vout )
b_empty = vout_IsEmpty( p_owner->p_vout );
- else if( p_dec->fmt_out.i_cat == AUDIO_ES && p_owner->p_aout )
+ else if( p_owner->fmt.i_cat == AUDIO_ES && p_owner->p_aout )
b_empty = aout_DecIsEmpty( p_owner->p_aout );
vlc_mutex_unlock( &p_owner->lock );
}
p_owner->pause.i_ignore = 0;
vlc_cond_signal( &p_owner->wait_request );
- DecoderOutputChangePause( p_dec, b_paused, i_date );
+ /* XXX only audio and video output have to be paused.
+ * - for sout it is useless
+ * - for subs, it is done by the vout
+ */
+ if( p_dec->fmt_out.i_cat == AUDIO_ES )
+ {
+ if( p_owner->p_aout )
+ aout_DecChangePause( p_owner->p_aout, b_paused, i_date );
+ }
+ else if( p_dec->fmt_out.i_cat == VIDEO_ES )
+ {
+ if( p_owner->p_vout )
+ vout_ChangePause( p_owner->p_vout, b_paused, i_date );
+ }
}
vlc_mutex_unlock( &p_owner->lock );
}
vlc_mutex_unlock( &p_owner->lock );
}
-void input_DecoderStartBuffering( decoder_t *p_dec )
+/**
+ * Requests that the decoder immediately discard all pending buffers.
+ * This is useful at end of stream, when seeking or when deselecting a stream.
+ */
+void input_DecoderFlush( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
-
DecoderFlush( p_dec );
+ vlc_mutex_unlock( &p_owner->lock );
+}
- p_owner->buffer.b_first = true;
- 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 && !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_subpic = NULL;
- p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
-
- 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;
+void input_DecoderStartWait( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+ assert( !p_owner->b_waiting );
- p_owner->b_buffering = true;
+ input_DecoderFlush( p_dec );
+ vlc_mutex_lock( &p_owner->lock );
+ p_owner->b_first = true;
+ p_owner->b_has_data = false;
+ p_owner->b_waiting = true;
vlc_cond_signal( &p_owner->wait_request );
-
vlc_mutex_unlock( &p_owner->lock );
}
-void input_DecoderStopBuffering( decoder_t *p_dec )
+void input_DecoderStopWait( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vlc_mutex_lock( &p_owner->lock );
-
- p_owner->b_buffering = false;
+ assert( p_owner->b_waiting );
+ vlc_mutex_lock( &p_owner->lock );
+ p_owner->b_waiting = false;
vlc_cond_signal( &p_owner->wait_request );
-
vlc_mutex_unlock( &p_owner->lock );
}
-void input_DecoderWaitBuffering( decoder_t *p_dec )
+void input_DecoderWait( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vlc_mutex_lock( &p_owner->lock );
+ assert( p_owner->b_waiting );
- while( p_owner->b_buffering && !p_owner->buffer.b_full )
+ vlc_mutex_lock( &p_owner->lock );
+ while( !p_owner->b_has_data )
{
- block_FifoWake( p_owner->p_fifo );
+ vlc_fifo_Lock( p_owner->p_fifo );
+ p_owner->b_woken = true;
+ vlc_fifo_Signal( p_owner->p_fifo );
+ vlc_fifo_Unlock( p_owner->p_fifo );
vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
}
-
vlc_mutex_unlock( &p_owner->lock );
}
else
{
/* TODO subtitle should not be flushed */
+ p_owner->b_waiting = false;
DecoderFlush( p_dec );
}
vlc_mutex_unlock( &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( p_fmt != NULL )
+ es_format_Copy( p_fmt, &p_owner->fmt );
if( pp_meta )
{
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 )
+ if( p_owner->b_waiting || p_owner->b_paused )
i_ts = VLC_TS_INVALID;
vlc_mutex_unlock( &p_owner->lock );
if( !p_owner->p_clock || i_ts <= VLC_TS_INVALID )
return i_ts;
- if( input_clock_ConvertTS( p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) )
+ if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) ) {
+ msg_Err(p_dec, "Could not get display date for timestamp %"PRId64"", i_ts);
return VLC_TS_INVALID;
+ }
return i_ts;
}
/* */
static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
{
- msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'. "
- "VLC probably does not support this sound or video format.",
- (char*)&codec );
- dialog_Fatal( p_dec, _("No suitable decoder module"),
- _("VLC does not support the audio or video format \"%4.4s\". "
- "Unfortunately there is no way for you to fix this."),
- (char*)&codec );
+ if (codec != VLC_FOURCC('u','n','d','f')) {
+ const char *desc = vlc_fourcc_GetDescription(p_dec->fmt_in.i_cat, codec);
+ if (!desc || !*desc)
+ desc = N_("No description for this codec");
+ msg_Err( p_dec, "Codec `%4.4s' (%s) is not supported.", (char*)&codec, desc );
+ dialog_Fatal( p_dec, _("Codec not supported"),
+ _("VLC could not decode the format \"%4.4s\" (%s)"),
+ (char*)&codec, desc );
+ } else {
+ msg_Err( p_dec, "could not identify codec" );
+ dialog_Fatal( p_dec, _("Unidentified codec"),
+ _("VLC could not identify the audio or video codec" ) );
+ }
}
*/
static decoder_t * CreateDecoder( vlc_object_t *p_parent,
input_thread_t *p_input,
- es_format_t *fmt, bool b_packetizer,
+ const es_format_t *fmt, bool b_packetizer,
input_resource_t *p_resource,
sout_instance_t *p_sout )
{
p_owner->p_sout_input = NULL;
p_owner->p_packetizer = NULL;
p_owner->b_packetizer = b_packetizer;
+ es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
/* decoder fifo */
+ p_owner->b_woken = false;
p_owner->p_fifo = block_FifoNew();
if( unlikely(p_owner->p_fifo == NULL) )
{
/* Set buffers allocation callbacks for the decoders */
p_dec->pf_aout_format_update = aout_update_format;
+ p_dec->pf_vout_format_update = vout_update_format;
p_dec->pf_vout_buffer_new = vout_new_buffer;
- p_dec->pf_vout_buffer_del = vout_del_buffer;
- p_dec->pf_picture_link = vout_link_picture;
- 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;
{
es_format_Clean( &p_owner->p_packetizer->fmt_in );
vlc_object_release( p_owner->p_packetizer );
+ p_owner->p_packetizer = NULL;
}
}
}
vlc_cond_init( &p_owner->wait_acknowledge );
p_owner->b_fmt_description = false;
- es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 );
p_owner->p_description = NULL;
p_owner->b_exit = false;
p_owner->pause.i_date = VLC_TS_INVALID;
p_owner->pause.i_ignore = 0;
- p_owner->b_buffering = false;
- p_owner->buffer.b_first = true;
- p_owner->buffer.b_full = false;
- p_owner->buffer.i_count = 0;
- 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_waiting = false;
+ p_owner->b_first = true;
+ p_owner->b_has_data = false;
p_owner->b_flushing = false;
/* The decoder's main loop */
for( ;; )
{
- block_t *p_block = block_FifoGet( p_owner->p_fifo );
+ block_t *p_block;
+
+ vlc_fifo_Lock( p_owner->p_fifo );
+ vlc_fifo_CleanupPush( p_owner->p_fifo );
+
+ while( vlc_fifo_IsEmpty( p_owner->p_fifo ) )
+ {
+ if( p_owner->b_woken )
+ break;
+ vlc_fifo_Wait( 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. */
+ }
- /* Make sure there is no cancellation point other than this one^^.
- * If you need one, be sure to push cleanup of p_block. */
- bool end_buffering = !p_block || p_block->i_flags & BLOCK_FLAG_CORE_EOS;
- DecoderSignalBuffering( p_dec, end_buffering );
- if (end_buffering)
- input_DecoderStopBuffering( p_dec );
+ p_block = vlc_fifo_DequeueUnlocked( p_owner->p_fifo );
+ if( p_block != NULL )
+ vlc_cond_signal( &p_owner->wait_acknowledge );
+
+ p_owner->b_woken = false;
+ vlc_cleanup_run();
+
+ if( p_block == NULL || p_block->i_flags & BLOCK_FLAG_CORE_EOS )
+ DecoderSignalWait( p_dec );
if( p_block )
{
p_block = NULL;
}
- if( p_dec->b_error )
- DecoderError( p_dec, p_block );
- else
- DecoderProcess( p_dec, p_block );
+ DecoderProcess( p_dec, p_block );
vlc_restorecancel( canc );
}
vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
}
-static void DecoderSignalBuffering( decoder_t *p_dec, bool b_full )
+static void DecoderSignalWait( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_buffering )
+ if( p_owner->b_waiting )
{
- if( b_full )
- p_owner->buffer.b_full = true;
+ p_owner->b_has_data = true;
vlc_cond_signal( &p_owner->wait_acknowledge );
}
return b_flushing;
}
-static void DecoderWaitUnblock( decoder_t *p_dec, bool *pb_reject )
+static bool DecoderWaitUnblock( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
break;
if( p_owner->b_paused )
{
- if( p_owner->b_buffering && !p_owner->buffer.b_full )
+ if( p_owner->b_waiting && !p_owner->b_has_data )
break;
if( p_owner->pause.i_ignore > 0 )
{
}
else
{
- if( !p_owner->b_buffering || !p_owner->buffer.b_full )
+ if( !p_owner->b_waiting || !p_owner->b_has_data )
break;
}
vlc_cond_wait( &p_owner->wait_request, &p_owner->lock );
}
- if( pb_reject )
- *pb_reject = p_owner->b_flushing;
+ return p_owner->b_flushing;
}
-static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
-{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
-
- vlc_assert_locked( &p_owner->lock );
-
- /* XXX only audio and video output have to be paused.
- * - for sout it is useless
- * - for subs, it is done by the vout
- */
- if( p_dec->fmt_out.i_cat == AUDIO_ES )
- {
- if( p_owner->p_aout )
- aout_DecChangePause( p_owner->p_aout, b_paused, i_date );
- }
- else if( p_dec->fmt_out.i_cat == VIDEO_ES )
- {
- if( p_owner->p_vout )
- vout_ChangePause( p_owner->p_vout, b_paused, i_date );
- }
-}
static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
{
if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
*pi_ts0 += i_es_delay;
if( pi_ts1 && *pi_ts1 > VLC_TS_INVALID )
*pi_ts1 += i_es_delay;
- if( input_clock_ConvertTS( p_clock, &i_rate, pi_ts0, pi_ts1, i_ts_bound ) )
+ if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_clock, &i_rate, pi_ts0, pi_ts1, i_ts_bound ) ) {
+ if( pi_ts1 != NULL )
+ msg_Err(p_dec, "Could not convert timestamps %"PRId64
+ ", %"PRId64"", *pi_ts0, *pi_ts1);
+ else
+ msg_Err(p_dec, "Could not convert timestamp %"PRId64, *pi_ts0);
*pi_ts0 = VLC_TS_INVALID;
+ }
}
else
{
/* */
vlc_mutex_lock( &p_owner->lock );
- if( p_audio && (p_owner->b_buffering || p_owner->buffer.p_audio) )
+ if( p_audio && p_owner->b_waiting )
{
- p_audio->p_next = NULL;
-
- *p_owner->buffer.pp_audio_next = p_audio;
- p_owner->buffer.pp_audio_next = &p_audio->p_next;
-
- p_owner->buffer.i_count++;
- if( p_owner->buffer.i_count > DECODER_MAX_BUFFERING_COUNT ||
- p_audio->i_pts - p_owner->buffer.p_audio->i_pts > DECODER_MAX_BUFFERING_AUDIO_DURATION )
- {
- p_owner->buffer.b_full = true;
- vlc_cond_signal( &p_owner->wait_acknowledge );
- }
+ p_owner->b_has_data = true;
+ vlc_cond_signal( &p_owner->wait_acknowledge );
}
for( ;; )
{
- bool b_has_more = false, b_paused, b_reject;
+ bool b_paused;
- DecoderWaitUnblock( p_dec, &b_reject );
- if( p_owner->b_buffering )
- break;
+ bool b_reject = DecoderWaitUnblock( p_dec );
b_paused = p_owner->b_paused;
- /* */
- if( p_owner->buffer.p_audio )
- {
- p_audio = p_owner->buffer.p_audio;
-
- p_owner->buffer.p_audio = p_audio->p_next;
- p_owner->buffer.i_count--;
-
- b_has_more = p_owner->buffer.p_audio != NULL;
- if( !b_has_more )
- p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
- }
-
if (!p_audio)
break;
block_Release( p_audio );
}
- if( !b_has_more )
- break;
- if( !p_owner->buffer.p_audio )
- break;
+ break;
}
vlc_mutex_unlock( &p_owner->lock );
}
{
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 <= VLC_TS_INVALID )
{
msg_Warn( p_dec, "non-dated video buffer received" );
*pi_lost_sum += 1;
- vout_ReleasePicture( p_vout, p_picture );
+ picture_Release( p_picture );
return;
}
/* */
vlc_mutex_lock( &p_owner->lock );
- if( ( p_owner->b_buffering && !p_owner->buffer.b_first ) || p_owner->buffer.p_picture )
+ if( p_owner->b_waiting && !p_owner->b_first )
{
- p_picture->p_next = NULL;
-
- *p_owner->buffer.pp_picture_next = p_picture;
- p_owner->buffer.pp_picture_next = &p_picture->p_next;
-
- p_owner->buffer.i_count++;
- if( p_owner->buffer.i_count > DECODER_MAX_BUFFERING_COUNT ||
- p_picture->date - p_owner->buffer.p_picture->date > DECODER_MAX_BUFFERING_VIDEO_DURATION )
- {
- p_owner->buffer.b_full = true;
- vlc_cond_signal( &p_owner->wait_acknowledge );
- }
+ p_owner->b_has_data = true;
+ vlc_cond_signal( &p_owner->wait_acknowledge );
}
- b_first_buffered = p_owner->buffer.p_picture != NULL;
-
- for( ;; b_first_buffered = false )
- {
- bool b_has_more = false;
+ bool b_first_after_wait = p_owner->b_waiting && p_owner->b_has_data;
- bool b_reject;
+ bool b_reject = DecoderWaitUnblock( p_dec );
- DecoderWaitUnblock( p_dec, &b_reject );
-
- if( p_owner->b_buffering && !p_owner->buffer.b_first )
- {
- vlc_mutex_unlock( &p_owner->lock );
- return;
- }
- bool b_buffering_first = p_owner->b_buffering;
-
- /* */
- if( p_owner->buffer.p_picture )
- {
- p_picture = p_owner->buffer.p_picture;
-
- p_owner->buffer.p_picture = p_picture->p_next;
- p_owner->buffer.i_count--;
-
- b_has_more = p_owner->buffer.p_picture != NULL;
- if( !b_has_more )
- p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
- }
-
- /* */
- 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->b_force = true;
- }
+ if( p_owner->b_waiting )
+ {
+ assert( p_owner->b_first );
+ msg_Dbg( p_dec, "Received first picture" );
+ p_owner->b_first = false;
+ p_picture->b_force = true;
+ }
- const bool b_dated = p_picture->date > VLC_TS_INVALID;
- int i_rate = INPUT_RATE_DEFAULT;
- DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
- &i_rate, DECODER_BOGUS_VIDEO_DELAY );
+ const bool b_dated = p_picture->date > VLC_TS_INVALID;
+ int i_rate = INPUT_RATE_DEFAULT;
+ DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
+ &i_rate, DECODER_BOGUS_VIDEO_DELAY );
- vlc_mutex_unlock( &p_owner->lock );
+ vlc_mutex_unlock( &p_owner->lock );
- /* */
- if( !p_picture->b_force && p_picture->date <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify video_output/*
- b_reject = true;
+ /* */
+ if( !p_picture->b_force && p_picture->date <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify video_output/*
+ b_reject = true;
- if( !b_reject )
+ if( !b_reject )
+ {
+ if( i_rate != p_owner->i_last_rate || b_first_after_wait )
{
- 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_PutPicture( p_vout, p_picture );
+ /* 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_PutPicture( p_vout, p_picture );
+ }
+ else
+ {
+ if( b_dated )
+ msg_Warn( p_dec, "early picture skipped" );
else
- {
- if( b_dated )
- msg_Warn( p_dec, "early picture skipped" );
- else
- msg_Warn( p_dec, "non-dated video buffer received" );
+ msg_Warn( p_dec, "non-dated video buffer received" );
- *pi_lost_sum += 1;
- vout_ReleasePicture( p_vout, p_picture );
- }
- int i_tmp_display;
- int i_tmp_lost;
- vout_GetResetStatistic( p_vout, &i_tmp_display, &i_tmp_lost );
-
- *pi_played_sum += i_tmp_display;
- *pi_lost_sum += i_tmp_lost;
-
- if( !b_has_more || b_buffering_first )
- break;
-
- vlc_mutex_lock( &p_owner->lock );
- if( !p_owner->buffer.p_picture )
- {
- vlc_mutex_unlock( &p_owner->lock );
- break;
- }
+ *pi_lost_sum += 1;
+ picture_Release( p_picture );
}
+ int i_tmp_display;
+ int i_tmp_lost;
+ vout_GetResetStatistic( p_vout, &i_tmp_display, &i_tmp_lost );
+
+ *pi_played_sum += i_tmp_display;
+ *pi_lost_sum += i_tmp_lost;
}
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
if( DecoderIsExitRequested( p_dec ) )
{
/* It prevent freezing VLC in case of broken decoder */
- vout_ReleasePicture( p_vout, p_pic );
+ picture_Release( p_pic );
if( p_block )
block_Release( p_block );
break;
if( p_owner->i_preroll_end > VLC_TS_INVALID && p_pic->date < p_owner->i_preroll_end )
{
- vout_ReleasePicture( p_vout, p_pic );
+ picture_Release( p_pic );
continue;
}
/* */
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_buffering || p_owner->buffer.p_subpic )
+ if( p_owner->b_waiting )
{
- p_subpic->p_next = NULL;
-
- *p_owner->buffer.pp_subpic_next = p_subpic;
- p_owner->buffer.pp_subpic_next = &p_subpic->p_next;
-
- 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_acknowledge );
- }
+ p_owner->b_has_data = true;
+ vlc_cond_signal( &p_owner->wait_acknowledge );
}
- 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_subpic )
- {
- p_subpic = p_owner->buffer.p_subpic;
-
- p_owner->buffer.p_subpic = p_subpic->p_next;
- p_owner->buffer.i_count--;
-
- b_has_more = p_owner->buffer.p_subpic != NULL;
- if( !b_has_more )
- p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
- }
-
- /* */
- DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
- NULL, INT64_MAX );
+ bool b_reject = DecoderWaitUnblock( p_dec );
- if( p_subpic->i_start <= VLC_TS_INVALID )
- b_reject = true;
+ DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
+ NULL, INT64_MAX );
- DecoderWaitDate( p_dec, &b_reject,
- p_subpic->i_start - SPU_MAX_PREPARE_TIME );
- vlc_mutex_unlock( &p_owner->lock );
+ if( p_subpic->i_start <= VLC_TS_INVALID )
+ b_reject = true;
- if( !b_reject )
- vout_PutSubpicture( p_vout, p_subpic );
- else
- subpicture_Delete( p_subpic );
+ DecoderWaitDate( p_dec, &b_reject,
+ p_subpic->i_start - SPU_MAX_PREPARE_TIME );
+ vlc_mutex_unlock( &p_owner->lock );
- if( !b_has_more )
- break;
- vlc_mutex_lock( &p_owner->lock );
- if( !p_owner->buffer.p_subpic )
- {
- vlc_mutex_unlock( &p_owner->lock );
- break;
- }
- }
+ if( !b_reject )
+ vout_PutSubpicture( p_vout, p_subpic );
+ else
+ subpicture_Delete( p_subpic );
}
#ifdef ENABLE_SOUT
-static void DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
+static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_buffering || p_owner->buffer.p_block )
- {
- block_ChainLastAppend( &p_owner->buffer.pp_block_next, p_sout_block );
-
- 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_acknowledge );
- }
- }
-
- for( ;; )
+ if( p_owner->b_waiting )
{
- 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, NULL, INT64_MAX );
-
- vlc_mutex_unlock( &p_owner->lock );
-
- if( !b_reject )
- sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block ); // FIXME --VLC_TS_INVALID inspect stream_output/*
- 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;
- }
+ p_owner->b_has_data = true;
+ vlc_cond_signal( &p_owner->wait_acknowledge );
}
-}
-#endif
-
-/* */
-static void DecoderFlushBuffering( decoder_t *p_dec )
-{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
-
- vlc_assert_locked( &p_owner->lock );
-
- while( p_owner->buffer.p_picture )
- {
- picture_t *p_picture = p_owner->buffer.p_picture;
-
- p_owner->buffer.p_picture = p_picture->p_next;
- p_owner->buffer.i_count--;
-
- if( p_owner->p_vout )
- {
- vout_ReleasePicture( p_owner->p_vout, p_picture );
- }
- if( !p_owner->buffer.p_picture )
- p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
- }
- while( p_owner->buffer.p_audio )
- {
- block_t *p_audio = p_owner->buffer.p_audio;
+ bool b_reject = DecoderWaitUnblock( p_dec );
- p_owner->buffer.p_audio = p_audio->p_next;
- p_owner->buffer.i_count--;
+ DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
+ &p_sout_block->i_length, NULL, INT64_MAX );
- block_Release( p_audio );
+ vlc_mutex_unlock( &p_owner->lock );
- if( !p_owner->buffer.p_audio )
- p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
- }
- while( p_owner->buffer.p_subpic )
+ if( !b_reject )
{
- subpicture_t *p_subpic = p_owner->buffer.p_subpic;
-
- p_owner->buffer.p_subpic = p_subpic->p_next;
- p_owner->buffer.i_count--;
-
- subpicture_Delete( p_subpic );
-
- if( !p_owner->buffer.p_subpic )
- p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
+ /* FIXME --VLC_TS_INVALID inspect stream_output*/
+ return sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
}
- if( p_owner->buffer.p_block )
+ else
{
- 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;
+ block_Release( p_sout_block );
+ return VLC_EGENERIC;
}
}
+#endif
#ifdef ENABLE_SOUT
/* This function process a block for sout
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 == NULL )
{
- es_format_Copy( &p_owner->sout, &p_dec->fmt_out );
+ assert( !p_owner->b_fmt_description ); // no need for owner lock
+ es_format_Clean( &p_owner->fmt );
+ es_format_Copy( &p_owner->fmt, &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;
+ p_owner->fmt.i_group = p_dec->fmt_in.i_group;
+ p_owner->fmt.i_id = p_dec->fmt_in.i_id;
if( p_dec->fmt_in.psz_language )
{
- free( p_owner->sout.psz_language );
- p_owner->sout.psz_language =
+ free( p_owner->fmt.psz_language );
+ p_owner->fmt.psz_language =
strdup( p_dec->fmt_in.psz_language );
}
p_owner->p_sout_input =
- sout_InputNew( p_owner->p_sout,
- &p_owner->sout );
+ sout_InputNew( p_owner->p_sout, &p_owner->fmt );
if( p_owner->p_sout_input == NULL )
{
msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
- (char *)&p_owner->sout.i_codec );
+ (char *)&p_owner->fmt.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;
- }
+ block_ChainRelease(p_sout_block);
break;
}
}
p_sout_block->p_next = NULL;
- DecoderPlaySout( p_dec, p_sout_block );
+ if( DecoderPlaySout( p_dec, p_sout_block ) == VLC_EGENERIC )
+ {
+ msg_Err( p_dec, "cannot continue streaming due to errors" );
+
+ p_dec->b_error = true;
+
+ /* Cleanup */
+ block_ChainRelease( p_next );
+ return;
+ }
p_sout_block = p_next;
}
es_format_Clean( &p_dec->fmt_in );
es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
}
+
+ /* If the packetizer provides aspect ratio information, pass it
+ * to the decoder as a hint if the decoder itself can't provide
+ * it. Copy it regardless of the current value of the decoder input
+ * format aspect ratio, to properly propagate changes in aspect
+ * ratio. */
+ if( p_packetizer->fmt_out.video.i_sar_num > 0 &&
+ p_packetizer->fmt_out.video.i_sar_den > 0)
+ {
+ p_dec->fmt_in.video.i_sar_num =
+ p_packetizer->fmt_out.video.i_sar_num;
+ p_dec->fmt_in.video.i_sar_den=
+ p_packetizer->fmt_out.video.i_sar_den;
+ }
+
if( p_packetizer->pf_get_cc )
DecoderGetCc( p_dec, p_packetizer );
DecoderDecodeVideo( p_dec, p_null );
}
}
- else if( p_block )
+ else
{
DecoderDecodeVideo( p_dec, p_block );
}
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_mutex_lock( &p_owner->lock );
- DecoderFlushBuffering( p_dec );
if( p_owner->b_flushing )
{
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);
+ if( p_dec->b_error )
+ {
+ if( p_block )
+ block_Release( p_block );
+ goto flush;
+ }
+
if( p_block && p_block->i_buffer <= 0 )
{
assert( !b_flush_request );
}
/* */
+flush:
if( b_flush_request )
DecoderProcessOnFlush( 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);
-
- /* */
- if( p_block )
- block_Release( p_block );
-
- if( b_flush_request )
- DecoderProcessOnFlush( p_dec );
-}
-
-
/**
* Destroys a decoder object
*
(unsigned)block_FifoCount( p_owner->p_fifo ) );
/* Free all packets still in the decoder fifo. */
- block_FifoEmpty( p_owner->p_fifo );
block_FifoRelease( p_owner->p_fifo );
- /* */
- vlc_mutex_lock( &p_owner->lock );
- DecoderFlushBuffering( p_dec );
- vlc_mutex_unlock( &p_owner->lock );
-
/* Cleanup */
if( p_owner->p_aout )
{
if( p_owner->p_sout_input )
{
sout_InputDelete( p_owner->p_sout_input );
- es_format_Clean( &p_owner->sout );
}
#endif
+ es_format_Clean( &p_owner->fmt );
if( p_dec->fmt_out.i_cat == SPU_ES )
{
- vout_thread_t *p_vout;
-
- p_vout = input_resource_HoldVout( p_owner->p_resource );
+ vout_thread_t *p_vout = input_resource_HoldVout( p_owner->p_resource );
if( p_vout )
{
if( p_owner->p_spu_vout == p_vout )
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 );
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 );
decoder_owner_sys_t *p_owner = p_dec->p_owner;
if( p_owner->p_aout
- && !AOUT_FMTS_IDENTICAL(&p_dec->fmt_out.audio, &p_owner->audio) )
+ && !AOUT_FMTS_IDENTICAL(&p_dec->fmt_out.audio, &p_owner->fmt.audio) )
{
audio_output_t *p_aout = p_owner->p_aout;
/* Parameters changed, restart the aout */
vlc_mutex_lock( &p_owner->lock );
- DecoderFlushBuffering( p_dec );
aout_DecDelete( p_owner->p_aout );
p_owner->p_aout = NULL;
if( p_owner->p_aout == NULL )
{
- const int i_force_dolby = var_InheritInteger( p_dec, "force-dolby-surround" );
- audio_sample_format_t format;
- audio_output_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;
- aout_FormatPrepare( &p_owner->audio );
- memcpy( &format, &p_owner->audio, sizeof( audio_sample_format_t ) );
+ audio_sample_format_t format = p_dec->fmt_out.audio;
+ aout_FormatPrepare( &format );
+
+ const int i_force_dolby = var_InheritInteger( p_dec, "force-dolby-surround" );
if( i_force_dolby &&
(format.i_original_channels&AOUT_CHAN_PHYSMASK) ==
(AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
}
}
- request_vout.pf_request_vout = aout_request_vout;
- request_vout.p_private = p_dec;
+ aout_request_vout_t request_vout = {
+ .pf_request_vout = aout_request_vout,
+ .p_private = p_dec,
+ };
+ audio_output_t *p_aout;
- assert( p_owner->p_aout == NULL );
p_aout = input_resource_GetAout( p_owner->p_resource );
if( p_aout )
{
vlc_mutex_lock( &p_owner->lock );
p_owner->p_aout = p_aout;
+
+ es_format_Clean( &p_owner->fmt );
+ es_format_Copy( &p_owner->fmt, &p_dec->fmt_out );
+ aout_FormatPrepare( &p_owner->fmt.audio );
+
DecoderUpdateFormatLocked( p_dec );
- if( unlikely(p_owner->b_paused) ) /* fake pause if needed */
+
+ if( unlikely(p_owner->b_paused) && p_aout != NULL )
+ /* fake pause if needed */
aout_DecChangePause( p_aout, true, mdate() );
vlc_mutex_unlock( &p_owner->lock );
}
p_dec->fmt_out.audio.i_bytes_per_frame =
- p_owner->audio.i_bytes_per_frame;
- p_dec->fmt_out.audio.i_frame_length = p_owner->audio.i_frame_length;
+ p_owner->fmt.audio.i_bytes_per_frame;
+ p_dec->fmt_out.audio.i_frame_length =
+ p_owner->fmt.audio.i_frame_length;
}
return 0;
}
-static picture_t *vout_new_buffer( decoder_t *p_dec )
+static int vout_update_format( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
- if( p_owner->p_vout == NULL ||
- p_dec->fmt_out.video.i_width != p_owner->video.i_width ||
- p_dec->fmt_out.video.i_height != p_owner->video.i_height ||
- p_dec->fmt_out.video.i_visible_width != p_owner->video.i_visible_width ||
- p_dec->fmt_out.video.i_visible_height != p_owner->video.i_visible_height ||
- p_dec->fmt_out.video.i_x_offset != p_owner->video.i_x_offset ||
- p_dec->fmt_out.video.i_y_offset != p_owner->video.i_y_offset ||
- p_dec->fmt_out.i_codec != p_owner->video.i_chroma ||
- (int64_t)p_dec->fmt_out.video.i_sar_num * p_owner->video.i_sar_den !=
- (int64_t)p_dec->fmt_out.video.i_sar_den * p_owner->video.i_sar_num )
+ if( p_owner->p_vout == NULL
+ || p_dec->fmt_out.video.i_width != p_owner->fmt.video.i_width
+ || p_dec->fmt_out.video.i_height != p_owner->fmt.video.i_height
+ || p_dec->fmt_out.video.i_visible_width != p_owner->fmt.video.i_visible_width
+ || p_dec->fmt_out.video.i_visible_height != p_owner->fmt.video.i_visible_height
+ || p_dec->fmt_out.video.i_x_offset != p_owner->fmt.video.i_x_offset
+ || p_dec->fmt_out.video.i_y_offset != p_owner->fmt.video.i_y_offset
+ || p_dec->fmt_out.i_codec != p_owner->fmt.video.i_chroma
+ || (int64_t)p_dec->fmt_out.video.i_sar_num * p_owner->fmt.video.i_sar_den !=
+ (int64_t)p_dec->fmt_out.video.i_sar_den * p_owner->fmt.video.i_sar_num ||
+ p_dec->fmt_out.video.orientation != p_owner->fmt.video.orientation )
{
vout_thread_t *p_vout;
!p_dec->fmt_out.video.i_height )
{
/* Can't create a new vout without display size */
- return NULL;
+ return -1;
}
video_format_t fmt = p_dec->fmt_out.video;
fmt.i_chroma = p_dec->fmt_out.i_codec;
- p_owner->video = fmt;
if( vlc_fourcc_IsYUV( fmt.i_chroma ) )
{
vlc_mutex_lock( &p_owner->lock );
- DecoderFlushBuffering( p_dec );
-
p_vout = p_owner->p_vout;
p_owner->p_vout = NULL;
vlc_mutex_unlock( &p_owner->lock );
p_vout = input_resource_RequestVout( p_owner->p_resource,
p_vout, &fmt,
dpb_size +
- p_dec->i_extra_picture_buffers +
- 1 + DECODER_MAX_BUFFERING_COUNT,
+ p_dec->i_extra_picture_buffers + 1,
true );
vlc_mutex_lock( &p_owner->lock );
p_owner->p_vout = p_vout;
+ es_format_Clean( &p_owner->fmt );
+ es_format_Copy( &p_owner->fmt, &p_dec->fmt_out );
+ p_owner->fmt.video.i_chroma = p_dec->fmt_out.i_codec;
+
DecoderUpdateFormatLocked( p_dec );
vlc_mutex_unlock( &p_owner->lock );
{
msg_Err( p_dec, "failed to create video output" );
p_dec->b_error = true;
- return NULL;
+ return -1;
}
}
+ return 0;
+}
+
+static picture_t *vout_new_buffer( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
- /* Get a new picture
- */
for( ;; )
{
if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
return NULL;
/* */
- DecoderSignalBuffering( p_dec, true );
+ DecoderSignalWait( p_dec );
/* Check the decoder doesn't leak pictures */
vout_FixLeaks( p_owner->p_vout );
}
}
-static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
-{
- vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic );
-}
-
-static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic )
-{
- vout_HoldPicture( p_dec->p_owner->p_vout, p_pic );
-}
-
-static void vout_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
-{
- vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic );
-}
-
static subpicture_t *spu_new_buffer( decoder_t *p_dec,
const subpicture_updater_t *p_updater )
{
while( i_attempts-- )
{
- if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
+ if( DecoderIsExitRequested( p_dec ) || DecoderIsFlushing( p_dec )
+ || p_dec->b_error )
break;
p_vout = input_resource_HoldVout( p_owner->p_resource );
if( p_owner->p_spu_vout != p_vout )
{
- vlc_mutex_lock( &p_owner->lock );
-
- DecoderFlushBuffering( p_dec );
-
- vlc_mutex_unlock( &p_owner->lock );
-
p_owner->i_spu_channel = vout_RegisterSubpictureChannel( p_vout );
p_owner->i_spu_order = 0;
p_owner->p_spu_vout = p_vout;
return p_subpic;
}
-
-static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
-{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
- vout_thread_t *p_vout = NULL;
-
- p_vout = input_resource_HoldVout( p_owner->p_resource );
- if( !p_vout || p_owner->p_spu_vout != p_vout )
- {
- if( p_vout )
- vlc_object_release( p_vout );
- msg_Warn( p_dec, "no vout found, leaking subpicture" );
- return;
- }
-
- subpicture_Delete( p_subpic );
-
- vlc_object_release( p_vout );
-}
-