Index: pjproject/trunk/pjmedia/include/pjmedia/master_port.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/master_port.h	(revision 497)
+++ pjproject/trunk/pjmedia/include/pjmedia/master_port.h	(revision 498)
@@ -53,5 +53,5 @@
  * @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.
  *
@@ -65,5 +65,4 @@
 
 
-
 /**
  * Start the media flow.
@@ -74,5 +73,4 @@
  */
 PJ_DECL(pj_status_t) pjmedia_master_port_start(pjmedia_master_port *m);
-
 
 
@@ -88,12 +86,63 @@
 
 /**
+ * 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);
 
 
Index: pjproject/trunk/pjmedia/src/pjmedia/clock_thread.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/clock_thread.c	(revision 497)
+++ pjproject/trunk/pjmedia/src/pjmedia/clock_thread.c	(revision 498)
@@ -20,4 +20,5 @@
 #include <pjmedia/errno.h>
 #include <pj/assert.h>
+#include <pj/lock.h>
 #include <pj/os.h>
 #include <pj/pool.h>
@@ -42,4 +43,5 @@
     pj_bool_t		     running;
     pj_bool_t		     quitting;
+    pj_lock_t		    *lock;
 };
 
@@ -83,8 +85,15 @@
     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)
-	return status;
+    if (status != PJ_SUCCESS) {
+	pj_lock_destroy(clock->lock);
+	return status;
+    }
 
 
@@ -105,10 +114,15 @@
     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;
@@ -206,4 +220,6 @@
 	    continue;
 
+	pj_lock_acquire(clock->lock);
+
 	/* Call callback, if any */
 	if (clock->cb)
@@ -216,5 +232,5 @@
 	clock->next_tick.u64 += clock->interval.u64;
 
-
+	pj_lock_release(clock->lock);
     }
 
@@ -239,9 +255,11 @@
     }
 
+    if (clock->lock) {
+	pj_lock_destroy(clock->lock);
+	clock->lock = NULL;
+    }
+
     return PJ_SUCCESS;
 }
 
 
-
-
-
Index: pjproject/trunk/pjmedia/src/pjmedia/master_port.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/master_port.c	(revision 497)
+++ pjproject/trunk/pjmedia/src/pjmedia/master_port.c	(revision 498)
@@ -21,4 +21,5 @@
 #include <pjmedia/errno.h>
 #include <pj/assert.h>
+#include <pj/lock.h>
 #include <pj/pool.h>
 #include <pj/string.h>
@@ -33,4 +34,5 @@
     unsigned	     buff_size;
     void	    *buff;
+    pj_lock_t	    *lock;
 };
 
@@ -91,11 +93,16 @@
 	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 */
@@ -116,5 +123,4 @@
     return pjmedia_clock_start(m->clock);
 }
-
 
 
@@ -139,4 +145,7 @@
     pj_status_t status;
 
+    
+    /* Lock access to ports. */
+    pj_lock_acquire(m->lock);
 
     /* Get frame from upstream port and pass it to downstream port */
@@ -163,4 +172,85 @@
 
     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;
 }
 
@@ -170,5 +260,6 @@
  * 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);
@@ -179,16 +270,21 @@
     }
 
-    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;
     }
 
-    return PJ_SUCCESS;
-}
-
-
+    if (m->lock) {
+	pj_lock_destroy(m->lock);
+	m->lock = NULL;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
