[vlc-devel] [PATCH 2/2] Allow multiple avio URL streams using TLS for URL callback function

keary.griffin at unwiredappeal.com keary.griffin at unwiredappeal.com
Mon Oct 3 20:36:48 CEST 2011


From: Keary Griffin <kearygriffin at gmail.com>

---
 modules/access/avio.c |   75 ++++++++++++++++++++++++++++++-------------------
 1 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/modules/access/avio.c b/modules/access/avio.c
index 8707fc3..d45fe12 100644
--- a/modules/access/avio.c
+++ b/modules/access/avio.c
@@ -53,7 +53,9 @@ static ssize_t Write( sout_access_out_t *, block_t * );
 static int     OutControl(sout_access_out_t *, int, va_list);
 static int     OutSeek ( sout_access_out_t *, off_t  );
 
-static int     SetupAvio(vlc_object_t *);
+static void    SetupAvioCallback(void);
+static void    ReleaseAvioCallback(void);
+static void    PrepareAvioCall( vlc_object_t * );
 
 struct access_sys_t {
     URLContext *context;
@@ -75,12 +77,7 @@ int OpenAvio(vlc_object_t *object)
     if (!sys)
         return VLC_ENOMEM;
 
-    /* We can either accept only one user (actually) or multiple ones
-     * with an exclusive lock */
-    if (SetupAvio(VLC_OBJECT(access))) {
-        msg_Err(access, "Module aready in use");
-        return VLC_EGENERIC;
-    }
+    SetupAvioCallback();
 
     /* */
     vlc_avcodec_lock();
@@ -102,6 +99,7 @@ int OpenAvio(vlc_object_t *object)
         goto error;
 
     msg_Dbg(access, "Opening '%s'", url);
+    PrepareAvioCall( VLC_OBJECT(access) );
     if (url_open(&sys->context, url, URL_RDONLY) < 0 )
         sys->context = NULL;
     free(url);
@@ -110,6 +108,7 @@ int OpenAvio(vlc_object_t *object)
         msg_Err(access, "Failed to open url using libavformat");
         goto error;
     }
+    /* Don't need PrepareAvio, already called above */
     const int64_t size = url_filesize(sys->context);
     msg_Dbg(access, "is_streamed=%d size=%"PRIi64, sys->context->is_streamed, size);
 
@@ -126,7 +125,7 @@ int OpenAvio(vlc_object_t *object)
     return VLC_SUCCESS;
 
 error:
-    SetupAvio(NULL);
+    ReleaseAvioCallback();
     free(sys);
     return VLC_EGENERIC;
 }
@@ -142,12 +141,7 @@ int OutOpenAvio(vlc_object_t *object)
     if (!sys)
         return VLC_ENOMEM;
 
-    /* We can either accept only one user (actually) or multiple ones
-     * with an exclusive lock */
-    if (SetupAvio((vlc_object_t*)access)) {
-        msg_Err(access, "Module aready in use");
-        return VLC_EGENERIC;
-    }
+    SetupAvioCallback();
 
     /* */
     vlc_avcodec_lock();
@@ -162,6 +156,7 @@ int OutOpenAvio(vlc_object_t *object)
         goto error;
 
     msg_Dbg(access, "avio_output Opening '%s'", url);
+    PrepareAvioCall( VLC_OBJECT(access) );
     if (url_open(&sys->context, url, URL_WRONLY) < 0 )
         sys->context = NULL;
     free(url);
@@ -179,7 +174,7 @@ int OutOpenAvio(vlc_object_t *object)
     return VLC_SUCCESS;
 
 error:
-    SetupAvio(NULL);
+    ReleaseAvioCallback();
     free(sys);
     return VLC_EGENERIC;
 }
@@ -192,9 +187,10 @@ void CloseAvio(vlc_object_t *object)
     access_t *access = (access_t*)object;
     access_sys_t *sys = access->p_sys;
 
+    PrepareAvioCall( VLC_OBJECT(access) );
     url_close(sys->context);
 
-    SetupAvio(NULL);
+    ReleaseAvioCallback();
 
     free(sys);
 }
@@ -204,9 +200,10 @@ void OutCloseAvio(vlc_object_t *object)
     sout_access_out_t *access = (sout_access_out_t*)object;
     sout_access_out_sys_t *sys = access->p_sys;
 
+    PrepareAvioCall( VLC_OBJECT(access) );
     url_close(sys->context);
 
-    SetupAvio(NULL);
+    ReleaseAvioCallback();
 
     free(sys);
 }
@@ -217,6 +214,7 @@ static ssize_t Read(access_t *access, uint8_t *data, size_t size)
     /* FIXME I am unsure of the meaning of the return value in case
      * of error.
      */
+    PrepareAvioCall( VLC_OBJECT(access) );
     int r = url_read(access->p_sys->context, data, size);
     access->info.b_eof = r <= 0;
     if (r < 0)
@@ -233,6 +231,7 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
     access_sys_t *p_sys = (access_sys_t*)p_access->p_sys;
     size_t i_write = 0;
 
+    PrepareAvioCall( VLC_OBJECT(p_access) );
     while( p_buffer != NULL )
     {
         block_t *p_next = p_buffer->p_next;;
@@ -252,6 +251,7 @@ static int Seek(access_t *access, uint64_t position)
 {
     access_sys_t *sys = access->p_sys;
 
+    PrepareAvioCall( VLC_OBJECT(access) );
     if (position > INT64_MAX ||
         url_seek(sys->context, position, SEEK_SET) < 0) {
         msg_Err(access, "Seek to %"PRIu64" failed\n", position);
@@ -267,6 +267,7 @@ static int OutSeek( sout_access_out_t *p_access, off_t i_pos )
 {
     sout_access_out_sys_t *sys = p_access->p_sys;
 
+    PrepareAvioCall( VLC_OBJECT(p_access) );
     if (url_seek(sys->context, i_pos, SEEK_SET) < 0)
         return VLC_EGENERIC;
     return VLC_SUCCESS;
@@ -322,6 +323,7 @@ static int Control(access_t *access, int query, va_list args)
     }
     case ACCESS_SET_PAUSE_STATE: {
         bool is_paused = va_arg(args, int);
+        PrepareAvioCall( VLC_OBJECT(access) );
         if (av_url_read_pause(sys->context, is_paused)< 0)
             return VLC_EGENERIC;
         return VLC_SUCCESS;
@@ -342,28 +344,43 @@ static int Control(access_t *access, int query, va_list args)
 
 /* */
 static vlc_mutex_t avio_lock = VLC_STATIC_MUTEX;
-static vlc_object_t *current_access = NULL;
-
+static vlc_threadvar_t current_access_tls;
+static int threadLocalCount = 0;
 
+/* All calls to avio functions must be preceeded by calling PrepareAvioCall */
+/* so this callback knows what vlc_object it should be checking */
 static int UrlInterruptCallback(void)
 {
+    vlc_object_t *current_access = vlc_threadvar_get(current_access_tls);
     assert(current_access);
     return !vlc_object_alive(current_access);
 }
 
-
-static int SetupAvio(vlc_object_t *access)
+static void SetupAvioCallback()
 {
     vlc_mutex_lock(&avio_lock);
-    assert(!access != !current_access);
-    if (access && current_access) {
-        vlc_mutex_unlock(&avio_lock);
-        return VLC_EGENERIC;
-    }
-    url_set_interrupt_cb(access ? UrlInterruptCallback : NULL);
-    current_access = access;
+    if (!threadLocalCount)
+    {
+        vlc_threadvar_create(&current_access_tls, NULL);
+        url_set_interrupt_cb(UrlInterruptCallback);
+    } 
+    threadLocalCount++;
     vlc_mutex_unlock(&avio_lock);
+}
 
-    return VLC_SUCCESS;
+static void ReleaseAvioCallback()
+{
+    vlc_mutex_lock(&avio_lock);
+    threadLocalCount--;
+    if (!threadLocalCount)
+    {
+        url_set_interrupt_cb(NULL);
+        vlc_threadvar_delete(&current_access_tls);
+    } 
+    vlc_mutex_unlock(&avio_lock);
 }
 
+static void PrepareAvioCall( vlc_object_t * vlc_obj )
+{
+    vlc_threadvar_set(current_access_tls, vlc_obj );
+}
-- 
1.7.1




More information about the vlc-devel mailing list