Version 7 (modified by bennylp, 16 years ago) (diff) |
---|
Background
pjsua_call.c
Currently this is how the media channel interacts with SIP call in PJSUA-LIB.
- pjsua_call_make_call() :
- pjsua_call_on_incoming() :
- pjsua_call_update() :
- pjsua_call_reinvite() :
- pjsua_call_on_rx_offer() :
- pjsua_call_on_create_offer() :
-
pjsua_media_channel_init();
pjsua_media_channel_create_sdp(&local_sdp, rem_sdp);
- pjsua_call_on_media_update() :
- pjsua_media_channel_update();
- pjsua_call_on_state_changed(DISCONNECTED) :
- pjsua_call_on_media_update(HOLD) :
- pjsua_media_channel_deinit();
pjsua_media.c
and this is the implementation of media channel functions above:
- pjsua_media_channel_init() :
- pjmedia_transport_srtp_create();
- pjsua_media_channel_create_sdp() :
-
pjmedia_endpt_create_sdp();
pjmedia_transport_media_create();
- pjsua_media_channel_update() :
-
pjmedia_transport_media_start();
pjmedia_session_create();
- pjsua_media_channel_deinit() :
-
stop_media_session();
pjmedia_transport_media_stop();
pjmedia_transport_close(srtp);
New
New code in italics. Deleted code is in strike-through.
pjsua_call.c
This is the proposed interaction:
- pjsua_call_make_call() :
- pjsua_call_on_incoming() :
-
pjsua_media_channel_init();
pjsua_media_channel_create_sdp(&local_sdp, rem_sdp);
pjsua_media_channel_init(&local_sdp, rem_sdp);
- pjsua_call_update() :
- pjsua_call_reinvite() :
- pjsua_call_on_rx_offer() :
- pjsua_call_on_create_offer() :
-
pjsua_media_channel_init(&local_sdp, rem_sdp);
pjsua_media_channel_create_sdp(&local_sdp, rem_sdp);
- pjsua_call_on_media_update() :
- pjsua_media_channel_update();
- pjsua_call_on_state_changed(DISCONNECTED) :
- pjsua_call_on_media_update(HOLD) :
- pjsua_media_channel_deinit();
pjsua_media.c
and this is the implementation of media channel functions above:
- pjsua_media_channel_init(&local_sdp, rem_sdp) :
-
pjmedia_transport_srtp_create();
pjmedia_transport_media_create(local_sdp, rem_sdp);
pjmedia_transport_media_create(rem_sdp);
pjmedia_transport_encode_sdp(local_sdp, rem_sdp);
- pjsua_media_channel_create_sdp(&local_sdp, rem_sdp) :
-
pjmedia_endpt_create_sdp();
pjmedia_transport_media_create(local_sdp, rem_sdp);
pjmedia_transport_encode_sdp(local_sdp, rem_sdp);
- pjsua_media_channel_update() :
-
pjmedia_transport_media_start();
pjmedia_session_create();
- pjsua_media_channel_deinit() :
-
stop_media_session();
pjmedia_transport_media_stop();
pjmedia_transport_close(srtp);
Changes in Transport
- media_create()
-
- The semantic has changed:
- previously this function is always called everytime we want to send offer
- now this function is only called once when the transport needs to be created. Meaning once before call, and once the session is woken up after call hold. When media is already created and the application wants to send offer, it will just call encode_sdp() below without re-creating the media.
- The syntax has changed:
- local_sdp parameter is removed. Local SDP should be populated in encode_sdp() instead. This is to make it consistent since SDP can be created without re-creating media.
- The semantic has changed:
- New: encode_sdp()
-
- This function is used to modify local SDP with transport info. It can be called for different purposes below.
- media_start()
-
- The syntax has changed:
- the local SDP is now const. This is because it's useless to modify the local SDP there since the SDP has already been negotiated.
- The syntax has changed:
Sample: ICE processing with the new media framework
Generating initial offer
This happens in encode_sdp(), when ICE is not running and {{{rem_sdp==NULL}}. The transport will include all ICE candidates in the offer.
Generating initial answer
First, the transport detects whether the remote offer contains ICE in media_create(). If yes, it marks use_ice=True.
Then in encode_sdp(), it checks if ICE is already running. Since this is an initial answer, ICE is not running yet. So it puts all candidates in the answer. In this function, the transport also checks for ICE-mismatch.
Generating subsequent offer
This happens in encode_sdp(), when ICE is already running and rem_sdp==NULL. The transport fills in the SDP with selected candidate only, one for each component.
Generating subsequent answer
This happens in encode_sdp(), when ICE is already running and rem_sdp is present. The transport detects for ICE restart condition or if the new offer no longer contains support for ICE. If ICE is restarted, then the internal ICE session will be destroyed and re-created.
The populated SDP depends on whether ICE is restarted or not. If ICE doesn't restart, then the answer contains only the selected candidate from the valid pairs, just like Generating subsequent offer above. If ICE is restarted, then it will contains all candidates.
media_start() processing
When we send offer, this is where we will see the remote answer for the first time. So we do the "heavy" negotiation here.
For ICE:
- Detect if answer contains ICE support ==> disable ICE
- Handle answer that contains ice-mismatch attribute ==> disable ICE
- Handle answer with transport address that doesn't match any candidates ==> disable ICE
- Handle when we set our role as Controlled, but answer contains ice-list ==> change role to Controlling
- If remote SDP contains the same ice-ufrag and ice-pwd as previous SDP, that means there's no change in the offer/answer, no need to do anything.
If things are okay, start ICE negotiation.
Bug
With the new framework, there's still a bug. The offer/answer RFC says that if UPDATE or re-INVITE fails, the media should remain unchanged, i.e. it falls back to use the previously successfully negotiated media.
That's not possible with the framework above, for the generating subsequent answer case above. Solving this is currently not possible with ICE, since that requires creating a new/fresh ice_strans everytime we receive updated offer, just in case the offer/answer fails so that we can revert back to old ice_strans.
Attachments (1)
-
ICE_SDP.png
(14.6 KB) -
added by bennylp 16 years ago.
ICE offer/answer flow chart
Download all attachments as: .zip