]> git.sesse.net Git - vlc/blobdiff - src/input/input.c
Fixed ES_OUT_SET_DEFAULT name (added ES_).
[vlc] / src / input / input.c
index 5c631479b2b3022eda7efebf839530b887f69b9c..a8729a4172c60ab0dcfaa00639c56380ac5fa0d5 100644 (file)
 #include <assert.h>
 
 #include "input_internal.h"
+#include "es_out.h"
+#include "access.h"
+#include "demux.h"
+#include "stream.h"
 
 #include <vlc_sout.h>
 #include "../stream_output/stream_output.h"
@@ -123,6 +127,7 @@ static void SubtitleAdd( input_thread_t *p_input, char *psz_subtitle, bool b_for
  *  - intf-change
  *  - intf-change-vout for when a vout is created or destroyed
  *  - rate-change for when playback rate changes
+ *  - stats-change for when statistics are updated
  * TODO explain when Callback is called
  * TODO complete this list (?)
  *****************************************************************************/
@@ -156,8 +161,9 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
     stats_TimerStart( p_input, psz_timer_name,
         STATS_TIMER_INPUT_LAUNCHING );
 
-    MALLOC_NULL( p_input->p, input_thread_private_t );
-    memset( p_input->p, 0, sizeof( input_thread_private_t ) );
+    p_input->p = calloc( 1, sizeof( input_thread_private_t ) );
+    if( !p_input->p )
+        return NULL;
 
     /* One "randomly" selected input thread is responsible for computing
      * the global stats. Check if there is already someone doing this */
@@ -257,7 +263,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
             psz_parser = val.psz_string;
             while( (psz_start = strchr( psz_parser, '{' ) ) )
             {
-                 seekpoint_t *p_seekpoint = vlc_seekpoint_New();
+                 seekpoint_t *p_seekpoint;
                  char backup;
                  psz_start++;
                  psz_end = strchr( psz_start, '}' );
@@ -266,6 +272,8 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
                  backup = *psz_parser;
                  *psz_parser = 0;
                  *psz_end = ',';
+
+                 p_seekpoint = vlc_seekpoint_New();
                  while( (psz_end = strchr( psz_start, ',' ) ) )
                  {
                      *psz_end = 0;
@@ -482,6 +490,7 @@ void input_StopThread( input_thread_t *p_input )
 
 sout_instance_t * input_DetachSout( input_thread_t *p_input )
 {
+    assert( p_input->b_dead );
     sout_instance_t *p_sout = p_input->p->p_sout;
     vlc_object_detach( p_sout );
     p_input->p->p_sout = NULL;
@@ -704,6 +713,7 @@ static void MainLoopStatistic( input_thread_t *p_input )
         stats_ComputeGlobalStats( p_input->p_libvlc,
                                   p_input->p_libvlc->p_stats );
     }
+    var_SetBool( p_input, "stats-change", true );
 }
 
 /**
@@ -727,20 +737,30 @@ static void MainLoop( input_thread_t *p_input )
         mtime_t i_current;
         mtime_t i_deadline;
         mtime_t i_wakeup;
+        bool b_paused;
 
         /* Demux data */
         b_force_update = false;
         i_wakeup = 0;
-        if( p_input->i_state != PAUSE_S )
+        /* FIXME if p_input->i_state == PAUSE_S the access/access_demux
+         * is paused -> this may cause problem with some of them
+         * The same problem can be seen when seeking while paused */
+        input_EsOutLock( p_input->p->p_es_out );
+        b_paused = p_input->i_state == PAUSE_S &&
+                   !input_EsOutIsBuffering( p_input->p->p_es_out );
+        input_EsOutUnlock( p_input->p->p_es_out );
+
+        if( !b_paused )
         {
             MainLoopDemux( p_input, &b_force_update, &i_start_mdate );
-            i_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out );
+
+            i_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
         }
 
         /* */
         do {
             i_deadline = i_wakeup;
-            if( p_input->i_state == PAUSE_S )
+            if( b_paused )
                 i_deadline = __MIN( i_intf_update, i_statistic_update );
 
             /* Handle control */
@@ -749,6 +769,7 @@ static void MainLoop( input_thread_t *p_input )
             while( !ControlPopNoLock( p_input, &i_type, &val, i_deadline ) )
             {
                 msg_Dbg( p_input, "control type=%d", i_type );
+
                 if( Control( p_input, i_type, val ) )
                     b_force_update = true;
             }
@@ -771,7 +792,7 @@ static void MainLoop( input_thread_t *p_input )
             /* Check if i_wakeup is still valid */
             if( i_wakeup != 0 )
             {
-                mtime_t i_new_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out );
+                mtime_t i_new_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
                 if( !i_new_wakeup )
                     i_wakeup = 0;
             }
@@ -783,7 +804,11 @@ static void MainLoop( input_thread_t *p_input )
         /* We have finish to demux data but not to play them */
         while( vlc_object_alive( p_input ) )
         {
-            if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
+            input_EsOutLock( p_input->p->p_es_out );
+            bool b_empty = input_EsOutDecodersIsEmpty( p_input->p->p_es_out );
+            input_EsOutUnlock( p_input->p->p_es_out );
+
+            if( b_empty )
                 break;
 
             msg_Dbg( p_input, "waiting decoder fifos to empty" );
@@ -1246,7 +1271,7 @@ error:
     input_ChangeState( p_input, ERROR_S );
 
     if( p_input->p->p_es_out )
-        input_EsOutDelete( p_input->p->p_es_out );
+        es_out_Delete( p_input->p->p_es_out );
 #ifdef ENABLE_SOUT
     if( p_input->p->p_sout )
     {
@@ -1334,7 +1359,7 @@ static void End( input_thread_t * p_input )
 
     /* Unload all modules */
     if( p_input->p->p_es_out )
-        input_EsOutDelete( p_input->p->p_es_out );
+        es_out_Delete( p_input->p->p_es_out );
 
     if( !p_input->b_preparsing )
     {
@@ -1470,6 +1495,58 @@ static void ControlReduce( input_thread_t *p_input )
         }
     }
 }
+/* Pause input */
+static void ControlPause( input_thread_t *p_input, mtime_t i_control_date )
+{
+    int i_ret;
+    int i_state;
+    if( p_input->p->input.p_access )
+        i_ret = access_Control( p_input->p->input.p_access,
+                                 ACCESS_SET_PAUSE_STATE, true );
+    else
+        i_ret = demux_Control( p_input->p->input.p_demux,
+                                DEMUX_SET_PAUSE_STATE, true );
+
+    i_state = PAUSE_S;
+    if( i_ret )
+    {
+        msg_Warn( p_input, "cannot set pause state" );
+        i_state = p_input->i_state;
+    }
+
+    /* Switch to new state */
+    input_ChangeStateWithVarCallback( p_input, i_state, false );
+
+    /* */
+    if( !i_ret )
+        input_EsOutChangePause( p_input->p->p_es_out, true, i_control_date );
+}
+static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
+{
+    int i_ret;
+    if( p_input->p->input.p_access )
+        i_ret = access_Control( p_input->p->input.p_access,
+                                 ACCESS_SET_PAUSE_STATE, false );
+    else
+        i_ret = demux_Control( p_input->p->input.p_demux,
+                                DEMUX_SET_PAUSE_STATE, false );
+
+    if( i_ret )
+    {
+        /* FIXME What to do ? */
+        msg_Warn( p_input, "cannot unset pause -> EOF" );
+        vlc_mutex_unlock( &p_input->p->lock_control );
+        input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
+        vlc_mutex_lock( &p_input->p->lock_control );
+    }
+
+    /* Switch to play */
+    input_ChangeStateWithVarCallback( p_input, PLAYING_S, false );
+
+    /* */
+    if( !i_ret )
+        input_EsOutChangePause( p_input->p->p_es_out, false, i_control_date );
+}
 
 static bool Control( input_thread_t *p_input, int i_type,
                            vlc_value_t val )
@@ -1480,6 +1557,8 @@ static bool Control( input_thread_t *p_input, int i_type,
     if( !p_input )
         return b_force_update;
 
+    input_EsOutLock( p_input->p->p_es_out );
+
     switch( i_type )
     {
         case INPUT_CONTROL_SET_DIE:
@@ -1593,61 +1672,16 @@ static bool Control( input_thread_t *p_input, int i_type,
             if( ( val.i_int == PLAYING_S && p_input->i_state == PAUSE_S ) ||
                 ( val.i_int == PAUSE_S && p_input->i_state == PAUSE_S ) )
             {
-                int i_ret;
-                if( p_input->p->input.p_access )
-                    i_ret = access_Control( p_input->p->input.p_access,
-                                             ACCESS_SET_PAUSE_STATE, false );
-                else
-                    i_ret = demux_Control( p_input->p->input.p_demux,
-                                            DEMUX_SET_PAUSE_STATE, false );
-
-                if( i_ret )
-                {
-                    /* FIXME What to do ? */
-                    msg_Warn( p_input, "cannot unset pause -> EOF" );
-                    vlc_mutex_unlock( &p_input->p->lock_control );
-                    input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
-                    vlc_mutex_lock( &p_input->p->lock_control );
-                }
+                ControlUnpause( p_input, i_control_date );
 
                 b_force_update = true;
-
-                /* Switch to play */
-                input_ChangeStateWithVarCallback( p_input, PLAYING_S, false );
-
-                /* */
-                if( !i_ret )
-                    input_EsOutChangePause( p_input->p->p_es_out, false, i_control_date );
             }
             else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
                      p_input->p->b_can_pause )
             {
-                int i_ret, state;
-                if( p_input->p->input.p_access )
-                    i_ret = access_Control( p_input->p->input.p_access,
-                                             ACCESS_SET_PAUSE_STATE, true );
-                else
-                    i_ret = demux_Control( p_input->p->input.p_demux,
-                                            DEMUX_SET_PAUSE_STATE, true );
+                ControlPause( p_input, i_control_date );
 
                 b_force_update = true;
-
-                if( i_ret )
-                {
-                    msg_Warn( p_input, "cannot set pause state" );
-                    state = p_input->i_state;
-                }
-                else
-                {
-                    state = PAUSE_S;
-                }
-
-                /* Switch to new state */
-                input_ChangeStateWithVarCallback( p_input, state, false );
-
-                /* */
-                if( !i_ret )
-                    input_EsOutChangePause( p_input->p->p_es_out, true, i_control_date );
             }
             else if( val.i_int == PAUSE_S && !p_input->p->b_can_pause )
             {
@@ -2016,12 +2050,33 @@ static bool Control( input_thread_t *p_input, int i_type,
             }
             break;
 
+        case INPUT_CONTROL_SET_FRAME_NEXT:
+            if( !p_input->p->b_can_pause )
+                break;
+
+            if( p_input->i_state == PAUSE_S )
+            {
+                input_EsOutFrameNext( p_input->p->p_es_out );
+            }
+            else if( p_input->i_state == PLAYING_S )
+            {
+                ControlPause( p_input, i_control_date );
+            }
+            else
+            {
+                msg_Err( p_input, "invalid state for frame next" );
+            }
+            b_force_update = true;
+            break;
+
         case INPUT_CONTROL_SET_BOOKMARK:
         default:
             msg_Err( p_input, "not yet implemented" );
             break;
     }
 
+    input_EsOutUnlock( p_input->p->p_es_out );
+
     return b_force_update;
 }
 
@@ -3053,10 +3108,13 @@ static void SubtitleAdd( input_thread_t *p_input, char *psz_subtitle, bool b_for
         if( count.i_int < list.p_list->i_count )
         {
             int i_id = list.p_list->p_values[count.i_int].i_int;
+
+            input_EsOutLock( p_input->p->p_es_out );
             es_out_id_t *p_es = input_EsOutGetFromID( p_input->p->p_es_out, i_id );
 
-            es_out_Control( p_input->p->p_es_out, ES_OUT_SET_DEFAULT, p_es );
+            es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES_DEFAULT, p_es );
             es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES, p_es );
+            input_EsOutUnlock( p_input->p->p_es_out );
         }
         var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
     }