summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h16
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h11
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c65
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c26
4 files changed, 108 insertions, 10 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index c9f4eb6d..698dde3d 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -1996,7 +1996,7 @@ PJ_DECL(pj_status_t) pjsua_verify_url(const char *url);
* not.
*
* @param entry Timer heap entry.
- * @param delay The interval to expire.
+ * @param delay The interval to expire.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*
@@ -2005,6 +2005,20 @@ PJ_DECL(pj_status_t) pjsua_verify_url(const char *url);
PJ_DECL(pj_status_t) pjsua_schedule_timer(pj_timer_entry *entry,
const pj_time_val *delay);
+/**
+ * Schedule a callback function to be called after a specified time interval.
+ * Note that the callback may be executed by different thread, depending on
+ * whether worker thread is enabled or not.
+ *
+ * @param cb The callback function.
+ * @param user_data The user data.
+ * @param msec_delay The time interval in msec.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_schedule_timer2(void (*cb)(void *user_data),
+ void *user_data,
+ unsigned msec_delay);
/**
* Cancel the previously scheduled timer.
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
index ec236197..99937d3e 100644
--- a/pjsip/include/pjsua-lib/pjsua_internal.h
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -76,6 +76,7 @@ struct pjsua_call_media
pjmedia_transport *tp; /**< Current media transport (can be 0) */
pj_status_t tp_ready; /**< Media transport status. */
+ pj_status_t tp_result; /**< Media transport creation result. */
pjmedia_transport *tp_orig; /**< Original media transport */
pj_bool_t tp_auto_del; /**< May delete media transport */
pjsua_med_tp_st tp_st; /**< Media transport state */
@@ -456,6 +457,16 @@ struct pjsua_data
#if PJSUA_HAS_VIDEO
pjsua_vid_win win[PJSUA_MAX_VID_WINS]; /**< Array of windows */
#endif
+
+ /* Timer entry list */
+ struct timer_list
+ {
+ PJ_DECL_LIST_MEMBER(struct timer_list);
+ pj_timer_entry entry;
+ void (*cb)(void *user_data);
+ void *user_data;
+ } timer_list;
+ pj_mutex_t *timer_mutex;
};
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index fc47121d..2806123b 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -712,6 +712,18 @@ PJ_DEF(pj_status_t) pjsua_create(void)
&pjsua_var.endpt);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ /* Init timer entry list */
+ pj_list_init(&pjsua_var.timer_list);
+
+ /* Create timer mutex */
+ status = pj_mutex_create_recursive(pjsua_var.pool, "pjsua_timer",
+ &pjsua_var.timer_mutex);
+ if (status != PJ_SUCCESS) {
+ pj_log_pop_indent();
+ pjsua_perror(THIS_FILE, "Unable to create mutex", status);
+ return status;
+ }
+
pjsua_set_state(PJSUA_STATE_CREATED);
pj_log_pop_indent();
return PJ_SUCCESS;
@@ -2603,6 +2615,59 @@ PJ_DEF(pj_status_t) pjsua_schedule_timer( pj_timer_entry *entry,
return pjsip_endpt_schedule_timer(pjsua_var.endpt, entry, delay);
}
+/* Timer callback */
+static void timer_cb( pj_timer_heap_t *th,
+ pj_timer_entry *entry)
+{
+ struct timer_list *tmr = (struct timer_list *)entry->user_data;
+ void (*cb)(void *user_data) = tmr->cb;
+ void *user_data = tmr->user_data;
+
+ PJ_UNUSED_ARG(th);
+
+ pj_mutex_lock(pjsua_var.timer_mutex);
+ pj_list_push_back(&pjsua_var.timer_list, tmr);
+ pj_mutex_unlock(pjsua_var.timer_mutex);
+
+ if (cb)
+ (*cb)(user_data);
+}
+
+/*
+ * Schedule a timer callback.
+ */
+PJ_DEF(pj_status_t) pjsua_schedule_timer2( void (*cb)(void *user_data),
+ void *user_data,
+ unsigned msec_delay)
+{
+ struct timer_list *tmr = NULL;
+ pj_status_t status;
+ pj_time_val delay;
+
+ pj_mutex_lock(pjsua_var.timer_mutex);
+
+ if (pj_list_empty(&pjsua_var.timer_list)) {
+ tmr = PJ_POOL_ALLOC_T(pjsua_var.pool, struct timer_list);
+ } else {
+ tmr = pjsua_var.timer_list.next;
+ pj_list_erase(tmr);
+ }
+ pj_timer_entry_init(&tmr->entry, 0, tmr, timer_cb);
+ tmr->cb = cb;
+ tmr->user_data = user_data;
+ delay.sec = 0;
+ delay.msec = msec_delay;
+
+ status = pjsip_endpt_schedule_timer(pjsua_var.endpt, &tmr->entry, &delay);
+ if (status != PJ_SUCCESS) {
+ pj_list_push_back(&pjsua_var.timer_list, tmr);
+ }
+
+ pj_mutex_unlock(pjsua_var.timer_mutex);
+
+ return status;
+}
+
/*
* Cancel the previously scheduled timer.
*
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index 7665e751..66cecf58 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -766,6 +766,20 @@ on_error:
}
#endif
+static void med_tp_timer_cb(void *user_data)
+{
+ pjsua_call_media *call_med = (pjsua_call_media*)user_data;
+
+ PJSUA_LOCK();
+
+ call_med->tp_ready = call_med->tp_result;
+ if (call_med->med_create_cb)
+ (*call_med->med_create_cb)(call_med, call_med->tp_ready,
+ call_med->call->secure_level, NULL);
+
+ PJSUA_UNLOCK();
+}
+
/* This callback is called when ICE negotiation completes */
static void on_ice_complete(pjmedia_transport *tp,
pj_ice_strans_op op,
@@ -778,12 +792,8 @@ static void on_ice_complete(pjmedia_transport *tp,
switch (op) {
case PJ_ICE_STRANS_OP_INIT:
- PJSUA_LOCK();
- call_med->tp_ready = result;
- if (call_med->med_create_cb)
- (*call_med->med_create_cb)(call_med, result,
- call_med->call->secure_level, NULL);
- PJSUA_UNLOCK();
+ call_med->tp_result = result;
+ pjsua_schedule_timer2(&med_tp_timer_cb, call_med, 1);
break;
case PJ_ICE_STRANS_OP_NEGOTIATION:
if (result != PJ_SUCCESS) {
@@ -1538,9 +1548,7 @@ static pj_status_t media_channel_init_cb(pjsua_call_id call_id,
for (mi=0; mi < call->med_cnt; ++mi) {
pjsua_call_media *call_med = &call->media[mi];
- if (call_med->med_init_cb ||
- call_med->tp_st == PJSUA_MED_TP_NULL)
- {
+ if (call_med->med_init_cb) {
pj_mutex_unlock(call->med_ch_mutex);
return PJ_SUCCESS;
}