]> git.sesse.net Git - vlc/blobdiff - src/input/decoder.c
Fixed OS-X compilation.
[vlc] / src / input / decoder.c
index 87d5dc88ee738a5674667ff5614c34b9ba52fa46..c61d07f0fdb00d9edd2d9e17147a3248dda049f8 100644 (file)
@@ -46,6 +46,7 @@
 #include "input_internal.h"
 #include "clock.h"
 #include "decoder.h"
+#include "event.h"
 
 #include "../video_output/vout_control.h"
 
@@ -53,7 +54,8 @@ static decoder_t *CreateDecoder( input_thread_t *, es_format_t *, int, sout_inst
 static void       DeleteDecoder( decoder_t * );
 
 static void      *DecoderThread( vlc_object_t * );
-static int        DecoderProcess( decoder_t *, block_t * );
+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 );
@@ -98,6 +100,10 @@ struct decoder_owner_sys_t
     audio_format_t audio;
     es_format_t    sout;
 
+    /* */
+    bool           b_fmt_description;
+    es_format_t    fmt_description;
+
     /* fifo */
     block_fifo_t *p_fifo;
 
@@ -329,14 +335,12 @@ void input_DecoderDelete( decoder_t *p_dec )
 
     vlc_object_kill( p_dec );
 
-    /* Make sure we aren't paused anymore */
+    /* Make sure we aren't paused/buffering/waiting anymore */
     vlc_mutex_lock( &p_owner->lock );
-    if( p_owner->b_paused || p_owner->b_buffering )
-    {
-        p_owner->b_paused = false;
-        p_owner->b_buffering = false;
-        vlc_cond_signal( &p_owner->wait );
-    }
+    p_owner->b_paused = false;
+    p_owner->b_buffering = false;
+    p_owner->b_flushing = true;
+    vlc_cond_signal( &p_owner->wait );
     vlc_mutex_unlock( &p_owner->lock );
 
     vlc_thread_join( p_dec );
@@ -370,7 +374,12 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block )
 
     if( p_owner->p_input->p->b_out_pace_control )
     {
-        block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
+        /* 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 );
     }
     else if( block_FifoSize( p_owner->p_fifo ) > 50000000 /* 50 MB */ )
     {
@@ -566,6 +575,7 @@ void input_DecoderWaitBuffering( decoder_t *p_dec )
 
     vlc_mutex_unlock( &p_owner->lock );
 }
+
 void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
@@ -590,6 +600,23 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
     vlc_mutex_unlock( &p_owner->lock );
 }
 
+bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+    bool b_changed;
+
+    vlc_mutex_lock( &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 );
+        p_owner->b_fmt_description = false;
+    }
+    vlc_mutex_unlock( &p_owner->lock );
+    return b_changed;
+}
+
 /*****************************************************************************
  * Internal functions
  *****************************************************************************/
@@ -768,6 +795,9 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
     vlc_mutex_init( &p_owner->lock );
     vlc_cond_init( &p_owner->wait );
 
+    p_owner->b_fmt_description = false;
+    es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 );
+
     p_owner->b_paused = false;
     p_owner->pause.i_date = 0;
     p_owner->pause.i_ignore = 0;
@@ -822,10 +852,14 @@ static void *DecoderThread( vlc_object_t *p_this )
 
         if( p_block )
         {
+            int canc = vlc_savecancel();
+
             if( p_dec->b_error )
-                block_Release( p_block );
+                DecoderError( p_dec, p_block );
             else
                 DecoderProcess( p_dec, p_block );
+
+            vlc_restorecancel( canc );
         }
     }
 
@@ -1114,12 +1148,23 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio,
             i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
             b_reject = true;
 
-        if( !b_reject )
+        /* Do not wait against unprotected date */
+        const mtime_t i_deadline = p_audio->start_date - AOUT_MAX_PREPARE_TIME;
+        while( !b_reject && i_deadline > mdate() )
         {
-            /* Wait if we are too early
-             * FIXME that's plain ugly to do it here */
-            mwait( p_audio->start_date - AOUT_MAX_PREPARE_TIME );
+            vlc_mutex_lock( &p_owner->lock );
+            if( p_owner->b_flushing || p_dec->b_die )
+            {
+                b_reject = true;
+                vlc_mutex_unlock( &p_owner->lock );
+                break;
+            }
+            vlc_cond_timedwait( &p_owner->wait, &p_owner->lock, i_deadline );
+            vlc_mutex_unlock( &p_owner->lock );
+        }
 
+        if( !b_reject )
+        {
             if( !aout_DecPlay( p_aout, p_aout_input, p_audio, i_rate ) )
                 *pi_played_sum += 1;
             *pi_lost_sum += aout_DecGetResetLost( p_aout, p_aout_input );
@@ -1854,6 +1899,17 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
     }
 }
 
+/* */
+static void DecoderProcessOnFlush( decoder_t *p_dec )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+    vlc_mutex_lock( &p_owner->lock );
+    DecoderFlushBuffering( p_dec );
+    vlc_mutex_unlock( &p_owner->lock );
+
+    DecoderSignalFlushed( p_dec );
+}
 /**
  * Decode a block
  *
@@ -1861,7 +1917,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
  * \param p_block the block to decode
  * \return VLC_SUCCESS or an error code
  */
-static int DecoderProcess( decoder_t *p_dec, block_t *p_block )
+static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
 {
     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);
@@ -1870,10 +1926,9 @@ static int DecoderProcess( decoder_t *p_dec, block_t *p_block )
     {
         assert( !b_flush_request );
         block_Release( p_block );
-        return VLC_SUCCESS;
+        return;
     }
 
-    int canc = vlc_savecancel();
 #ifdef ENABLE_SOUT
     if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
     {
@@ -1918,18 +1973,22 @@ static int DecoderProcess( decoder_t *p_dec, block_t *p_block )
 
     /* */
     if( b_flush_request )
-    {
-        vlc_mutex_lock( &p_owner->lock );
-        DecoderFlushBuffering( p_dec );
-        vlc_mutex_unlock( &p_owner->lock );
+        DecoderProcessOnFlush( p_dec );
+}
 
-        DecoderSignalFlushed( p_dec );
-    }
-    vlc_restorecancel( canc );
+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);
 
-    return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
+    /* */
+    if( p_block )
+        block_Release( p_block );
+
+    if( b_flush_request )
+        DecoderProcessOnFlush( p_dec );
 }
 
+
 /**
  * Destroys a decoder object
  *
@@ -1968,7 +2027,7 @@ static void DeleteDecoder( decoder_t * p_dec )
 
         /* We are about to die. Reattach video output to p_vlc. */
         vout_Request( p_dec, p_owner->p_vout, NULL );
-        var_SetBool( p_owner->p_input, "intf-change-vout", true );
+        input_SendEventVout( p_owner->p_input );
     }
 
 #ifdef ENABLE_SOUT
@@ -2005,6 +2064,8 @@ static void DeleteDecoder( decoder_t * p_dec )
         vlc_object_release( p_owner->p_packetizer );
     }
 
+    es_format_Clean( &p_owner->fmt_description );
+
     vlc_cond_destroy( &p_owner->wait );
     vlc_mutex_destroy( &p_owner->lock );
 
@@ -2016,6 +2077,28 @@ static void DeleteDecoder( decoder_t * p_dec )
 /*****************************************************************************
  * Buffers allocation callbacks for the decoders
  *****************************************************************************/
+static void DecoderUpdateFormatLocked( decoder_t *p_dec )
+{
+    decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+    vlc_assert_locked( &p_owner->lock );
+
+    es_format_Clean( &p_owner->fmt_description );
+
+    p_owner->b_fmt_description = true;
+    es_format_Copy( &p_owner->fmt_description, &p_dec->fmt_out );
+}
+static vout_thread_t *aout_request_vout( void *p_private,
+                                         vout_thread_t *p_vout, video_format_t *p_fmt )
+{
+    decoder_t *p_dec = p_private;
+
+    p_vout =  vout_Request( p_dec, p_vout, p_fmt );
+    input_SendEventVout( p_dec->p_owner->p_input );
+
+    return p_vout;
+}
+
 static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
@@ -2047,6 +2130,7 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
         audio_sample_format_t format;
         aout_input_t *p_aout_input;
         aout_instance_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;
@@ -2068,13 +2152,19 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
             }
         }
 
+        request_vout.pf_request_vout = aout_request_vout;
+        request_vout.p_private = p_dec;
+
         p_aout = p_owner->p_aout;
         p_aout_input = aout_DecNew( p_dec, &p_aout,
-                                    &format, &p_dec->fmt_out.audio_replay_gain );
+                                    &format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
 
         vlc_mutex_lock( &p_owner->lock );
+
         p_owner->p_aout = p_aout;
         p_owner->p_aout_input = p_aout_input;
+        DecoderUpdateFormatLocked( p_dec );
+
         vlc_mutex_unlock( &p_owner->lock );
 
         if( p_owner->p_aout_input == NULL )
@@ -2181,9 +2271,12 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
 
         vlc_mutex_lock( &p_owner->lock );
         p_owner->p_vout = p_vout;
+
+        DecoderUpdateFormatLocked( p_dec );
+
         vlc_mutex_unlock( &p_owner->lock );
 
-        var_SetBool( p_owner->p_input, "intf-change-vout", true );
+        input_SendEventVout( p_owner->p_input );
         if( p_vout == NULL )
         {
             msg_Err( p_dec, "failed to create video output" );