715 | | Basically the idea is to manage the in the application, rather than in PJSUA-LIB. Since we manage the media ourselves, we can design the media interconnection to whatever suit the requirements. One possible design is to create one conference bridge for each call, so that each call's media (including anything related to the call, such as WAV files, tone generators, outgoing call leg, etc.) runs on its own thread. |
| 715 | Basically the idea is to manage the media in the application, rather than in PJSUA-LIB. Since we manage the media ourselves, we can design the media interconnection to whatever suit the requirements. One possible design is to create one conference bridge for each call, so that each call's media (including anything related to the call, such as WAV files, tone generators, outgoing call leg, etc.) runs on its own thread. |
718 | | 1. First thing we should do is to stop the PJSUA-LIB's conference bridge. This can be accomplished by calling [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g4b6ffc203b8799f08f072d0921777161 pjsua_set_no_snd_dev()]. With this call, PJSUA-LIB would not connect the conference bridge to any sound devices (including NULL sound device), so basically it would not run. |
719 | | 1. Because the main conference bridge is no longer working, we cannot use the usual PJSUA-LIB's API to add media ports (thing such as [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g90a2ec9c8516b5ad13b061a46ae1d07a pjsua_player_create()]), since these API adds the media ports to the main bridge, which no longer works of course. |
720 | | 1. When a call's media is established (like when the call is CONFIRMED), PJSUA-LIB will still register the call's stream to the main bridge, but we can just ignore this. The main bridge has been stopped, so although the stream is ''registered'' to it, it won't try to retrieve or send any audio to the stream. |
| 718 | 1. First thing we should do is to stop the PJSUA-LIB's conference bridge from running. This can be accomplished by calling [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g4b6ffc203b8799f08f072d0921777161 pjsua_set_no_snd_dev()]. With this call, PJSUA-LIB would not connect the conference bridge to any sound devices (including NULL sound device), so basically it would not run. |
| 719 | 1. Because the main conference bridge is no longer running/working, we cannot use the usual PJSUA-LIB's API to add media ports (functions such as [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g90a2ec9c8516b5ad13b061a46ae1d07a pjsua_player_create()]), since these API adds the media ports to the main bridge, which no longer works of course. |
| 720 | 1. When a call's media is established (like when the call is CONFIRMED), PJSUA-LIB will still register the call's stream to the main bridge, but we can just ignore this. The main bridge has been stopped, so although the stream is ''registered'' to it, it won't try to retrieve or send any audio frames from/to the stream. |
753 | | 1. Add call's media to the conference bridge. Unfortunately call's media is not normally exposed to PJSUA application, so we would need to include {{{<pjsua-lib/pjsua_internal.h>}}} to access it: |
754 | | {{{ |
755 | | #include <pjsua-lib/pjsua_internal.h> |
756 | | |
757 | | .. |
758 | | pjsua_call *call = &pjsua_var.calls[call_id]; |
759 | | pjmedia_port *stream; |
760 | | |
761 | | pjmedia_session_get_port(call->session, 0, &stream); |
762 | | pjmedia_conf_add_port(cd->conf, cd->pool, stream, NULL, &cd->call_slot); |
| 753 | 1. Implement {{{on_stream_created()}}} callback of {{{pjsua_callback}}}. This callback notifies application when a stream has been created and about to be registered to the bridge. We'll use this callback to add the stream's media port to our own conference bridge: |
| 754 | {{{ |
| 755 | static void on_stream_created(pjsua_call_id call_id, |
| 756 | pjmedia_session *sess, |
| 757 | unsigned stream_idx, |
| 758 | pjmedia_port **p_port) |
| 759 | { |
| 760 | pjmedia_conf_add_port(cd->conf, cd->pool, *p_port, NULL, &cd->call_slot); |
| 761 | } |
765 | | 1. Since we're allocating resources for the call, don't forget to release these resources once the call is disconnected: |
| 764 | 1. Since stream may be destroyed during a call (for example, when call is put on hold), we need to remove the stream from our conference bridge when the stream is destroyed, otherwise application will crash because the conference bridge tries to retrieve/put audio frames from/to a non-existant stream. This can be done by implementing {{{on_stream_destroyed()}}} callback: |
| 765 | {{{ |
| 766 | static void on_stream_destroyed(pjsua_call_id call_id, |
| 767 | pjmedia_session *sess, |
| 768 | unsigned stream_idx) |
| 769 | { |
| 770 | pjmedia_conf_remove_port(cd->conf, &cd->call_slot); |
| 771 | } |
| 772 | }}} |
| 773 | 1. Finally, don't forget to release the resources when the call is disconnected. |