summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
authorLiong Sauw Ming <ming@teluu.com>2011-06-16 05:10:45 +0000
committerLiong Sauw Ming <ming@teluu.com>2011-06-16 05:10:45 +0000
commitd1fc1193fc57517f5adc32bc2e0b9077fd367304 (patch)
treed7e0d008d09a3468974bca26b23f97baf15c83e4 /pjsip
parent6e5dd25621edefef5a17a000bd75b0d825d6c32f (diff)
Closed #1173: PJSUA callback to allow creation of custom media transports by application
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.x@3585 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h42
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c25
2 files changed, 66 insertions, 1 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 404b140c..b52990eb 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -421,6 +421,22 @@ typedef struct pjsua_reg_info
/**
+ * This enumeration specifies the options for custom media transport creation.
+ */
+typedef enum pjsua_create_media_transport_flag
+{
+ /**
+ * This flag indicates that the media transport must also close its
+ * "member" or "child" transport when pjmedia_transport_close() is
+ * called. If this flag is not specified, then the media transport
+ * must not call pjmedia_transport_close() of its member transport.
+ */
+ PJSUA_MED_TP_CLOSE_MEMBER = 1
+
+} pjsua_create_media_transport_flag;
+
+
+/**
* This structure describes application callback to receive various event
* notification from PJSUA-API. All of these callbacks are OPTIONAL,
* although definitely application would want to implement some of
@@ -918,6 +934,32 @@ typedef struct pjsua_callback
void (*on_ice_transport_error)(int index, pj_ice_strans_op op,
pj_status_t status, void *param);
+ /**
+ * This callback can be used by application to implement custom media
+ * transport adapter for the call, or to replace the media transport
+ * with something completely new altogether.
+ *
+ * This callback is called when a new call is created. The library has
+ * created a media transport for the call, and it is provided as the
+ * \a base_tp argument of this callback. Upon returning, the callback
+ * must return an instance of media transport to be used by the call.
+ *
+ * @param call_id Call ID
+ * @param media_idx The media index in the SDP for which this media
+ * transport will be used.
+ * @param base_tp The media transport which otherwise will be
+ * used by the call has this callback not been
+ * implemented.
+ * @param flags Bitmask from pjsua_create_media_transport_flag.
+ *
+ * @return The callback must return an instance of media
+ * transport to be used by the call.
+ */
+ pjmedia_transport* (*on_create_media_transport)(pjsua_call_id call_id,
+ unsigned media_idx,
+ pjmedia_transport *base_tp,
+ unsigned flags);
+
} pjsua_callback;
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index f6791131..bf121e78 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -1174,6 +1174,8 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
{
pjsua_call *call = &pjsua_var.calls[call_id];
pj_status_t status;
+ pj_bool_t use_custom_med_tp = PJ_FALSE;
+ unsigned custom_med_tp_flags = 0;
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
pjsua_acc *acc = &pjsua_var.acc[call->acc_id];
@@ -1192,11 +1194,17 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
return PJ_EBUSY;
}
+ if (!call->med_orig &&
+ pjsua_var.ua_cfg.cb.on_create_media_transport)
+ {
+ use_custom_med_tp = PJ_TRUE;
+ }
+
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
/* This function may be called when SRTP transport already exists
* (e.g: in re-invite, update), don't need to destroy/re-create.
*/
- if (!call->med_orig || call->med_tp == call->med_orig) {
+ if (!call->med_orig) {
/* Check if SRTP requires secure signaling */
if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) {
@@ -1210,6 +1218,8 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
/* Always create SRTP adapter */
pjmedia_srtp_setting_default(&srtp_opt);
srtp_opt.close_member_tp = PJ_FALSE;
+ if (use_custom_med_tp)
+ custom_med_tp_flags |= PJSUA_MED_TP_CLOSE_MEMBER;
/* If media session has been ever established, let's use remote's
* preference in SRTP usage policy, especially when it is stricter.
*/
@@ -1268,6 +1278,18 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
PJ_LOG(4,(THIS_FILE, "Media index %d selected for call %d",
call->audio_idx, call->index));
+ if (use_custom_med_tp) {
+ /* Use custom media transport returned by the application */
+ call->med_tp = (*pjsua_var.ua_cfg.cb.on_create_media_transport)(
+ call_id, call->audio_idx, call->med_tp,
+ custom_med_tp_flags);
+ if (!call->med_tp) {
+ if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE;
+ pjsua_media_channel_deinit(call_id);
+ return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE);
+ }
+ }
+
/* Create the media transport */
status = pjmedia_transport_media_create(call->med_tp, tmp_pool, 0,
rem_sdp, call->audio_idx);
@@ -1543,6 +1565,7 @@ pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id)
if (call->med_orig && call->med_tp && call->med_tp != call->med_orig) {
pjmedia_transport_close(call->med_tp);
call->med_tp = call->med_orig;
+ call->med_orig = NULL;
}
check_snd_dev_idle();