[vlc-devel] [PATCH 2/4] decoder: add decoder_QueueVideo
Thomas Guillem
thomas at gllm.fr
Fri Dec 4 14:35:14 CET 2015
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.
---
include/vlc_codec.h | 23 +++++++++++++
src/input/decoder.c | 98 ++++++++++++++++++++++++++++++++++-------------------
2 files changed, 87 insertions(+), 34 deletions(-)
diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index 81090ba..d55e966 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -121,6 +121,9 @@ struct decoder_t
* XXX use decoder_GetDisplayRate */
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 */
decoder_owner_sys_t *p_owner;
@@ -239,6 +242,26 @@ static inline picture_t *decoder_NewPicture( decoder_t *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
* format (fmt_out.audio). If there is currently no audio output or if the
* audio output format has changed, a new audio output will be set up.
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 821f9a8..a793add 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -888,50 +888,45 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
*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;
- picture_t *p_pic;
- int i_lost = 0;
- int i_decoded = 0;
- int i_displayed = 0;
+ vout_thread_t *p_vout = p_owner->p_vout;
- 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;
-
- i_decoded++;
-
- 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;
- }
+ vlc_mutex_unlock( &p_owner->lock );
+ picture_Release( p_pic );
+ return -1;
+ }
- if( p_owner->i_preroll_end > VLC_TS_INVALID )
- {
- msg_Dbg( p_dec, "End of video preroll" );
- p_owner->i_preroll_end = VLC_TS_INVALID;
- vlc_mutex_unlock( &p_owner->lock );
- /* */
- if( p_vout )
- vout_Flush( p_vout, VLC_TS_INVALID+1 );
- }
- else
- vlc_mutex_unlock( &p_owner->lock );
+ if( p_owner->i_preroll_end > VLC_TS_INVALID )
+ {
+ msg_Dbg( p_dec, "End of video preroll" );
+ p_owner->i_preroll_end = VLC_TS_INVALID;
+ vlc_mutex_unlock( &p_owner->lock );
+ /* */
+ if( p_vout )
+ vout_Flush( p_vout, VLC_TS_INVALID+1 );
+ }
+ else
+ vlc_mutex_unlock( &p_owner->lock );
- if( p_dec->pf_get_cc &&
- ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
- DecoderGetCc( p_dec, p_dec );
+ 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 );
- }
+ 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;
+ /* Update ugly stat */
if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_displayed > 0) )
{
vlc_mutex_lock( &p_input->p->counters.counters_lock );
@@ -943,6 +938,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
*/
static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block )
@@ -1532,6 +1561,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_dec->pf_get_attachments = DecoderGetInputAttachments;
p_dec->pf_get_display_date = DecoderGetDisplayDate;
p_dec->pf_get_display_rate = DecoderGetDisplayRate;
+ p_dec->pf_queue_video = DecoderQueueVideo;
/* Load a packetizer module if the input is not already packetized */
if( p_sout == NULL && !fmt->b_packetized )
--
2.1.4
More information about the vlc-devel
mailing list