summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-06-12 10:13:31 +0000
committerBenny Prijono <bennylp@teluu.com>2006-06-12 10:13:31 +0000
commit070c6a1f21fb75982716948e1390dd449088ef60 (patch)
tree55933c79b70f2bf56d7f547cb9facb7d66f0033d /pjmedia
parent66f91465de3c70018b6c31f14da273cdce518eb8 (diff)
Added mutex protection and option not to delete upstream/downstream port in master_port.c
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@498 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia/master_port.h57
-rw-r--r--pjmedia/src/pjmedia/clock_thread.c28
-rw-r--r--pjmedia/src/pjmedia/master_port.c108
3 files changed, 178 insertions, 15 deletions
diff --git a/pjmedia/include/pjmedia/master_port.h b/pjmedia/include/pjmedia/master_port.h
index 44b7db78..06af20b3 100644
--- a/pjmedia/include/pjmedia/master_port.h
+++ b/pjmedia/include/pjmedia/master_port.h
@@ -52,7 +52,7 @@ typedef struct pjmedia_master_port pjmedia_master_port;
* @param pool Pool to allocate master port from.
* @param u_port Upstream port.
* @param d_port Downstream port.
- * @param options Options flags.
+ * @param options Options flags, bitmask from #pjmedia_master_port_flag.
* @param p_m Pointer to receive the master port instance.
*
* @return PJ_SUCCESS on success.
@@ -64,7 +64,6 @@ PJ_DECL(pj_status_t) pjmedia_master_port_create(pj_pool_t *pool,
pjmedia_master_port **p_m);
-
/**
* Start the media flow.
*
@@ -75,7 +74,6 @@ PJ_DECL(pj_status_t) pjmedia_master_port_create(pj_pool_t *pool,
PJ_DECL(pj_status_t) pjmedia_master_port_start(pjmedia_master_port *m);
-
/**
* Stop the media flow.
*
@@ -87,14 +85,65 @@ PJ_DECL(pj_status_t) pjmedia_master_port_stop(pjmedia_master_port *m);
/**
+ * Change the upstream port. Note that application is responsible to destroy
+ * current upstream port (the one that is going to be replaced with the
+ * new port).
+ *
+ * @param m The master port.
+ * @param port Port to be used for upstream port.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_master_port_set_uport(pjmedia_master_port *m,
+ pjmedia_port *port);
+
+
+/**
+ * Get the upstream port.
+ *
+ * @param m The master port.
+ *
+ * @return The upstream port.
+ */
+PJ_DECL(pjmedia_port*) pjmedia_master_port_get_uport(pjmedia_master_port*m);
+
+
+/**
+ * Change the downstream port. Note that application is responsible to destroy
+ * current downstream port (the one that is going to be replaced with the
+ * new port).
+ *
+ * @param m The master port.
+ * @param port Port to be used for downstream port.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_master_port_set_dport(pjmedia_master_port *m,
+ pjmedia_port *port);
+
+
+/**
+ * Get the downstream port.
+ *
+ * @param m The master port.
+ *
+ * @return The downstream port.
+ */
+PJ_DECL(pjmedia_port*) pjmedia_master_port_get_dport(pjmedia_master_port*m);
+
+
+/**
* Destroy the master port, and optionally destroy the upstream and
* downstream ports.
*
* @param m The master port.
+ * @param destroy_ports If non-zero, the function will destroy both
+ * upstream and downstream ports too.
*
* @return PJ_SUCCESS on success.
*/
-PJ_DECL(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m);
+PJ_DECL(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m,
+ pj_bool_t destroy_ports);
diff --git a/pjmedia/src/pjmedia/clock_thread.c b/pjmedia/src/pjmedia/clock_thread.c
index dad7447a..391f7d1f 100644
--- a/pjmedia/src/pjmedia/clock_thread.c
+++ b/pjmedia/src/pjmedia/clock_thread.c
@@ -19,6 +19,7 @@
#include <pjmedia/clock.h>
#include <pjmedia/errno.h>
#include <pj/assert.h>
+#include <pj/lock.h>
#include <pj/os.h>
#include <pj/pool.h>
@@ -41,6 +42,7 @@ struct pjmedia_clock
pj_thread_t *thread;
pj_bool_t running;
pj_bool_t quitting;
+ pj_lock_t *lock;
};
@@ -82,10 +84,17 @@ PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool,
clock->running = PJ_FALSE;
clock->quitting = PJ_FALSE;
+ /* I don't think we need a mutex, so we'll use null. */
+ status = pj_lock_create_null_mutex(pool, "clock", &clock->lock);
+ if (status != PJ_SUCCESS)
+ return status;
+
status = pj_thread_create(pool, "clock", &clock_thread, clock,
0, 0, &clock->thread);
- if (status != PJ_SUCCESS)
+ if (status != PJ_SUCCESS) {
+ pj_lock_destroy(clock->lock);
return status;
+ }
*p_clock = clock;
@@ -104,12 +113,17 @@ PJ_DEF(pj_status_t) pjmedia_clock_start(pjmedia_clock *clock)
PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL);
+ if (clock->running)
+ return PJ_SUCCESS;
+
status = pj_get_timestamp(&now);
if (status != PJ_SUCCESS)
return status;
+ pj_lock_acquire(clock->lock);
clock->next_tick.u64 = now.u64 + clock->interval.u64;
clock->running = PJ_TRUE;
+ pj_lock_release(clock->lock);
return status;
}
@@ -205,6 +219,8 @@ static int clock_thread(void *arg)
if (!clock->running)
continue;
+ pj_lock_acquire(clock->lock);
+
/* Call callback, if any */
if (clock->cb)
(*clock->cb)(&clock->timestamp, clock->user_data);
@@ -215,7 +231,7 @@ static int clock_thread(void *arg)
/* Calculate next tick */
clock->next_tick.u64 += clock->interval.u64;
-
+ pj_lock_release(clock->lock);
}
return 0;
@@ -238,10 +254,12 @@ PJ_DEF(pj_status_t) pjmedia_clock_destroy(pjmedia_clock *clock)
clock->thread = NULL;
}
+ if (clock->lock) {
+ pj_lock_destroy(clock->lock);
+ clock->lock = NULL;
+ }
+
return PJ_SUCCESS;
}
-
-
-
diff --git a/pjmedia/src/pjmedia/master_port.c b/pjmedia/src/pjmedia/master_port.c
index 42edd96e..ce45038a 100644
--- a/pjmedia/src/pjmedia/master_port.c
+++ b/pjmedia/src/pjmedia/master_port.c
@@ -20,6 +20,7 @@
#include <pjmedia/clock.h>
#include <pjmedia/errno.h>
#include <pj/assert.h>
+#include <pj/lock.h>
#include <pj/pool.h>
#include <pj/string.h>
@@ -32,6 +33,7 @@ struct pjmedia_master_port
pjmedia_port *d_port;
unsigned buff_size;
void *buff;
+ pj_lock_t *lock;
};
@@ -90,13 +92,18 @@ PJ_DEF(pj_status_t) pjmedia_master_port_create( pj_pool_t *pool,
if (!m->buff)
return PJ_ENOMEM;
+ /* Create lock object */
+ status = pj_lock_create_simple_mutex(pool, "mport", &m->lock);
+ if (status != PJ_SUCCESS)
+ return status;
/* Create media clock */
status = pjmedia_clock_create(pool, clock_rate, samples_per_frame, 0,
&clock_callback, m, &m->clock);
- if (status != PJ_SUCCESS)
+ if (status != PJ_SUCCESS) {
+ pj_lock_destroy(m->lock);
return status;
-
+ }
/* Done */
*p_m = m;
@@ -117,7 +124,6 @@ PJ_DEF(pj_status_t) pjmedia_master_port_start(pjmedia_master_port *m)
}
-
/*
* Stop the media flow.
*/
@@ -138,6 +144,9 @@ static void clock_callback(const pj_timestamp *ts, void *user_data)
pjmedia_frame frame;
pj_status_t status;
+
+ /* Lock access to ports. */
+ pj_lock_acquire(m->lock);
/* Get frame from upstream port and pass it to downstream port */
pj_memset(&frame, 0, sizeof(frame));
@@ -162,6 +171,87 @@ static void clock_callback(const pj_timestamp *ts, void *user_data)
frame.type = PJMEDIA_FRAME_TYPE_NONE;
status = pjmedia_port_put_frame(m->u_port, &frame);
+
+ /* Release lock */
+ pj_lock_release(m->lock);
+}
+
+
+/*
+ * Change the upstream port.
+ */
+PJ_DEF(pj_status_t) pjmedia_master_port_set_uport(pjmedia_master_port *m,
+ pjmedia_port *port)
+{
+ PJ_ASSERT_RETURN(m && port, PJ_EINVAL);
+
+ /* If we have downstream port, make sure they have matching samples per
+ * frame.
+ */
+ if (m->d_port) {
+ PJ_ASSERT_RETURN(
+ port->info.clock_rate/port->info.samples_per_frame==
+ m->d_port->info.clock_rate/m->d_port->info.samples_per_frame,
+ PJMEDIA_ENCSAMPLESPFRAME
+ );
+ }
+
+ pj_lock_acquire(m->lock);
+
+ m->u_port = port;
+
+ pj_lock_release(m->lock);
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Get the upstream port.
+ */
+PJ_DEF(pjmedia_port*) pjmedia_master_port_get_uport(pjmedia_master_port*m)
+{
+ PJ_ASSERT_RETURN(m, NULL);
+ return m->u_port;
+}
+
+
+/*
+ * Change the downstream port.
+ */
+PJ_DEF(pj_status_t) pjmedia_master_port_set_dport(pjmedia_master_port *m,
+ pjmedia_port *port)
+{
+ PJ_ASSERT_RETURN(m && port, PJ_EINVAL);
+
+ /* If we have upstream port, make sure they have matching samples per
+ * frame.
+ */
+ if (m->u_port) {
+ PJ_ASSERT_RETURN(
+ port->info.clock_rate/port->info.samples_per_frame==
+ m->u_port->info.clock_rate/m->u_port->info.samples_per_frame,
+ PJMEDIA_ENCSAMPLESPFRAME
+ );
+ }
+
+ pj_lock_acquire(m->lock);
+
+ m->d_port = port;
+
+ pj_lock_release(m->lock);
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * Get the downstream port.
+ */
+PJ_DEF(pjmedia_port*) pjmedia_master_port_get_dport(pjmedia_master_port*m)
+{
+ PJ_ASSERT_RETURN(m, NULL);
+ return m->d_port;
}
@@ -169,7 +259,8 @@ static void clock_callback(const pj_timestamp *ts, void *user_data)
* Destroy the master port, and optionally destroy the u_port and
* d_port ports.
*/
-PJ_DEF(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m)
+PJ_DEF(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m,
+ pj_bool_t destroy_ports)
{
PJ_ASSERT_RETURN(m, PJ_EINVAL);
@@ -178,16 +269,21 @@ PJ_DEF(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m)
m->clock = NULL;
}
- if (m->u_port) {
+ if (m->u_port && destroy_ports) {
pjmedia_port_destroy(m->u_port);
m->u_port = NULL;
}
- if (m->d_port) {
+ if (m->d_port && destroy_ports) {
pjmedia_port_destroy(m->d_port);
m->d_port = NULL;
}
+ if (m->lock) {
+ pj_lock_destroy(m->lock);
+ m->lock = NULL;
+ }
+
return PJ_SUCCESS;
}