+ /* */
+ 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( i_rate != p_owner->i_last_rate || b_first_after_wait )
+ {
+ /* 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
+ msg_Warn( p_dec, "non-dated video buffer received" );
+
+ *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 )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+ picture_t *p_pic;
+ int i_lost = 0;
+ int i_decoded = 0;
+ int i_displayed = 0;
+
+ while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
+ {
+ vout_thread_t *p_vout = p_owner->p_vout;
+ if( DecoderIsFlushing( p_dec ) )
+ { /* It prevent freezing VLC in case of broken decoder */
+ picture_Release( p_pic );
+ if( p_block )
+ block_Release( p_block );
+ break;
+ }
+
+ i_decoded++;
+
+ if( p_owner->i_preroll_end > VLC_TS_INVALID && p_pic->date < p_owner->i_preroll_end )
+ {
+ picture_Release( p_pic );
+ continue;
+ }
+
+ if( p_owner->i_preroll_end > VLC_TS_INVALID )
+ {
+ msg_Dbg( p_dec, "End of video preroll" );
+ if( p_vout )
+ vout_Flush( p_vout, VLC_TS_INVALID+1 );
+ /* */
+ p_owner->i_preroll_end = VLC_TS_INVALID;
+ }
+
+ if( p_dec->pf_get_cc &&
+ ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
+ DecoderGetCc( p_dec, p_dec );
+
+ DecoderPlayVideo( p_dec, p_pic, &i_displayed, &i_lost );
+ }
+
+ /* Update ugly stat */
+ input_thread_t *p_input = p_owner->p_input;
+
+ if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_displayed > 0) )
+ {
+ vlc_mutex_lock( &p_input->p->counters.counters_lock );
+ stats_Update( p_input->p->counters.p_decoded_video, i_decoded, NULL );
+ stats_Update( p_input->p->counters.p_lost_pictures, i_lost , NULL);
+ stats_Update( p_input->p->counters.p_displayed_pictures,
+ i_displayed, NULL);
+ vlc_mutex_unlock( &p_input->p->counters.counters_lock );
+ }
+}
+
+/* This function process a video block
+ */
+static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flush )
+{
+ decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
+
+ 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 )) )
+ {
+ 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 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 );
+
+ 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 );
+
+ p_packetized_block = p_next;
+ }
+ }
+ /* The packetizer does not output a block that tell the decoder to flush
+ * do it ourself */
+ if( b_flush )
+ {
+ block_t *p_null = DecoderBlockFlushNew();
+ if( p_null )
+ DecoderDecodeVideo( p_dec, p_null );
+ }
+ }
+ else
+ {
+ DecoderDecodeVideo( p_dec, p_block );
+ }
+
+ if( b_flush && p_owner->p_vout )
+ vout_Flush( p_owner->p_vout, VLC_TS_INVALID+1 );
+}
+
+static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
+ int *pi_played_sum, int *pi_lost_sum )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+ audio_output_t *p_aout = p_owner->p_aout;
+
+ /* */
+ if( p_audio && p_audio->i_pts <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/*
+ {
+ msg_Warn( p_dec, "non-dated audio buffer received" );
+ *pi_lost_sum += 1;
+ block_Release( p_audio );
+ return;
+ }
+
+ /* */
+ vlc_mutex_lock( &p_owner->lock );
+
+ if( p_audio && p_owner->b_waiting )
+ {
+ p_owner->b_has_data = true;
+ vlc_cond_signal( &p_owner->wait_acknowledge );
+ }
+
+ for( ;; )
+ {
+ bool b_paused;
+
+ bool b_reject = DecoderWaitUnblock( p_dec );
+
+ b_paused = p_owner->b_paused;
+
+ if (!p_audio)
+ break;
+
+ /* */
+ int i_rate = INPUT_RATE_DEFAULT;
+
+ DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
+ &i_rate, AOUT_MAX_ADVANCE_TIME );
+
+ if( p_audio->i_pts <= VLC_TS_INVALID
+ || i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE
+ || i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
+ b_reject = true;
+
+ DecoderWaitDate( p_dec, &b_reject,
+ p_audio->i_pts - AOUT_MAX_PREPARE_TIME );
+
+ if( unlikely(p_owner->b_paused != b_paused) )
+ continue; /* race with input thread? retry... */
+ if( p_aout == NULL )
+ b_reject = true;