Commit 0f01756e authored by Thomas Guillem's avatar Thomas Guillem Committed by Rémi Denis-Courmont

decoder: add decoder_QueueVideo

This function allow asynchronous decoders to queue a picture to the video
output. Decoders that use this function should return NULL in pf_decode_video
callback.
Signed-off-by: default avatarRémi Denis-Courmont <remi@remlab.net>
parent d0a163c5
...@@ -121,6 +121,9 @@ struct decoder_t ...@@ -121,6 +121,9 @@ struct decoder_t
* XXX use decoder_GetDisplayRate */ * XXX use decoder_GetDisplayRate */
int (*pf_get_display_rate)( decoder_t * ); int (*pf_get_display_rate)( decoder_t * );
/* XXX use decoder_QueueVideo */
int (*pf_queue_video)( decoder_t *, picture_t * );
/* Private structure for the owner of the decoder */ /* Private structure for the owner of the decoder */
decoder_owner_sys_t *p_owner; decoder_owner_sys_t *p_owner;
...@@ -238,6 +241,26 @@ static inline picture_t *decoder_NewPicture( decoder_t *dec ) ...@@ -238,6 +241,26 @@ static inline picture_t *decoder_NewPicture( decoder_t *dec )
return decoder_GetPicture( dec ); return decoder_GetPicture( dec );
} }
/**
* This function queues a picture to the video output.
*
* \note
* The caller doesn't own the picture anymore after this call (even in case of
* error).
* FIXME: input_DecoderFrameNext won't work if a module use this function.
*
* \return 0 if the picture is queued, -1 on error
*/
static inline int decoder_QueueVideo( decoder_t *dec, picture_t *p_pic )
{
if( !dec->pf_queue_video )
{
picture_Release( p_pic );
return -1;
}
return dec->pf_queue_video( dec, p_pic );
}
/** /**
* This function notifies the audio output pipeline of a new audio output * This function notifies the audio output pipeline of a new audio output
* format (fmt_out.audio). If there is currently no audio output or if the * format (fmt_out.audio). If there is currently no audio output or if the
......
...@@ -894,50 +894,45 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, ...@@ -894,50 +894,45 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
*pi_lost_sum += i_tmp_lost; *pi_lost_sum += i_tmp_lost;
} }
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) static int DecoderPreparePlayVideo( decoder_t *p_dec, picture_t *p_pic )
{ {
decoder_owner_sys_t *p_owner = p_dec->p_owner; decoder_owner_sys_t *p_owner = p_dec->p_owner;
picture_t *p_pic; vout_thread_t *p_vout = p_owner->p_vout;
int i_lost = 0;
int i_decoded = 0;
int i_displayed = 0;
while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) ) vlc_mutex_lock( &p_owner->lock );
if( p_owner->i_preroll_end > VLC_TS_INVALID && p_pic->date < p_owner->i_preroll_end )
{ {
vout_thread_t *p_vout = p_owner->p_vout; vlc_mutex_unlock( &p_owner->lock );
picture_Release( p_pic );
i_decoded++; return -1;
}
vlc_mutex_lock( &p_owner->lock );
if( p_owner->i_preroll_end > VLC_TS_INVALID && p_pic->date < p_owner->i_preroll_end )
{
vlc_mutex_unlock( &p_owner->lock );
picture_Release( p_pic );
continue;
}
if( p_owner->i_preroll_end > VLC_TS_INVALID ) if( p_owner->i_preroll_end > VLC_TS_INVALID )
{ {
msg_Dbg( p_dec, "End of video preroll" ); msg_Dbg( p_dec, "End of video preroll" );
p_owner->i_preroll_end = VLC_TS_INVALID; p_owner->i_preroll_end = VLC_TS_INVALID;
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
/* */ /* */
if( p_vout ) if( p_vout )
vout_Flush( p_vout, VLC_TS_INVALID+1 ); vout_Flush( p_vout, VLC_TS_INVALID+1 );
} }
else else
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
if( p_dec->pf_get_cc && if( p_dec->pf_get_cc &&
( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) ) ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
DecoderGetCc( p_dec, p_dec ); DecoderGetCc( p_dec, p_dec );
DecoderPlayVideo( p_dec, p_pic, &i_displayed, &i_lost ); return 0;
} }
/* Update ugly stat */ static void DecoderUpdateStatVideo( decoder_t *p_dec, int i_decoded,
int i_lost, int i_displayed )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
input_thread_t *p_input = p_owner->p_input; input_thread_t *p_input = p_owner->p_input;
/* Update ugly stat */
if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_displayed > 0) ) if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_displayed > 0) )
{ {
vlc_mutex_lock( &p_input->p->counters.counters_lock ); vlc_mutex_lock( &p_input->p->counters.counters_lock );
...@@ -949,6 +944,40 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) ...@@ -949,6 +944,40 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
} }
} }
static int DecoderQueueVideo( decoder_t *p_dec, picture_t *p_pic )
{
assert( p_pic );
int i_lost = 0;
int i_displayed = 0;
int i_ret;
if( ( i_ret = DecoderPreparePlayVideo( p_dec, p_pic ) ) == 0 )
DecoderPlayVideo( p_dec, p_pic, &i_displayed, &i_lost );
DecoderUpdateStatVideo( p_dec, 1, i_lost, i_displayed );
return i_ret;
}
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{
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 )) )
{
i_decoded++;
if( DecoderPreparePlayVideo( p_dec, p_pic ) != 0 )
continue;
DecoderPlayVideo( p_dec, p_pic, &i_displayed, &i_lost );
}
DecoderUpdateStatVideo( p_dec, i_decoded, i_lost, i_displayed );
}
/* This function process a video block /* This function process a video block
*/ */
static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block ) static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block )
...@@ -1533,6 +1562,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, ...@@ -1533,6 +1562,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_dec->pf_get_attachments = DecoderGetInputAttachments; p_dec->pf_get_attachments = DecoderGetInputAttachments;
p_dec->pf_get_display_date = DecoderGetDisplayDate; p_dec->pf_get_display_date = DecoderGetDisplayDate;
p_dec->pf_get_display_rate = DecoderGetDisplayRate; p_dec->pf_get_display_rate = DecoderGetDisplayRate;
p_dec->pf_queue_video = DecoderQueueVideo;
/* Load a packetizer module if the input is not already packetized */ /* Load a packetizer module if the input is not already packetized */
if( p_sout == NULL && !fmt->b_packetized ) if( p_sout == NULL && !fmt->b_packetized )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment