]> git.sesse.net Git - vlc/blobdiff - src/input/decoder.c
Fix popupSave/Stream deadlock
[vlc] / src / input / decoder.c
index 4a5eeff1d979d653594e2742c089ad15efebbb31..96da051d0677c7aa1272551069addf1680b80d38 100644 (file)
 #include <vlc_codec.h>
 #include <vlc_osd.h>
 #include <vlc_meta.h>
+#include <vlc_dialog.h>
 
-#include <vlc_interface.h>
 #include "audio_output/aout_internal.h"
 #include "stream_output/stream_output.h"
 #include "input_internal.h"
 #include "clock.h"
 #include "decoder.h"
 #include "event.h"
-#include "ressource.h"
+#include "resource.h"
 
 #include "../video_output/vout_control.h"
 
@@ -77,8 +77,6 @@ static void vout_unlink_picture( decoder_t *, picture_t * );
 static subpicture_t *spu_new_buffer( decoder_t * );
 static void spu_del_buffer( decoder_t *, subpicture_t * );
 
-static es_format_t null_es_format;
-
 struct decoder_owner_sys_t
 {
     int64_t         i_preroll_end;
@@ -276,8 +274,8 @@ decoder_t *input_DecoderNew( input_thread_t *p_input,
         if( p_dec == NULL )
         {
             msg_Err( p_input, "could not create packetizer" );
-            intf_UserFatal( p_input, false, _("Streaming / Transcoding failed"),
-                            _("VLC could not open the packetizer module.") );
+            dialog_Fatal( p_input, _("Streaming / Transcoding failed"),
+                          _("VLC could not open the packetizer module.") );
             return NULL;
         }
     }
@@ -289,8 +287,8 @@ decoder_t *input_DecoderNew( input_thread_t *p_input,
         if( p_dec == NULL )
         {
             msg_Err( p_input, "could not create decoder" );
-            intf_UserFatal( p_input, false, _("Streaming / Transcoding failed"),
-                            _("VLC could not open the decoder module.") );
+            dialog_Fatal( p_input, _("Streaming / Transcoding failed"),
+                          _("VLC could not open the decoder module.") );
             return NULL;
         }
     }
@@ -305,8 +303,9 @@ decoder_t *input_DecoderNew( input_thread_t *p_input,
     }
 
     p_dec->p_owner->p_clock = p_clock;
+    assert( p_dec->fmt_out.i_cat != UNKNOWN_ES );
 
-    if( fmt->i_cat == AUDIO_ES )
+    if( p_dec->fmt_out.i_cat == AUDIO_ES )
         i_priority = VLC_THREAD_PRIORITY_AUDIO;
     else
         i_priority = VLC_THREAD_PRIORITY_VIDEO;
@@ -441,8 +440,8 @@ int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel )
         if( !p_cc )
         {
             msg_Err( p_dec, "could not create decoder" );
-            intf_UserFatal( p_dec, false, _("Streaming / Transcoding failed"),
-                            _("VLC could not open the decoder module.") );
+            dialog_Fatal( p_dec, _("Streaming / Transcoding failed"),
+                          _("VLC could not open the decoder module.") );
             return VLC_EGENERIC;
         }
         else if( !p_cc->p_module )
@@ -588,7 +587,7 @@ void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
     *pi_duration = 0;
 
     vlc_mutex_lock( &p_owner->lock );
-    if( p_dec->fmt_in.i_cat == VIDEO_ES )
+    if( p_dec->fmt_out.i_cat == VIDEO_ES )
     {
         if( p_owner->b_paused && p_owner->p_vout )
         {
@@ -675,9 +674,10 @@ static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
     msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
              "VLC probably does not support this sound or video format.",
              (char*)&codec );
-    intf_UserFatal( p_dec, false, _("No suitable decoder module"), 
-                    _("VLC does not support the audio or video format \"%4.4s\". "
-                      "Unfortunately there is no way for you to fix this."), (char*)&codec );
+    dialog_Fatal( p_dec, _("No suitable decoder module"),
+                 _("VLC does not support the audio or video format \"%4.4s\". "
+                  "Unfortunately there is no way for you to fix this."),
+                  (char*)&codec );
 }
 
 
@@ -694,6 +694,8 @@ static decoder_t * CreateDecoder( input_thread_t *p_input,
 {
     decoder_t *p_dec;
     decoder_owner_sys_t *p_owner;
+    es_format_t null_es_format;
+
     int i;
 
     p_dec = vlc_object_create( p_input, i_object_type );
@@ -888,10 +890,23 @@ static void *DecoderThread( vlc_object_t *p_this )
     return NULL;
 }
 
+static block_t *DecoderBlockFlushNew()
+{
+    block_t *p_null = block_Alloc( 128 );
+    if( !p_null )
+        return NULL;
+
+    p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY |
+                       BLOCK_FLAG_CORRUPTED |
+                       BLOCK_FLAG_CORE_FLUSH;
+    memset( p_null->p_buffer, 0, p_null->i_buffer );
+
+    return p_null;
+}
+
 static void DecoderFlush( decoder_t *p_dec )
 {
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
-    block_t *p_null;
 
     vlc_assert_locked( &p_owner->lock );
 
@@ -903,15 +918,9 @@ static void DecoderFlush( decoder_t *p_dec )
     vlc_cond_signal( &p_owner->wait );
 
     /* Send a special block */
-    p_null = block_New( p_dec, 128 );
+    block_t *p_null = DecoderBlockFlushNew();
     if( !p_null )
         return;
-    p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY;
-    p_null->i_flags |= BLOCK_FLAG_CORE_FLUSH;
-    if( !p_dec->fmt_in.b_packetized )
-        p_null->i_flags |= BLOCK_FLAG_CORRUPTED;
-    memset( p_null->p_buffer, 0, p_null->i_buffer );
-
     input_DecoderDecode( p_dec, p_null );
 
     /* */
@@ -1004,13 +1013,13 @@ static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i
      * - for sout it is useless
      * - for subs, it is done by the vout
      */
-    if( p_dec->fmt_in.i_cat == AUDIO_ES )
+    if( p_dec->fmt_out.i_cat == AUDIO_ES )
     {
         if( p_owner->p_aout && p_owner->p_aout_input )
             aout_DecChangePause( p_owner->p_aout, p_owner->p_aout_input,
                                  b_paused, i_date );
     }
-    else if( p_dec->fmt_in.i_cat == VIDEO_ES )
+    else if( p_dec->fmt_out.i_cat == VIDEO_ES )
     {
         if( p_owner->p_vout )
             vout_ChangePause( p_owner->p_vout, b_paused, i_date );
@@ -1020,10 +1029,10 @@ static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
 {
     if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
         *pi_preroll = INT64_MAX;
-    else if( p->i_pts > 0 )
-        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
     else if( p->i_dts > 0 )
         *pi_preroll = __MIN( *pi_preroll, p->i_dts );
+    else if( p->i_pts > 0 )
+        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
 }
 
 static mtime_t DecoderTeletextFixTs( mtime_t i_ts )
@@ -1060,7 +1069,8 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
             *pi_ts0 += i_es_delay;
             if( pi_ts1 && *pi_ts1 > 0 )
                 *pi_ts1 += i_es_delay;
-            input_clock_ConvertTS( p_clock, &i_rate, pi_ts0, pi_ts1, i_ts_bound );
+            if( input_clock_ConvertTS( p_clock, &i_rate, pi_ts0, pi_ts1, i_ts_bound ) )
+                *pi_ts0 = 0;
         }
         else
         {
@@ -1795,6 +1805,14 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flus
                 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 if( p_block )
     {
@@ -1835,6 +1853,14 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flus
                 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 )
+                DecoderDecodeAudio( p_dec, p_null );
+        }
     }
     else if( p_block )
     {
@@ -1862,7 +1888,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
         stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
         vlc_mutex_unlock( &p_input->p->counters.counters_lock );
 
-        p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
+        p_vout = input_resource_HoldVout( p_input->p->p_resource );
         if( p_vout && p_owner->p_spu_vout == p_vout )
         {
             /* Preroll does not work very well with subtitle */
@@ -1887,7 +1913,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
 
     if( b_flush && p_owner->p_spu_vout )
     {
-        p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
+        p_vout = input_resource_HoldVout( p_input->p->p_resource );
 
         if( p_vout && p_owner->p_spu_vout == p_vout )
             spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
@@ -1951,15 +1977,15 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
             p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;
         }
 
-        if( p_dec->fmt_in.i_cat == AUDIO_ES )
+        if( p_dec->fmt_out.i_cat == AUDIO_ES )
         {
             DecoderProcessAudio( p_dec, p_block, b_flush );
         }
-        else if( p_dec->fmt_in.i_cat == VIDEO_ES )
+        else if( p_dec->fmt_out.i_cat == VIDEO_ES )
         {
             DecoderProcessVideo( p_dec, p_block, b_flush );
         }
-        else if( p_dec->fmt_in.i_cat == SPU_ES )
+        else if( p_dec->fmt_out.i_cat == SPU_ES )
         {
             DecoderProcessSpu( p_dec, p_block, b_flush );
         }
@@ -2016,7 +2042,7 @@ static void DeleteDecoder( decoder_t * p_dec )
         aout_DecDelete( p_owner->p_aout, p_owner->p_aout_input );
     if( p_owner->p_aout )
     {
-        input_ressource_RequestAout( p_owner->p_input->p->p_ressource,
+        input_resource_RequestAout( p_owner->p_input->p->p_resource,
                                      p_owner->p_aout );
         input_SendEventAout( p_owner->p_input );
         p_owner->p_aout = NULL;
@@ -2030,7 +2056,7 @@ static void DeleteDecoder( decoder_t * p_dec )
             vout_ChangePause( p_owner->p_vout, false, mdate() );
 
         /* */
-        input_ressource_RequestVout( p_owner->p_input->p->p_ressource, p_owner->p_vout, NULL );
+        input_resource_RequestVout( p_owner->p_input->p->p_resource, p_owner->p_vout, NULL, true );
         input_SendEventVout( p_owner->p_input );
     }
 
@@ -2042,11 +2068,11 @@ static void DeleteDecoder( decoder_t * p_dec )
     }
 #endif
 
-    if( p_dec->fmt_in.i_cat == SPU_ES )
+    if( p_dec->fmt_out.i_cat == SPU_ES )
     {
         vout_thread_t *p_vout;
 
-        p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
+        p_vout = input_resource_HoldVout( p_owner->p_input->p->p_resource );
         if( p_vout )
         {
             if( p_owner->p_spu_vout == p_vout )
@@ -2105,12 +2131,13 @@ static void DecoderUpdateFormatLocked( decoder_t *p_dec )
     p_dec->p_description = NULL;
 }
 static vout_thread_t *aout_request_vout( void *p_private,
-                                         vout_thread_t *p_vout, video_format_t *p_fmt )
+                                         vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recyle )
 {
     decoder_t *p_dec = p_private;
+    input_thread_t *p_input = p_dec->p_owner->p_input;
 
-    p_vout = input_ressource_RequestVout( p_dec->p_owner->p_input->p->p_ressource, p_vout, p_fmt );
-    input_SendEventVout( p_dec->p_owner->p_input );
+    p_vout = input_resource_RequestVout( p_input->p->p_resource, p_vout, p_fmt, b_recyle );
+    input_SendEventVout( p_input );
 
     return p_vout;
 }
@@ -2173,7 +2200,7 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
 
         p_aout = p_owner->p_aout;
         if( !p_aout )
-            p_aout = input_ressource_RequestAout( p_owner->p_input->p->p_ressource, NULL );
+            p_aout = input_resource_RequestAout( p_owner->p_input->p->p_resource, NULL );
         p_aout_input = aout_DecNew( p_dec, &p_aout,
                                     &format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
 
@@ -2287,8 +2314,8 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
         p_owner->p_vout = NULL;
         vlc_mutex_unlock( &p_owner->lock );
 
-        p_vout = input_ressource_RequestVout( p_owner->p_input->p->p_ressource,
-                                              p_vout, &p_dec->fmt_out.video );
+        p_vout = input_resource_RequestVout( p_owner->p_input->p->p_resource,
+                                              p_vout, &p_dec->fmt_out.video, true );
 
         vlc_mutex_lock( &p_owner->lock );
         p_owner->p_vout = p_vout;
@@ -2375,7 +2402,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec )
         if( p_dec->b_die || p_dec->b_error )
             break;
 
-        p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
+        p_vout = input_resource_HoldVout( p_owner->p_input->p->p_resource );
         if( p_vout )
             break;
 
@@ -2420,7 +2447,7 @@ static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
     decoder_owner_sys_t *p_owner = p_dec->p_owner;
     vout_thread_t *p_vout = NULL;
 
-    p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
+    p_vout = input_resource_HoldVout( p_owner->p_input->p->p_resource );
     if( !p_vout || p_owner->p_spu_vout != p_vout )
     {
         if( p_vout )