diff options
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 16 | ||||
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua_internal.h | 11 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 65 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 26 |
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; } |