]> git.sesse.net Git - vlc/blobdiff - src/input/input.c
qt4: Missing vlc_gc_decref().
[vlc] / src / input / input.c
index a8b701c41edd9a554ffb09ed43b1be13541ad301..6f1554f29a4f2ae7b32e1b4591d34de3d907e50d 100644 (file)
 #include <vlc_sout.h>
 #include "../stream_output/stream_output.h"
 
-#include <vlc_playlist.h>
 #include <vlc_interface.h>
 #include <vlc_url.h>
-#include <vlc_demux.h>
 #include <vlc_charset.h>
+#include <vlc_playlist.h>
 
 #ifdef HAVE_SYS_STAT_H
 #   include <sys/stat.h>
@@ -53,6 +52,8 @@
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
+static void Destructor( input_thread_t * p_input );
+
 static  int Run  ( input_thread_t *p_input );
 static  int RunAndDestroy  ( input_thread_t *p_input );
 
@@ -62,7 +63,6 @@ static  int             Init    ( input_thread_t *p_input );
 static void             Error   ( input_thread_t *p_input );
 static void             End     ( input_thread_t *p_input );
 static void             MainLoop( input_thread_t *p_input );
-static void             Destroy( input_thread_t *p_input, sout_instance_t **pp_sout );
 
 static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
 static void       ControlReduce( input_thread_t * );
@@ -112,7 +112,8 @@ static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_atta
  * * Get only:
  *  - length
  *  - bookmarks
- *  - seekable (if you can seek, it doesn't say if 'bar display' has be shown or not, for that check position != 0.0)
+ *  - seekable (if you can seek, it doesn't say if 'bar display' has be shown
+ *    or not, for that check position != 0.0)
  *  - can-pause
  * * For intf callback upon changes
  *  - intf-change
@@ -121,14 +122,17 @@ static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_atta
  * TODO complete this list (?)
  *****************************************************************************/
 static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
-                               const char *psz_header, vlc_bool_t b_quick, sout_instance_t *p_sout )
+                               const char *psz_header, vlc_bool_t b_quick,
+                               sout_instance_t *p_sout )
 {
+    static const char input_name[] = "input";
     input_thread_t *p_input = NULL;                 /* thread descriptor */
     vlc_value_t val;
     int i;
 
     /* Allocate descriptor */
-    p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
+    p_input = vlc_custom_create( p_parent, sizeof( *p_input ),
+                                 VLC_OBJECT_INPUT, input_name );
     if( p_input == NULL )
     {
         msg_Err( p_parent, "out of memory" );
@@ -138,14 +142,14 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
 
     /* One "randomly" selected input thread is responsible for computing
      * the global stats. Check if there is already someone doing this */
-    if( p_input->p_libvlc->p_playlist->p_stats && !b_quick )
+    if( p_input->p_libvlc->p_stats && !b_quick )
     {
-        vlc_mutex_lock( &p_input->p_libvlc->p_playlist->p_stats->lock );
-        if( p_input->p_libvlc->p_playlist->p_stats_computer == NULL )
+        vlc_mutex_lock( &p_input->p_libvlc->p_stats->lock );
+        if( p_input->p_libvlc->p_stats_computer == NULL )
         {
-            p_input->p_libvlc->p_playlist->p_stats_computer = p_input;
+            p_input->p_libvlc->p_stats_computer = p_input;
         }
-        vlc_mutex_unlock( &p_input->p_libvlc->p_playlist->p_stats->lock );
+        vlc_mutex_unlock( &p_input->p_libvlc->p_stats->lock );
     }
 
     p_input->b_preparsing = b_quick;
@@ -167,11 +171,13 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
     TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
     p_input->p->p_es_out = NULL;
     p_input->p->p_sout  = NULL;
+    p_input->p->b_owns_its_sout = VLC_TRUE;
     p_input->p->b_sout_keep  = VLC_FALSE;
     p_input->p->b_out_pace_control = VLC_FALSE;
     p_input->i_pts_delay = 0;
 
     /* Init Input fields */
+    vlc_gc_incref( p_item ); /* Released in Destructor() */
     p_input->p->input.p_item = p_item;
     p_input->p->input.p_access = NULL;
     p_input->p->input.p_stream = NULL;
@@ -202,8 +208,10 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
 
     /* Parse input options */
     vlc_mutex_lock( &p_item->lock );
+    assert( p_item->optflagc == p_item->i_options );
     for( i = 0; i < p_item->i_options; i++ )
-        var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i] );
+        var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
+                         !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
     vlc_mutex_unlock( &p_item->lock );
 
     /* Create Object Variables for private use only */
@@ -274,32 +282,42 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
 
     /* */
     if( p_sout )
+    {
         p_input->p->p_sout = p_sout;
+        p_input->p->b_owns_its_sout = VLC_FALSE;
+    }
+
+    memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
+    vlc_mutex_init( p_input, &p_input->p->counters.counters_lock );
 
     /* Attach only once we are ready */
     vlc_object_attach( p_input, p_parent );
 
+    /* Set the destructor when we are sure we are initialized */
+    vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );
+
     return p_input;
 }
 
-static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout )
+/**
+ * Input destructor (called when the object's refcount reaches 0).
+ */
+static void Destructor( input_thread_t * p_input )
 {
-    vlc_object_detach( p_input );
     input_thread_private_t *priv = p_input->p;
 
-    if( pp_sout )
-        *pp_sout = NULL;
-    if( priv->p_sout )
+    if( priv->b_owns_its_sout && priv->p_sout )
     {
-        if( pp_sout )
-            *pp_sout = priv->p_sout;
-        else if( priv->b_sout_keep )
+        if( priv->b_sout_keep )
             SoutKeep( priv->p_sout );
         else
             sout_DeleteInstance( priv->p_sout );
     }
 
-    vlc_object_release( p_input );
+    vlc_gc_decref( p_input->p->input.p_item );
+
+    vlc_mutex_destroy( &p_input->p->counters.counters_lock );
+
     vlc_mutex_destroy( &priv->lock_control );
     free( priv );
 }
@@ -343,7 +361,8 @@ input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
     {
         input_ChangeState( p_input, ERROR_S );
         msg_Err( p_input, "cannot create input thread" );
-        Destroy( p_input, &p_sout );
+        vlc_object_detach( p_input );
+        vlc_object_release( p_input );
         return NULL;
     }
 
@@ -386,7 +405,7 @@ int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
         {
             input_ChangeState( p_input, ERROR_S );
             msg_Err( p_input, "cannot create input thread" );
-            Destroy( p_input, NULL );
+            vlc_object_release( p_input );
             return VLC_EGENERIC;
         }
     }
@@ -413,7 +432,8 @@ int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
     if( !Init( p_input ) )
         End( p_input );
 
-    Destroy( p_input, NULL );
+    vlc_object_detach( p_input );
+    vlc_object_release( p_input );
 
     return VLC_SUCCESS;
 }
@@ -462,24 +482,10 @@ void input_StopThread( input_thread_t *p_input )
     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
 }
 
-/**
- * Clean up a dead input thread
- * This function does not return until the thread is effectively cancelled.
- *
- * \param the input thread to kill
- */
-void input_DestroyThread( input_thread_t *p_input )
-{
-    input_DestroyThreadExtended( p_input, NULL );
-}
-
-void input_DestroyThreadExtended( input_thread_t *p_input, sout_instance_t **pp_sout )
+sout_instance_t * input_DetachSout( input_thread_t *p_input )
 {
-    /* Join the thread */
-    vlc_thread_join( p_input );
-
-    /* */
-    Destroy( p_input, pp_sout );
+    p_input->p->b_owns_its_sout = VLC_FALSE;
+    return p_input->p->p_sout;
 }
 
 /*****************************************************************************
@@ -496,7 +502,15 @@ static int Run( input_thread_t *p_input )
     {
         /* If we failed, wait before we are killed, and exit */
         p_input->b_error = VLC_TRUE;
-        playlist_Signal( pl_Get( p_input ) );
+
+        /* FIXME: we don't want to depend on the playlist */
+        playlist_t * p_playlist = vlc_object_find( p_input,
+            VLC_OBJECT_PLAYLIST, FIND_PARENT );
+        if( p_playlist )
+        {
+            playlist_Signal( p_playlist );
+            vlc_object_release( p_playlist );
+        }
 
         Error( p_input );
 
@@ -575,7 +589,7 @@ static int RunAndDestroy( input_thread_t *p_input )
 
 exit:
     /* Release memory */
-    Destroy( p_input, NULL );
+    vlc_object_release( p_input );
     return 0;
 }
 
@@ -745,10 +759,10 @@ static void MainLoop( input_thread_t *p_input )
         {
             stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
             /* Are we the thread responsible for computing global stats ? */
-            if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
+            if( p_input->p_libvlc->p_stats_computer == p_input )
             {
-                stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
-                                     p_input->p_libvlc->p_playlist->p_stats );
+                stats_ComputeGlobalStats( p_input->p_libvlc,
+                                     p_input->p_libvlc->p_stats );
             }
         }
     }
@@ -764,16 +778,6 @@ static int Init( input_thread_t * p_input )
     int i_es_out_mode;
     int i, i_delay;
 
-    /* Initialize optional stream output. (before access/demuxer)
-     * XXX: we add a special case if the uri starts by vlc.
-     * else 'vlc in.file --sout "" vlc:quit'  cannot work (the output will
-     * be destroyed in case of a file).
-     * (this will break playing of file starting by 'vlc:' but I don't
-     * want to add more logic, just force file by file:// or code it ;)
-     */
-    memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
-    vlc_mutex_init( p_input, &p_input->p->counters.counters_lock );
-
     for( i = 0; i < p_input->p->input.p_item->i_options; i++ )
     {
         if( !strncmp( p_input->p->input.p_item->ppsz_options[i], "meta-file", 9 ) )
@@ -1053,8 +1057,8 @@ static int Init( input_thread_t * p_input )
                 }
                 free( subs[i] );
             }
-            if( subs ) free( subs );
-            if( psz_autopath ) free( psz_autopath );
+            free( subs );
+            free( psz_autopath );
         }
         free( psz_subtitle );
 
@@ -1292,7 +1296,7 @@ static void End( input_thread_t * p_input )
         InputSourceClean( p_input->p->slave[i] );
         free( p_input->p->slave[i] );
     }
-    if( p_input->p->slave ) free( p_input->p->slave );
+    free( p_input->p->slave );
 
     /* Unload all modules */
     if( p_input->p->p_es_out )
@@ -1305,11 +1309,11 @@ static void End( input_thread_t * p_input )
         {
             /* make sure we are up to date */
             stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
-            if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
+            if( p_input->p_libvlc->p_stats_computer == p_input )
             {
-                stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
-                                          p_input->p_libvlc->p_playlist->p_stats );
-                p_input->p_libvlc->p_playlist->p_stats_computer = NULL;
+                stats_ComputeGlobalStats( p_input->p_libvlc,
+                                          p_input->p_libvlc->p_stats );
+                p_input->p_libvlc->p_stats_computer = NULL;
             }
             CL_CO( read_bytes );
             CL_CO( read_packets );
@@ -1344,8 +1348,6 @@ static void End( input_thread_t * p_input )
         TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment );
     }
 
-    vlc_mutex_destroy( &p_input->p->counters.counters_lock );
-
     /* Tell we're dead */
     p_input->b_dead = VLC_TRUE;
 }
@@ -1379,27 +1381,32 @@ static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item,
     if( b_keep_sout )
     {
         /* Remove the sout from the playlist garbage collector */
-        playlist_t *p_playlist = pl_Yield( p_parent );
-
-        vlc_mutex_lock( &p_playlist->gc_lock );
-        p_sout = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD );
-        if( p_sout )
+        /* FIXME: we don't want to depend on the playlist, sout
+         * should be attached to libvlc */
+        playlist_t * p_playlist = vlc_object_find( p_parent,
+            VLC_OBJECT_PLAYLIST, FIND_PARENT );
+        if( p_playlist )
         {
-            if( p_sout->p_parent != VLC_OBJECT(p_playlist) )
-            {
-                vlc_object_release( p_sout );
-                p_sout = NULL;
-            }
-            else
+            vlc_mutex_lock( &p_playlist->gc_lock );
+            p_sout = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD );
+            if( p_sout )
             {
-                vlc_object_detach( p_sout );    /* Remove it from the GC */
+                if( p_sout->p_parent != VLC_OBJECT(p_playlist) )
+                {
+                    vlc_object_release( p_sout );
+                    p_sout = NULL;
+                }
+                else
+                {
+                    vlc_object_detach( p_sout );    /* Remove it from the GC */
 
-                vlc_object_release( p_sout );
+                    vlc_object_release( p_sout );
+                }
             }
-        }
-        vlc_mutex_unlock( &p_playlist->gc_lock );
+            vlc_mutex_unlock( &p_playlist->gc_lock );
 
-        pl_Release( p_parent );
+            vlc_object_release( p_playlist );
+        }
     }
 
     if( pb_sout_keep )
@@ -1407,10 +1414,14 @@ static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item,
 
     return p_sout;
 }
+
 static void SoutKeep( sout_instance_t *p_sout )
 {
-    /* attach sout to the playlist */
-    playlist_t  *p_playlist = pl_Yield( p_sout );
+    /* FIXME: we don't want to depend on the playlist, sout
+     * should be attached to libvlc */
+    playlist_t * p_playlist = vlc_object_find( p_sout, VLC_OBJECT_PLAYLIST,
+                                               FIND_PARENT );
+    if( !p_playlist ) return;
 
     msg_Dbg( p_sout, "sout has been kept" );
     vlc_object_attach( p_sout, p_playlist );
@@ -2201,7 +2212,7 @@ static int InputSourceInit( input_thread_t *p_input,
         {
             psz_demux = psz_forced_demux;
         }
-        else if( !psz_demux || *psz_demux == '\0' )
+        else if( *psz_demux == '\0' )
         {
             /* special hack for forcing a demuxer with --demux=module
              * (and do nothing with a list) */
@@ -2227,9 +2238,9 @@ static int InputSourceInit( input_thread_t *p_input,
     else
     {
         /* Preparsing is only for file:// */
-        if( psz_demux && *psz_demux )
+        if( *psz_demux )
             goto error;
-        if( !psz_access || !*psz_access ) /* path without scheme:// */
+        if( !*psz_access ) /* path without scheme:// */
             psz_access = "file";
         if( strcmp( psz_access, "file" ) )
             goto error;
@@ -2289,8 +2300,7 @@ static int InputSourceInit( input_thread_t *p_input,
         input_ChangeState( p_input, OPENING_S );
 
         /* Now try a real access */
-        in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path,
-                                    p_input->b_preparsing );
+        in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
 
         /* Access failed, URL encoded ? */
         if( in->p_access == NULL && strchr( psz_path, '%' ) )
@@ -2301,8 +2311,7 @@ static int InputSourceInit( input_thread_t *p_input,
                      psz_access, psz_demux, psz_path );
 
             in->p_access = access2_New( p_input,
-                                        psz_access, psz_demux, psz_path,
-                                        p_input->b_preparsing );
+                                        psz_access, psz_demux, psz_path );
         }
         if( in->p_access == NULL )
         {
@@ -2700,8 +2709,7 @@ static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_atta
                           sizeof(input_attachment_t**) * ( i_attachment + i_new ) );
     for( i = 0; i < i_new; i++ )
         attachment[i_attachment++] = pp_new[i];
-    if( pp_new )
-        free( pp_new );
+    free( pp_new );
 
     /* */
     *pi_attachment = i_attachment;