[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(¤t_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(¤t_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