X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fdecoder.c;h=a00b4c8944a21215e50a4657f8e075eee86d666a;hb=ac217da0399df26771fec3005f4faaa65a2eb34b;hp=69dc112515a60c6ea86b35940c51767c2adcc942;hpb=df61d33b06e2b3cbbe746b2f5a9bea5b370c24ff;p=vlc diff --git a/src/input/decoder.c b/src/input/decoder.c index 69dc112515..a00b4c8944 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -31,7 +31,7 @@ #endif #include -#include +#include #include #include @@ -153,6 +153,9 @@ decoder_t *input_DecoderNew( input_thread_t *p_input, decoder_t *p_dec = NULL; vlc_value_t val; +#ifndef ENABLE_SOUT + (void)b_force_decoder; +#else /* If we are in sout mode, search for packetizer module */ if( p_input->p->p_sout && !b_force_decoder ) { @@ -167,6 +170,7 @@ decoder_t *input_DecoderNew( input_thread_t *p_input, } } else +#endif { /* Create the decoder configuration structure */ p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_DECODER ); @@ -441,10 +445,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_dec = vlc_object_create( p_input, i_object_type ); if( p_dec == NULL ) - { - msg_Err( p_input, "out of memory" ); return NULL; - } p_dec->pf_decode_audio = 0; p_dec->pf_decode_video = 0; @@ -463,7 +464,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) ); if( p_dec->p_owner == NULL ) { - msg_Err( p_dec, "out of memory" ); + vlc_object_release( p_dec ); return NULL; } p_dec->p_owner->b_own_thread = true; @@ -479,9 +480,10 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_dec->p_owner->p_packetizer = NULL; /* decoder fifo */ - if( ( p_dec->p_owner->p_fifo = block_FifoNew( p_dec ) ) == NULL ) + if( ( p_dec->p_owner->p_fifo = block_FifoNew() ) == NULL ) { - msg_Err( p_dec, "out of memory" ); + free( p_dec->p_owner ); + vlc_object_release( p_dec ); return NULL; } @@ -559,7 +561,7 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_owner->b_cc_supported = true; } - vlc_mutex_init( p_dec, &p_owner->lock_cc ); + vlc_mutex_init( &p_owner->lock_cc ); for( i = 0; i < 4; i++ ) { p_owner->pb_cc_present[i] = false; @@ -623,6 +625,13 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) ) { + if( p_dec->b_die ) + { + /* It prevent freezing VLC in case of broken decoder */ + if( p_block ) + block_Release( p_block ); + break; + } vlc_mutex_lock( &p_input->p->counters.counters_lock ); stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_audio, 1, NULL ); vlc_mutex_unlock( &p_input->p->counters.counters_lock ); @@ -722,6 +731,104 @@ static void VoutFlushPicture( vout_thread_t *p_vout ) } vlc_mutex_unlock( &p_vout->picture_lock ); } + + +static void optimize_video_pts( decoder_t *p_dec ) +{ + picture_t * oldest_pict = NULL; + picture_t * youngest_pict = NULL; + int i; + + input_thread_t * p_input = p_dec->p_owner->p_input; + vout_thread_t * p_vout = p_dec->p_owner->p_vout; + input_thread_private_t * p_priv = p_input->p; + + /* Enable with --auto-adjust-pts-delay */ + if( !p_priv->pts_adjust.auto_adjust ) return; + + for( i = 0; i < I_RENDERPICTURES; i++ ) + { + picture_t * pic = PP_RENDERPICTURE[i]; + if( pic->i_status != READY_PICTURE ) + continue; + + if( !oldest_pict || pic->date < oldest_pict->date ) + oldest_pict = pic; + if( !youngest_pict || pic->date > youngest_pict->date ) + youngest_pict = pic; + } + + if( !youngest_pict || !oldest_pict ) + return; + + /* Try to find if we can reduce the pts + * This first draft is way to simple, and we can't say if the + * algo will converge. It's also full of constants. + * But this simple algo allows to reduce the latency + * to the minimum. + * The whole point of this, is to bypass the pts_delay set + * by the access but also the delay arbitraly set by + * the remote server. + * Actually the remote server's muxer may set up a + * pts<->dts delay in the muxed stream. That is + * why we may end up in having a negative pts_delay, + * to compensate that artificial delay. */ + mtime_t buffer_size = youngest_pict->date - oldest_pict->date; + int64_t pts_slide = 0; + if( buffer_size < 10000 ) + { + if( p_priv->pts_adjust.i_num_faulty > 10 ) + { + pts_slide = __MAX(p_input->i_pts_delay *3 / 2, 10000); + p_priv->pts_adjust.i_num_faulty = 0; + } + if( p_priv->pts_adjust.to_high ) + { + p_priv->pts_adjust.to_high = !p_priv->pts_adjust.to_high; + p_priv->pts_adjust.i_num_faulty = 0; + } + p_priv->pts_adjust.i_num_faulty++; + } + else if( buffer_size > 100000 ) + { + if( p_priv->pts_adjust.i_num_faulty > 25 ) + { + pts_slide = -buffer_size/2; + p_priv->pts_adjust.i_num_faulty = 0; + } + if( p_priv->pts_adjust.to_high ) + { + p_priv->pts_adjust.to_high = !p_priv->pts_adjust.to_high; + p_priv->pts_adjust.i_num_faulty = 0; + } + p_priv->pts_adjust.i_num_faulty++; + } + if( pts_slide ) + { + mtime_t origi_delay = p_input->i_pts_delay; + + p_input->i_pts_delay += pts_slide; + + /* Don't play with the pts delay for more than -2<->3sec */ + if( p_input->i_pts_delay < -2000000 ) + p_input->i_pts_delay = -2000000; + else if( p_input->i_pts_delay > 3000000 ) + p_input->i_pts_delay = 3000000; + pts_slide = p_input->i_pts_delay - origi_delay; + + msg_Dbg( p_input, "Sliding the pts by %dms pts delay at %dms picture buffer was %dms", + (int)pts_slide/1000, (int)p_input->i_pts_delay/1000, (int)buffer_size/1000); + + vlc_mutex_lock( &p_vout->picture_lock ); + /* Slide all the picture */ + for( i = 0; i < I_RENDERPICTURES; i++ ) + PP_RENDERPICTURE[i]->date += pts_slide; + /* FIXME: slide aout/spu */ + vlc_mutex_unlock( &p_vout->picture_lock ); + + } +} + static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) { input_thread_t *p_input = p_dec->p_owner->p_input; @@ -729,6 +836,14 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) ) { + if( p_dec->b_die ) + { + /* It prevent freezing VLC in case of broken decoder */ + if( p_block ) + block_Release( p_block ); + break; + } + vlc_mutex_lock( &p_input->p->counters.counters_lock ); stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_video, 1, NULL ); vlc_mutex_unlock( &p_input->p->counters.counters_lock ); @@ -753,6 +868,9 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) vout_DatePicture( p_dec->p_owner->p_vout, p_pic, p_pic->date ); + + optimize_video_pts( p_dec ); + vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic ); } } @@ -775,6 +893,7 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block ) return VLC_SUCCESS; } +#ifdef ENABLE_SOUT if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER ) { block_t *p_sout_block; @@ -829,7 +948,7 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block ) p_sout_block = p_next; } - /* For now it's enough, as only sout inpact on this flag */ + /* For now it's enough, as only sout impact on this flag */ if( p_dec->p_owner->p_sout->i_out_pace_nocontrol > 0 && p_dec->p_owner->p_input->p->b_out_pace_control ) { @@ -844,7 +963,9 @@ static int DecoderDecode( decoder_t *p_dec, block_t *p_block ) } } } - else if( p_dec->fmt_in.i_cat == AUDIO_ES ) + else +#endif + if( p_dec->fmt_in.i_cat == AUDIO_ES ) { if( p_block ) DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block ); @@ -979,7 +1100,11 @@ static void DeleteDecoder( decoder_t * p_dec ) /* Cleanup */ if( p_dec->p_owner->p_aout_input ) aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input ); - + if( p_dec->p_owner->p_aout ) + { + vlc_object_release( p_dec->p_owner->p_aout ); + p_dec->p_owner->p_aout = NULL; + } if( p_dec->p_owner->p_vout ) { int i_pic; @@ -1000,11 +1125,13 @@ static void DeleteDecoder( decoder_t * p_dec ) vout_Request( p_dec, p_dec->p_owner->p_vout, 0 ); } +#ifdef ENABLE_SOUT if( p_dec->p_owner->p_sout_input ) { sout_InputDelete( p_dec->p_owner->p_sout_input ); es_format_Clean( &p_dec->p_owner->sout ); } +#endif if( p_dec->fmt_in.i_cat == SPU_ES ) {