105 | | TBD. |
| 107 | Currently, it's only APS-Direct that has been implemented, here are the steps to build an application with APS-Direct feature. |
| 108 | |
| 109 | 1. Enable APS sound device implementation as described [http://trac.pjsip.org/repos/wiki/APS here]. |
| 110 | 1. Enable audio switch board, i.e. in config_site.h: |
| 111 | {{{ |
| 112 | #define PJMEDIA_CONF_USE_SWITCH_BOARD 1 |
| 113 | }}} |
| 114 | 1. Enable passthrough codecs, i.e. in config_site.h: |
| 115 | {{{ |
| 116 | #define PJMEDIA_HAS_PASSTHROUGH_CODECS 1 |
| 117 | }}} |
| 118 | |
| 119 | For building sample application {{{symbian_ua}}}, those steps are enough since it's already prepared to use APS-Direct. |
| 120 | |
| 121 | For general application, there are few more things to be handled: |
| 122 | - Reopening sound device when it needs to change the active format/codec, e.g: when a call is confirmed and stream has been created, the sound device format should be matched to the SDP negotiation result. Here is the sample code for application that using pjsua-lib, reopening sound device is done in {{{on_stream_created()}}} pjsua callback, this will replace the precreated pjsua-lib sound device instance: |
| 123 | {{{ |
| 124 | /* Global sound port. */ |
| 125 | static pjmedia_snd_port *snd_port; |
| 126 | |
| 127 | /* Reopen sound device on on_stream_created() pjsua callback. */ |
| 128 | static void on_stream_created(pjsua_call_id call_id, |
| 129 | pjmedia_session *sess, |
| 130 | unsigned stream_idx, |
| 131 | pjmedia_port **) |
| 132 | { |
| 133 | pjmedia_port *conf; |
| 134 | pjmedia_session_info sess_info; |
| 135 | pjmedia_stream_info *strm_info; |
| 136 | pjmedia_snd_setting setting; |
| 137 | unsigned samples_per_frame; |
| 138 | |
| 139 | /* Get active format for this stream, based on SDP negotiation result. */ |
| 140 | pjmedia_session_get_info(sess, &sess_info); |
| 141 | strm_info = &sess_info.stream_info[stream_idx]; |
| 142 | |
| 143 | /* Init sound device setting based on stream info. */ |
| 144 | pj_bzero(&setting, sizeof(setting)); |
| 145 | setting.format = strm_info->param->info.format; |
| 146 | setting.bitrate = strm_info->param->info.avg_bps; |
| 147 | setting.cng = strm_info->param->setting.cng; |
| 148 | setting.vad = strm_info->param->setting.vad; |
| 149 | setting.plc = strm_info->param->setting.plc; |
| 150 | |
| 151 | /* Close sound device and get the conference port. */ |
| 152 | conf = pjsua_set_no_snd_dev(); |
| 153 | |
| 154 | samples_per_frame = strm_info->param->info.clock_rate * |
| 155 | strm_info->param->info.frm_ptime * |
| 156 | strm_info->param->info.channel_cnt / |
| 157 | 1000; |
| 158 | |
| 159 | /* Reset conference port attributes. */ |
| 160 | conf->info.samples_per_frame = samples_per_frame; |
| 161 | conf->info.clock_rate = 8000; |
| 162 | conf->info.channel_count = 1; |
| 163 | conf->info.bits_per_sample = 16; |
| 164 | |
| 165 | /* Reopen sound device. */ |
| 166 | pjmedia_snd_port_create2(app_pool, |
| 167 | PJMEDIA_DIR_CAPTURE_PLAYBACK, |
| 168 | 0, |
| 169 | 0, |
| 170 | 8000, |
| 171 | 1, |
| 172 | samples_per_frame, |
| 173 | 16, |
| 174 | &setting, |
| 175 | &snd_port); |
| 176 | |
| 177 | /* Connect sound to conference port. */ |
| 178 | pjmedia_snd_port_connect(snd_port, conf); |
| 179 | } |
| 180 | }}} |
| 181 | - Note that sound device instance is now owned and managed by application, so {{{pjsua_media_config.snd_auto_close_time}}} will not work. Here is a very simple sample code to close the sound device immediately when a call get disconnected: |
| 182 | {{{ |
| 183 | /* Callback called by the pjsua-lib when call's state has changed. */ |
| 184 | static void on_call_state(pjsua_call_id call_id, pjsip_event *) |
| 185 | { |
| 186 | pjsua_call_info ci; |
| 187 | |
| 188 | pjsua_call_get_info(call_id, &ci); |
| 189 | |
| 190 | if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { |
| 191 | if (snd_port) { |
| 192 | pjmedia_snd_port_destroy(snd_port); |
| 193 | snd_port = NULL; |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | }}} |