Hello, while testing transport adapters by activating #define TRANSPORT_ADAPTER_SAMPLE in "pjsip-apps/src/pjsua/pjsua_app.c" it seems (and assuming correctly understanding the documentation in "pjsua.h") app_config.cfg.cb.on_create_media_transport is called only for media channels which are 'automatically created' at the moment of initiating/answering a new call. I.e. even if media streams may be created arbitrarily during a pjsua call e.g. by vid call add for these later streams is the above "user-defined" adapter mechanism not available (as well as for inactive streams which exist already but are being activated later during a call e.g. by "vid call enable 1"). (Is this so far correct?) :-) Attached is a small tweak to propose to relax this constraint in order to make that adapter functionality useful also for later created streams. After a little investigating the code in "media_channel_init_cb()" it looks like analogous snippets can be inserted into "call_add_video()" and "call_modify_video()" in "pjsua_vid.c" to achieve that. Maybe having easily overlooked something, is there anything speaking against that idea? Though, if the "user-defined" adapter creator should return NULL (which probably is not the general case), then reading the code it looks like the channel creation request is rejected by PJSIP_SC_TEMPORARILY_UNAVAILABLE; but interestingly this return value sometimes doesn't survive the "on_rx_offer()" callback mechanism; the above response code gets overwritten by PJSIP_SC_NOT_ACCEPTABLE_HERE in "pjsua_vid.c" as seen in the "OverwriteState" attachment. This is probably the case for channels which are created later during a call. Eeri Kask -------------- next part -------------- --- pjsip/src/pjsua-lib/pjsua_vid.c.orig 2014-04-28 12:40:29.000000000 +0200 +++ pjsip/src/pjsua-lib/pjsua_vid.c 2014-05-05 07:56:49.000000000 +0200 @@ -1567,10 +1567,21 @@ call_med->strm.v.cap_dev = cap_dev; /* Init transport media */ - status = pjmedia_transport_media_create(call_med->tp, pool, 0, - NULL, call_med->idx); - if (status != PJ_SUCCESS) - goto on_error; + if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) { + if (call_med->use_custom_med_tp) { + unsigned flags = PJSUA_MED_TP_CLOSE_MEMBER; + call_med->tp = + (*pjsua_var.ua_cfg.cb.on_create_media_transport) + (call->index, call_med->idx, call_med->tp, flags); + if (!call_med->tp) + status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TEMPORARILY_UNAVAILABLE); + } + if (call_med->tp) + status = pjmedia_transport_media_create(call_med->tp, pool, 0, + NULL, call_med->idx); + if (status != PJ_SUCCESS) + goto on_error; + } pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_INIT); @@ -1717,8 +1728,17 @@ /* Init transport media */ if (call_med->tp && call_med->tp_st == PJSUA_MED_TP_IDLE) { - status = pjmedia_transport_media_create(call_med->tp, pool, 0, - NULL, call_med->idx); + if (call_med->use_custom_med_tp) { + unsigned flags = PJSUA_MED_TP_CLOSE_MEMBER; + call_med->tp = + (*pjsua_var.ua_cfg.cb.on_create_media_transport) + (call->index, call_med->idx, call_med->tp, flags); + if (!call_med->tp) + status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_TEMPORARILY_UNAVAILABLE); + } + if (call_med->tp) + status = pjmedia_transport_media_create(call_med->tp, pool, 0, + NULL, call_med->idx); if (status != PJ_SUCCESS) goto on_error; } -------------- next part -------------- --- ./pjsip/src/pjsip-ua/sip_inv.c.orig 2014-05-06 12:57:06.000000000 +0200 +++ ./pjsip/src/pjsip-ua/sip_inv.c 2014-05-06 13:42:55.000000000 +0200 @@ -4515,23 +4515,23 @@ /* The incoming SDP is unacceptable. If the SDP negotiator * state has just been changed, i.e: DONE -> REMOTE_OFFER, * revert it back. */ if (pjmedia_sdp_neg_get_state(inv->neg) == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER) { pjmedia_sdp_neg_cancel_offer(inv->neg); } status = pjsip_dlg_create_response(inv->dlg, rdata, - 488, NULL, &tdata); + PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, &tdata); if (status != PJ_SUCCESS) return; accept = pjsip_endpt_get_capability(dlg->endpt, PJSIP_H_ACCEPT, NULL); if (accept) { pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, accept)); }