]> git.sesse.net Git - vlc/blobdiff - src/input/es_out.c
es_out: do not start buffering when already buferring
[vlc] / src / input / es_out.c
index e8eae0fe3777ffe81484fd9052fef1d2f7e97fa5..b2326435e9923971fbc862425f8078a860a0347c 100644 (file)
@@ -461,7 +461,7 @@ static int EsOutSetRecord(  es_out_t *out, bool b_record )
 
         if( !psz_sout && psz_path )
         {
-            char *psz_file = input_CreateFilename( VLC_OBJECT(p_input), psz_path, INPUT_RECORD_PREFIX, NULL );
+            char *psz_file = input_CreateFilename( p_input, psz_path, INPUT_RECORD_PREFIX, NULL );
             if( psz_file )
             {
                 if( asprintf( &psz_sout, "#record{dst-prefix='%s'}", psz_file ) < 0 )
@@ -491,7 +491,7 @@ static int EsOutSetRecord(  es_out_t *out, bool b_record )
 
             p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_sys->p_sout_record );
             if( p_es->p_dec_record && p_sys->b_buffering )
-                input_DecoderStartBuffering( p_es->p_dec_record );
+                input_DecoderStartWait( p_es->p_dec_record );
         }
     }
     else
@@ -573,13 +573,16 @@ static void EsOutChangePosition( es_out_t *out )
     {
         es_out_id_t *p_es = p_sys->es[i];
 
-        if( !p_es->p_dec )
-            continue;
-
-        input_DecoderStartBuffering( p_es->p_dec );
-
-        if( p_es->p_dec_record )
-            input_DecoderStartBuffering( p_es->p_dec_record );
+        if( p_es->p_dec != NULL )
+        {
+            input_DecoderFlush( p_es->p_dec );
+            if( !p_sys->b_buffering )
+            {
+                input_DecoderStartWait( p_es->p_dec );
+                if( p_es->p_dec_record != NULL )
+                    input_DecoderStartWait( p_es->p_dec_record );
+            }
+        }
     }
 
     for( int i = 0; i < p_sys->i_pgrm; i++ )
@@ -597,17 +600,14 @@ static void EsOutChangePosition( es_out_t *out )
 static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 {
     es_out_sys_t *p_sys = out->p_sys;
-    int i_ret;
 
     mtime_t i_stream_start;
     mtime_t i_system_start;
     mtime_t i_stream_duration;
     mtime_t i_system_duration;
-    i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
+    if (input_clock_GetState( p_sys->p_pgrm->p_clock,
                                   &i_stream_start, &i_system_start,
-                                  &i_stream_duration, &i_system_duration );
-    assert( !i_ret || b_forced );
-    if( i_ret )
+                                  &i_stream_duration, &i_system_duration ))
         return;
 
     mtime_t i_preroll_duration = 0;
@@ -620,7 +620,11 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 
     if( i_stream_duration <= i_buffering_duration && !b_forced )
     {
-        const double f_level = __MAX( (double)i_stream_duration / i_buffering_duration, 0 );
+        double f_level;
+        if (i_buffering_duration == 0)
+            f_level = 0;
+        else
+            f_level = __MAX( (double)i_stream_duration / i_buffering_duration, 0 );
         input_SendEventCache( p_sys->p_input, f_level );
 
         msg_Dbg( p_sys->p_input, "Buffering %d%%", (int)(100 * f_level) );
@@ -646,12 +650,12 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 
         if( !p_es->p_dec || p_es->fmt.i_cat == SPU_ES )
             continue;
-        input_DecoderWaitBuffering( p_es->p_dec );
+        input_DecoderWait( p_es->p_dec );
         if( p_es->p_dec_record )
-            input_DecoderWaitBuffering( p_es->p_dec_record );
+            input_DecoderWait( p_es->p_dec_record );
     }
 
-    msg_Dbg( p_sys->p_input, "Decoder buffering done in %d ms",
+    msg_Dbg( p_sys->p_input, "Decoder wait done in %d ms",
               (int)(mdate() - i_decoder_buffering_start)/1000 );
 
     /* Here is a good place to destroy unused vout with every demuxer */
@@ -671,9 +675,9 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
         if( !p_es->p_dec )
             continue;
 
-        input_DecoderStopBuffering( p_es->p_dec );
+        input_DecoderStopWait( p_es->p_dec );
         if( p_es->p_dec_record )
-            input_DecoderStopBuffering( p_es->p_dec_record );
+            input_DecoderStopWait( p_es->p_dec_record );
     }
 }
 static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
@@ -823,21 +827,19 @@ static void EsOutFrameNext( es_out_t *out )
 static mtime_t EsOutGetBuffering( es_out_t *out )
 {
     es_out_sys_t *p_sys = out->p_sys;
+    mtime_t i_stream_duration, i_system_start;
 
     if( !p_sys->p_pgrm )
         return 0;
+    else
+    {
+        mtime_t i_stream_start, i_system_duration;
 
-    int i_ret;
-    mtime_t i_stream_start;
-    mtime_t i_system_start;
-    mtime_t i_stream_duration;
-    mtime_t i_system_duration;
-    i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
+        if( input_clock_GetState( p_sys->p_pgrm->p_clock,
                                   &i_stream_start, &i_system_start,
-                                  &i_stream_duration, &i_system_duration );
-
-    if( i_ret )
-        return 0;
+                                  &i_stream_duration, &i_system_duration ) )
+            return 0;
+    }
 
     mtime_t i_delay;
 
@@ -848,6 +850,7 @@ static mtime_t EsOutGetBuffering( es_out_t *out )
     else
     {
         mtime_t i_system_duration;
+
         if( p_sys->b_paused )
         {
             i_system_duration = p_sys->i_pause_date  - i_system_start;
@@ -1012,7 +1015,7 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
     }
 
     /* Update now playing */
-    input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
+    input_item_SetESNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
     input_item_SetPublisher( p_input->p->p_item, p_pgrm->psz_publisher );
 
     input_SendEventMeta( p_input );
@@ -1154,7 +1157,7 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, const vlc_meta_t *p_me
 
     /* Check against empty meta data (empty for what we handle) */
     if( !vlc_meta_Get( p_meta, vlc_meta_Title) &&
-        !vlc_meta_Get( p_meta, vlc_meta_NowPlaying) &&
+        !vlc_meta_Get( p_meta, vlc_meta_ESNowPlaying) &&
         !vlc_meta_Get( p_meta, vlc_meta_Publisher) &&
         vlc_meta_GetExtraCount( p_meta ) <= 0 )
     {
@@ -1293,20 +1296,20 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, const vlc_epg_t *p_epg
 
     if( p_pgrm == p_sys->p_pgrm )
     {
-        input_item_SetNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
+        input_item_SetESNowPlaying( p_input->p->p_item, p_pgrm->psz_now_playing );
         input_SendEventMeta( p_input );
     }
 
     if( p_pgrm->psz_now_playing )
     {
         input_Control( p_input, INPUT_ADD_INFO, psz_cat,
-            vlc_meta_TypeToLocalizedString(vlc_meta_NowPlaying),
+            vlc_meta_TypeToLocalizedString(vlc_meta_ESNowPlaying), "%s",
             p_pgrm->psz_now_playing );
     }
     else
     {
         input_Control( p_input, INPUT_DEL_INFO, psz_cat,
-            vlc_meta_TypeToLocalizedString(vlc_meta_NowPlaying) );
+            vlc_meta_TypeToLocalizedString(vlc_meta_ESNowPlaying) );
     }
 
     free( psz_cat );
@@ -1344,48 +1347,34 @@ static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta )
 {
     es_out_sys_t    *p_sys = p_out->p_sys;
     input_thread_t  *p_input = p_sys->p_input;
-
     input_item_t *p_item = input_GetItem( p_input );
 
-    char *psz_title = NULL;
-    char *psz_arturl = input_item_GetArtURL( p_item );
+    if( vlc_meta_Get( p_meta, vlc_meta_Title ) != NULL )
+        input_item_SetName( p_item, vlc_meta_Get( p_meta, vlc_meta_Title ) );
 
-    vlc_mutex_lock( &p_item->lock );
-
-    if( vlc_meta_Get( p_meta, vlc_meta_Title ) && !p_item->b_fixed_name )
-        psz_title = strdup( vlc_meta_Get( p_meta, vlc_meta_Title ) );
+    char *psz_arturl = NULL;
+    if( vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL ) != NULL )
+        psz_arturl = input_item_GetArtURL( p_item ); /* save value */
 
+    vlc_mutex_lock( &p_item->lock );
     vlc_meta_Merge( p_item->p_meta, p_meta );
-
-    if( !psz_arturl || *psz_arturl == '\0' )
-    {
-        const char *psz_tmp = vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL );
-        if( psz_tmp )
-            psz_arturl = strdup( psz_tmp );
-    }
     vlc_mutex_unlock( &p_item->lock );
 
-    if( psz_arturl && *psz_arturl )
-    {
+    if( psz_arturl != NULL ) /* restore/favor previously set item art URL */
         input_item_SetArtURL( p_item, psz_arturl );
+    else
+        psz_arturl = input_item_GetArtURL( p_item );
 
-        if( !strncmp( psz_arturl, "attachment://", 13 ) )
-        {
-            /* Don't look for art cover if sout
-             * XXX It can change when sout has meta data support */
-            if( p_input->p->p_sout && !p_input->b_preparsing )
-                input_item_SetArtURL( p_item, "" );
-            else
-                input_ExtractAttachmentAndCacheArt( p_input );
-        }
+    if( psz_arturl != NULL && !strncmp( psz_arturl, "attachment://", 13 ) )
+    {   /* Clear art cover if streaming out.
+         * FIXME: Why? Remove this when sout gets meta data support. */
+        if( p_input->p->p_sout && !p_input->b_preparsing )
+            input_item_SetArtURL( p_item, NULL );
+        else
+            input_ExtractAttachmentAndCacheArt( p_input, psz_arturl + 13 );
     }
     free( psz_arturl );
 
-    if( psz_title )
-    {
-        input_item_SetName( p_item, psz_title );
-        free( psz_title );
-    }
     input_item_SetPreparsed( p_item, true );
 
     input_SendEventMeta( p_input );
@@ -1558,13 +1547,13 @@ static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es )
     if( p_es->p_dec )
     {
         if( p_sys->b_buffering )
-            input_DecoderStartBuffering( p_es->p_dec );
+            input_DecoderStartWait( p_es->p_dec );
 
         if( !p_es->p_master && p_sys->p_sout_record )
         {
             p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_clock, p_sys->p_sout_record );
             if( p_es->p_dec_record && p_sys->b_buffering )
-                input_DecoderStartBuffering( p_es->p_dec_record );
+                input_DecoderStartWait( p_es->p_dec_record );
         }
     }
 
@@ -1829,6 +1818,16 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
                         i_wanted = es->i_channel;
                 }
             }
+            else if ( es->fmt.i_codec == EsOutFourccClosedCaptions[0] ||
+                      es->fmt.i_codec == EsOutFourccClosedCaptions[1] ||
+                      es->fmt.i_codec == EsOutFourccClosedCaptions[2] ||
+                      es->fmt.i_codec == EsOutFourccClosedCaptions[3])
+            {
+                    /* We don't want to enable on initial create since p_master
+                       isn't set yet (otherwise we will think it's a standard
+                       ES_SUB stream and cause a resource leak) */
+                    return;
+            }
             else
             {
                 /* If there is no user preference, select the default subtitle 
@@ -1839,6 +1838,9 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
                     ( p_sys->p_es_sub && 
                       p_sys->p_es_sub->fmt.i_priority < es->fmt.i_priority ) )
                     i_wanted = es->i_channel;
+                else if( p_sys->p_es_sub &&
+                         p_sys->p_es_sub->fmt.i_priority >= es->fmt.i_priority )
+                    i_wanted = p_sys->p_es_sub->i_channel;
             }
 
             if( p_sys->i_sub_last >= 0 )
@@ -2010,6 +2012,10 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
 
         /* */
         es->pb_cc_present[i] = true;
+
+        /* Enable if user specified on command line */
+        if (p_sys->i_sub_last == i)
+            EsOutSelect(out, es->pp_cc_es[i], true);
     }
 
     vlc_mutex_unlock( &p_sys->lock );
@@ -2031,7 +2037,7 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
     /* We don't try to reselect */
     if( es->p_dec )
     {
-        while( vlc_object_alive(p_sys->p_input) && !p_sys->b_buffering && es->p_dec )
+        while( vlc_object_alive(p_sys->p_input) && !p_sys->b_buffering )
         {
             if( input_DecoderIsEmpty( es->p_dec ) &&
                 ( !es->p_dec_record || input_DecoderIsEmpty( es->p_dec_record ) ))
@@ -2479,7 +2485,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
     {
         const int i_id = (int)va_arg( args, int );
         es_out_id_t *p_es = EsOutGetFromID( out, i_id );
-        int i_new_query;
+        int i_new_query = 0;
 
         switch( i_query )
         {
@@ -2487,7 +2493,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
         case ES_OUT_RESTART_ES_BY_ID:     i_new_query = ES_OUT_RESTART_ES; break;
         case ES_OUT_SET_ES_DEFAULT_BY_ID: i_new_query = ES_OUT_SET_ES_DEFAULT; break;
         default:
-          assert(0);
+          vlc_assert_unreachable();
         }
         /* TODO if the lock is made non recursive it should be changed */
         int i_ret = es_out_Control( out, i_new_query, p_es );