Changes between Version 3 and Version 4 of FAQ


Ignore:
Timestamp:
Sep 24, 2007 3:58:36 PM (17 years ago)
Author:
bennylp
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • FAQ

    v3 v4  
    2121=== What about the "viral" nature of the GPL? === #gpl-viral 
    2222 
    23 People often think that using GPL-ed software means that other software linked with the GPL software have to be GPL too, hence GPL is considered as viral. '''That is not exactly true''', especially with PJSIP. When linking with PJSIP, only  your application (that is based on PJSIP) has to be GPL-ed, since it is considered as derived work. Other libraries linked with PJSIP don't have to be GPL, because we specifically allow linking PJSIP with third party libraries, as long as they are listed in [http://www.pjsip.org/licensing.htm Third Party Software] that are allowed to be linked with PJSIP. 
     23People often think that using GPL-ed software means that other software linked with the GPL software have to be GPL too, hence GPL is considered as viral. '''That is not exactly true''', especially with PJSIP. When linking with PJSIP, only the application (that is based on PJSIP) has to be GPL-ed, since it is considered as derived work. Other libraries linked with PJSIP don't have to be GPL, because we specifically allow linking PJSIP with third party libraries, as long as they are listed in [/licensing.htm Third Party Software] that are allowed to be linked with PJSIP. 
    2424 
    2525 
    2626=== Can I develop closed source products with PJSIP? === #proprietary 
    2727 
    28 It depends. We use the standard GPL v2 or later for PJSIP, and GPL does allow using GPL-ed code for closed source development, '''as long as the resulting product is not redistributed''' (for example, it is only used for internal purpose). Please see [http://www.gnu.org/licenses/gpl-faq.html GPL FAQ] for more information about what you can/can't do with GPL software. 
     28It depends. We use the standard GPL v2 or later for PJSIP, and GPL does allow using GPL-ed code for closed source development, '''as long as the resulting product is not redistributed''' (for example, it is only used for internal purpose). Please see [http://www.gnu.org/licenses/gpl-faq.html GPL FAQ] for more information about what can/can't be done with GPL software. 
    2929 
    3030Alternatively, we can discuss alternative licensing for PJSIP, please contact support@pjsip.org for details. 
     
    4141=== Where can I find the latest release of PJSIP? === #latest 
    4242 
    43 The latest PJSIP is always the SVN trunk version. You can find information on how to retrieve PJSIP from SVN in the [http://www.pjsip.org/download.htm PJSIP Download] and [http://www.pjsip.org/using.htm Getting Started] page. 
     43The latest PJSIP is always the SVN trunk version. Please find the information on how to retrieve PJSIP from SVN in the [/download.htm PJSIP Download] and [/using.htm Getting Started] page. 
     44 
     45=== If PJSIP is said to be small footprint, then why the source is so big? === #src-large 
     46 
     47It is common in all projects to have source distribution that is larger than the resulting build. This is because source distribution contains other things such as documentations and scripts. The source tarball of PJSIP v0.7 is significantly larger than v0.5 because in v0.7 we include third party libraries in their original form of distribution, so that they get proper attribution and for easier update, unlike in v.0.5 where we just picked the source files that we like and included them in PJSIP. 
    4448 
    4549---- 
     
    4953=== I'm having problem building PJSIP, please help! === #build-problems 
    5054 
    51 You should check the [http://www.pjsip.org/using.htm Getting Started] page. 
     55Please check the [/using.htm Getting Started] page. 
    5256 
    5357=== I'm getting "Unable to open DSound.h error", please help! === #dsound 
    5458 
    55 You should really check the [http://www.pjsip.org/using.htm Getting Started] page first. 
     59You should really check the [/using.htm Getting Started] page first. 
    5660 
    5761---- 
     
    6165=== Can I use the SIP stack with my own media stack? === 
    6266 
    63 Sure. The SIP stack (pjsip) and media stack (pjmedia) is independent from one another, and they are only integrated at the higher level user agent library (pjsua-lib). Please see the library architecture diagram on [http://www.pjsip.org/docs.htm PJSIP Documentation] page for reference. 
    64  
    65 So yes, you can use the SIP stack (pjsip) without having to use pjmedia, as long as you don't use pjsua-lib. 
     67Sure. The SIP stack (pjsip) and media stack (pjmedia) is independent from one another, and they are only integrated at the higher level user agent library (pjsua-lib). Please see the library architecture diagram on [/docs.htm PJSIP Documentation] page for reference. 
     68 
     69So yes, the SIP stack (pjsip) can be used without pjmedia, as long as you don't use pjsua-lib. 
    6670 
    6771 
     
    7276=== What platforms are PJSIP known to run on? === #platforms 
    7377 
    74 PJSIP runs on many platforms, embedded or non-embedded. Please see the platforms list that it currently supports in [http://www.pjsip.org/sip_media_features.htm#platforms Platform features] page. Apart from the platforms that we maintain ourselves, the community have also been constantly finding new platforms that PJSIP can run on. For now we don't maintain list of platforms that the community have ported PJSIP to, but you can search for them in the mailing list archive. 
     78PJSIP runs on many platforms, embedded or non-embedded. Please see the platforms list that it currently supports in [/sip_media_features.htm#platforms Platform features] page. Apart from the platforms that we maintain ourselves, the community have also been constantly finding new platforms that PJSIP can run on, for example on [http://libw11.free.fr/ Nintendo DS] (a cool project by Samuel Vinson), and also on various platforms based on uC-Linux and ARM processor. 
    7579 
    7680 
    7781=== How can I port PJSIP to platform XYZ? === #porting 
    7882 
    79 PJSIP has been designed for ultra-portability, and we have ported PJSIP to exotic platform such as Symbian (long time ago, PJSIP has also been ported to Linux kernel). People even have ported PJSIP to even more exotic platforms such as Nintendo DS and Texas Instrument (TI) DSP. So there is a good chance that PJSIP will be ''port''-able to your platform. 
    80  
    81 You can start from the [http://www.pjsip.org/porting.htm Porting] page. For additional information, there is also information on porting [http://www.pjsip.org/sip_symbian.htm PJSIP to Symbian], to emphasize that even on difficult platform like this, PJSIP is still ''port''-able. 
     83PJSIP has been designed for ultra-portability, and we have ported PJSIP to exotic platform such as Symbian (long time ago, PJSIP has also been ported to Linux kernel). People even have ported PJSIP to even more exotic platforms such as [http://libw11.free.fr/ Nintendo DS] (ported by Samuel Vinson) and Texas Instrument (TI) DSP. So there is a good chance that PJSIP will be ''port''-able to your platform. 
     84 
     85Please start from the [/porting.htm Porting] page. For additional information, there is also information on porting [/sip_symbian.htm PJSIP to Symbian], to emphasize that even on difficult platform like this, PJSIP is still ''port''-able. 
    8286 
    8387---- 
     
    8791=== I'm having problems with no/poor audio (quality), please help! === #audio-problem 
    8892 
    89 We have created a Wiki page dedicated for troubleshooting all sorts of audio problems, please follow the instructions in http://www.pjsip.org/trac/wiki/sound-problems. If this does not solve your problem, please consult the [http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org PJSIP mailing list] 
     93We have created a Wiki page dedicated for troubleshooting all sorts of audio problems, please follow the instructions in [wiki:sound-problems Troubleshooting Sound Problems wiki]. If this does not solve your problem, please consult the [http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org PJSIP mailing list]. 
    9094 
    9195=== I'm having problems with echo, please help === #echo 
     
    9397Please see above. 
    9498 
     99=== How to run PJSUA without sound device? === #no-snd-dev 
     100 
     101Some PJSUA-LIB based applications do not need to interact with local sound device, thus do not need to have sound device in the deployed machine. PJSUA-LIB indeed supports running the media without sound device. With ''pjsua'' application, you can run ''pjsua'' without sound device with {{{--null-audio}}} option. 
     102 
     103 
     104=== How can I adjust the audio volume level? === #audio-volume 
     105 
     106The easiest is to adjust the audio level in the conference bridge, using: 
     107 - [/pjmedia/docs/html/group__PJMEDIA__CONF.htm#g8895228fdc9b7d6892320aa03b198574 pjmedia_conf_adjust_rx_level()] and [/pjmedia/docs/html/group__PJMEDIA__CONF.htm#gff0b554ee974c7905071f1051eeb4479 pjmedia_conf_adjust_tx_level()], if you use PJMEDIA directly, or 
     108 - [/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#gac62b6ef2ec5dd2f8717809548201e89 pjsua_conf_adjust_rx_level()] and [/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#gd828a91a6ee5d361ecb07fa818e17e41 pjsua_conf_adjust_tx_level()] if you use PJSUA-API. 
     109 
     110Note that the two different APIs have different level adjustment value; PJMEDIA expects the value in integer, while PJSUA expects the value in floating point. Please see the API documentation for the details. 
     111 
     112Another way to manage the audio level is to use the operating system specific API to adjust the audio device level directly. Currently PJMEDIA does not provide portable APIs to interact with audio device level, so please see the operating system SDK documentation for information on how to achieve this. 
     113 
     114 
    95115=== Why does PJSIP refuse to send DTMF to remote? === #rfc-2833 
    96116 
     
    101121}}} 
    102122 
    103 Without receiving this capability indication, PJSIP will refuse to send RFC 2833 event, and a call to {{{pjsua_call_dial_dtmf()}}} or {{{pjmedia_session_dial_dtmf()}}} or {{{pjmedia_stream_dial_dtmf()}}} will return error code '''[http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__ERRNO.htm#g043502be6c0961209feade822cdd79b7 PJMEDIA_RTP_EREMNORFC2833]'''. In this case, you can send the [#inband-dtmf DTMF tone inband] instead (see below). 
     123Without receiving this capability indication, PJSIP will refuse to send RFC 2833 event, and a call to {{{pjsua_call_dial_dtmf()}}} or {{{pjmedia_session_dial_dtmf()}}} or {{{pjmedia_stream_dial_dtmf()}}} will return error code [/pjmedia/docs/html/group__PJMEDIA__ERRNO.htm#g043502be6c0961209feade822cdd79b7 PJMEDIA_RTP_EREMNORFC2833]. In this case, you can send the [#inband-dtmf DTMF tone inband] instead (see below). 
    104124 
    105125 
    106126=== How can I send inband DTMF tones? === #inband-dtmf 
    107127 
    108 It's quite easy with [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB.htm PJSUA-LIB] API: 
    109  1. Once you get the call established, create an instance of [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__MF__DTMF__TONE__GENERATOR.htm Tone Generator]. 
    110  1. Register this tone generator to pjsua's conference bridge, by calling [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g833528c1019f4ab5c8fb216b4b5f788b pjsua_conf_add_port()]. 
    111  1. ''Connect'' the tone generator to the call, with [http://www.pjsip.org/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g3451304d677e013130dfb9e6b37e3ee6 pjsua_conf_connect()]. 
    112  1. Now instruct the tone generator to ''play'' some DTMF digits ([http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__MF__DTMF__TONE__GENERATOR.htm#gf7920b73983e1e09dfe883cbdd2861ae pjmedia_tonegen_play_digits()]). The digits then will be streamed to the call, and remote endpoint should receive the DTMF tone inband. 
     128It's quite easy with [/pjsip/docs/html/group__PJSUA__LIB.htm PJSUA-LIB] API: 
     129 1. Once the call is established, create an instance of [/pjmedia/docs/html/group__PJMEDIA__MF__DTMF__TONE__GENERATOR.htm Tone Generator]. 
     130 1. Register this tone generator to pjsua's conference bridge, by calling [/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g833528c1019f4ab5c8fb216b4b5f788b pjsua_conf_add_port()]. 
     131 1. ''Connect'' the tone generator to the call, with [/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g3451304d677e013130dfb9e6b37e3ee6 pjsua_conf_connect()]. 
     132 1. Now instruct the tone generator to ''play'' some DTMF digits ([/pjmedia/docs/html/group__PJMEDIA__MF__DTMF__TONE__GENERATOR.htm#gf7920b73983e1e09dfe883cbdd2861ae pjmedia_tonegen_play_digits()]). The digits then will be streamed to the call, and remote endpoint should receive the DTMF tone inband. 
     133 
     134Here is a snippet to do it: 
     135 
     136{{{ 
     137struct my_call_data 
     138{ 
     139   pj_pool_t          *pool; 
     140   pjmedia_port       *tonegen; 
     141   pjsua_conf_port_id  toneslot; 
     142}; 
     143 
     144struct my_call_data *call_init_tonegen(pjsua_call_id call_id) 
     145{ 
     146  pj_pool_t *pool; 
     147  struct my_call_data *cd; 
     148  pjsua_call_info ci; 
     149 
     150  pool = pjsua_pool_create("mycall", 512, 512); 
     151  cd = PJ_POOL_ZALLOC_T(pool, struct my_call_data); 
     152  cd->pool = pool; 
     153 
     154  pjmedia_tonegen_create(cd->pool, 8000, 1, 160, 16, 0, &cd->tonegen); 
     155  pjsua_conf_add_port(cd->pool, cd->tonegen, &cd->toneslot); 
     156 
     157  pjsua_call_get_info(call_id, &ci); 
     158  pjsua_conf_connect(ci.conf_slot, cd->toneslot); 
     159 
     160  pjsua_call_set_user_data(call_id, (void*) cd); 
     161 
     162  return cd; 
     163} 
     164 
     165void call_play_digit(pjsua_call_id call_id, const char *digits) 
     166{ 
     167  pjmedia_tone_digit d[16]; 
     168  unsigned i, count = strlen(digits); 
     169  struct my_call_data *cd; 
     170 
     171  cd = (struct my_call_data*) pjsua_call_get_user_data(call_id); 
     172  if (!cd) 
     173     cd = call_init_tonegen(call_id); 
     174 
     175  if (count > PJ_ARRAY_SIZE(d)) 
     176    count = PJ_ARRAY_SIZE(d); 
     177 
     178  pj_bzero(d, sizeof(d)); 
     179  for (i=0; i<count; ++i) { 
     180    d[i].digit = digits[i]; 
     181    d[i].on_msec = 100; 
     182    d[i].off_msec = 200; 
     183    d[i].volume = 0; 
     184  } 
     185 
     186  pjmedia_tonegen_play_digits(cd->tonegen, count, d, 0); 
     187} 
     188 
     189void call_deinit_tonegen(pjsua_call_id call_id) 
     190{ 
     191  struct my_call_data *cd; 
     192 
     193  cd = (struct my_call_data*) pjsua_call_get_user_data(call_id); 
     194  if (!cd) 
     195     return; 
     196 
     197  pjsua_conf_remove_port(cd->toneslot); 
     198  pjmedia_port_destroy(cd->tonegen); 
     199  pj_pool_release(cd->pool); 
     200 
     201  pjsua_call_set_user_data(call_id, NULL); 
     202} 
     203}}} 
     204 
     205Since we're allocating resources for the call, these resources must be released once the call is disconnected. We should do this in {{{on_call_state()}}} callback: 
     206 
     207{{{ 
     208static void on_call_state(pjsua_call_id call_id, pjsip_event *e) 
     209{ 
     210   pjsua_call_info call_info; 
     211 
     212   pjsua_call_get_info(call_id, &call_info); 
     213 
     214   if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) { 
     215      call_deinit_tonegen(call_id); 
     216   } 
     217} 
     218}}} 
     219 
     220With the above snippet, we just need to call '''call_play_digit()''' every time we need to send inband DTMF digit.  
     221 
     222=== I didn't hear ringing tones when I make a call, why? === #ringtone 
     223 
     224''pjsua'' does not play any ring tones when the call gets 180/Ringing, since it's just a simple application for demonstration purpose. When you're building your own application, you can add this feature yourself. You can play a ringing tone by using the tone generator as described above (but connecting the tone generator to the sound device instead of to the call), or you can play your own WAV file instead. 
    113225 
    114226 
     
    117229In PJMEDIA default setup, media flow is normally triggered by the ''clock'' from the audio device. We made this kind of design to ensure that the audio device always gets fed whenever it needs to be fed, and also since this design would work best for DSP devices, where audio flow would be triggered by some kind of (soft) IRQs thus it should provide the best timing source for audio flow (and without needing to have multi-threading capability). 
    118230 
    119 Unfortunately, not all audio devices provide good timing. Especially in PC world, and also with some uC-Linux based development boards that only support OSS, it is very common to have sound cards that can't provide reliable timing. On these platforms, you will notice that audio frames come in burst rather than one by one and spaced equally. So with 20ms ''ptime'' for example, rather than having one frame every 20ms, these devices would give PJMEDIA three or four frames every 60ms or 80ms. Since RTP packets are transmitted as soon as audio frame is available from the sound card, this would cause PJMEDIA to transmit RTP packets at (what looks like) irregular interval. 
     231Unfortunately, not all audio devices provide good timing. Especially in PC world, and also with some uC-Linux based development boards that only support OSS, it is very common to have sound cards that can't provide reliable timing. On these platforms, audio frames will come in burst rather than one by one and spaced equally. So with 20ms ''ptime'' for example, rather than having one frame every 20ms, these devices would give PJMEDIA three or four frames every 60ms or 80ms. Since RTP packets are transmitted as soon as audio frame is available from the sound card, this would cause PJMEDIA to transmit RTP packets at (what looks like) irregular interval. 
    120232 
    121233In my opinion, this should be fine, as the remote endpoint should be able to accommodate this with its ''jitter buffer''. 
    122234 
    123 If you don't like this, and you'd rather want PJMEDIA to transmit RTP packets at good interval, you can install a [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__MASTER__PORT.htm master clock port] between sound device and conference bridge, so that the master port will drive the media clock instead. A master clock port uses an internal thread to drive the media flow, so it should provide better timing on most platforms. 
     235If you don't like this, and rather want PJMEDIA to transmit RTP packets at good interval, you can install a [/pjmedia/docs/html/group__PJMEDIA__MASTER__PORT.htm master clock port] between sound device and conference bridge, so that the master port will drive the media clock instead. A master clock port uses an internal thread to drive the media flow, so it should provide better timing on most platforms. 
    124236 
    125237The steps to install master port between sound device and conference bridge are as follows: 
    126  1. Create a [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__SPLITCOMB.htm splitter/combiner (splitcomb) port]. 
    127  1. Create a reverse phase port on the splitcomb ([http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__SPLITCOMB.htm#gc59338fd9d471a14c06b0f51c2290b68 pjmedia_splitcomb_create_rev_channel()]). 
    128  1. Create the [http://www.pjsip.org/pjmedia/docs/html/group__PJMED__SND__PORT.htm sound device port] as usual. 
    129  1. Connect the sound device port to the splitcomb (use [http://www.pjsip.org/pjmedia/docs/html/group__PJMED__SND__PORT.htm#g046156b765a34e6c640b0534e6b21f9c pjmedia_snd_port_connect()]). 
    130  1. Create a [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__MASTER__PORT.htm master clock port], and specify the splitcomb's reverse channel as the ''upstream'' port, and the [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__CONF.htm conference bridge] as the ''downstream'' port. 
     238 1. Create a [/pjmedia/docs/html/group__PJMEDIA__SPLITCOMB.htm splitter/combiner (splitcomb) port]. 
     239 1. Create a reverse phase port on the splitcomb ([/pjmedia/docs/html/group__PJMEDIA__SPLITCOMB.htm#gc59338fd9d471a14c06b0f51c2290b68 pjmedia_splitcomb_create_rev_channel()]). 
     240 1. Create the [/pjmedia/docs/html/group__PJMED__SND__PORT.htm sound device port] as usual. 
     241 1. Connect the sound device port to the splitcomb (use [/pjmedia/docs/html/group__PJMED__SND__PORT.htm#g046156b765a34e6c640b0534e6b21f9c pjmedia_snd_port_connect()]). 
     242 1. Create a [/pjmedia/docs/html/group__PJMEDIA__MASTER__PORT.htm master clock port], and specify the splitcomb's reverse channel as the ''upstream'' port, and the [/pjmedia/docs/html/group__PJMEDIA__CONF.htm conference bridge] as the ''downstream'' port. 
    131243 1. Start the master port. 
    132244 
    133 For example, if you normally ''connect'' the sound device to the conference bridge (the default setup in pjsua-lib) with the code below: 
     245For example, normally we ''connect'' the sound device to the conference bridge (the default setup in pjsua-lib) with the code below: 
    134246 
    135247{{{ 
     
    143255}}} 
    144256 
    145 Then the change required to install master clock between sound device and conference bridge would be something like this: 
     257The change required to install master clock between sound device and conference bridge would be something like this: 
    146258 
    147259{{{ 
     
    164276}}} 
    165277 
     278(Note that with PJSUA-LIB, we can get the instance of the conference bridge by calling [/pjsip/docs/html/group__PJSUA__LIB__MEDIA.htm#g4b6ffc203b8799f08f072d0921777161 pjsua_set_no_snd_dev()]). 
     279 
     280With the above snippet, the irregularity of the sound device clock will be ''normalized'' by the master port, so the conference bridge will be run by the ''good'' clock. Of course this means some buffering is needed to compensate the ''clock'' difference between the sound device and the master port, and this is what the ''reverse channel'' of the ''splitcomb'' is for. The ''reverse channel'' can accommodate up to [/pjmedia/docs/html/group__PJMEDIA__CONFIG.htm#ga2e53b9eb4cb76294f95a15a2a0ef8cc PJMEDIA_SOUND_BUFFER_COUNT] frames, so if the clock difference is larger than this, you will need to enlarge {{{PJMEDIA_SOUND_BUFFER_COUNT}}} to an acceptable value (32, for example). 
     281 
     282 
    166283 
    167284=== Does PJSIP support G.723 or G.729 codec? === #g729-g723 
     
    171288No, because there is no ready to use G.723/G.729 codec implementation in PJMEDIA. We specifically don't include G.723/G.729 support in our code because G.723/G.729 are both patented and royalty based codecs, so we are quite nervous with the possibility that some lawyers may contact us should we include them in PJMEDIA. So our decision is to include only free and open source codec in PJMEDIA. 
    172289 
    173 But yes, because you can always add your own codec in PJMEDIA. Please see [#adding-codec Adding a new codec] question below for more info. 
     290But yes, because we can always add more codecs in PJMEDIA. Please see [#adding-codec Adding a new codec] question below for more info. 
    174291 
    175292=== How to add new codec to PJMEDIA? === #adding-codec 
    176293 
    177 First of all, read the [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__CODEC.htm Codec Framework] documentation. Then, the easiest is to take other codec source file in {{{pjmedia-codec}}} directory (such as [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c gsm.c]), and replace GSM specific function calls with the functions that are provided by your codec library. 
    178  
    179 Once you're finished, you should end up with just two public APIs exported by your codec: the initialization function, and the deinitialization function. 
    180  
    181 Then register your codec to PJMEDIA in your application by calling the codec initialization function. After this, your codec should be picked up automagically by the rest of PJMEDIA framework. 
     294First of all, read the [/pjmedia/docs/html/group__PJMEDIA__CODEC.htm Codec Framework] documentation. Then, the easiest is to take other codec source file in {{{pjmedia-codec}}} directory (such as [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c gsm.c]), and replace GSM specific function calls with the functions that are provided by your codec library. 
     295 
     296Once it's finished, you should end up with just two public APIs exported by the codec: the initialization function, and the deinitialization function. 
     297 
     298Then register your codec to PJMEDIA in the application by calling the codec initialization function. After this, the codec should be picked up automagically by the rest of PJMEDIA framework (that is, PJSIP should advertise the codec in outgoing SDP and negotiate it with remote's SDP). 
    182299 
    183300 
    184301=== How can I manipulate audio samples directly? === #audio-man 
    185302 
    186 In PJMEDIA, audio frames are sent back and forth between what is called [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__PORT__CONCEPT.htm media port (pjmedia_port)]. So to be able to peek or manipulate audio frames, you need to implement your own media port. 
    187  
    188 Implementing media port should be easy. Basically you just need to implement these: 
    189  1. Create your media port structure. 
    190  1. Fill in the media port information to describe your media port (like, the name, clock rate, bits per sample, etc.). Use [http://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__PORT__INTERFACE.htm#gb3259d2924c7a2243733391f6f8f0a9a pjmedia_port_info_init()] to initialize the port into. 
    191  1. Implement {{{get_frame()}}} callback (of the ''pjmedia_port'') if your media port is a source (that is, your media port feed audio frames to other media ports). 
    192  1. Implement {{{put_frame()}}} callback (of the ''pjmedia_port'') if your media port is a sink (that is, other media ports may feed audio frames to your media port). 
     303In PJMEDIA, audio frames are sent back and forth between what is called [/pjmedia/docs/html/group__PJMEDIA__PORT__CONCEPT.htm media port (pjmedia_port)]. So to be able to peek or manipulate audio frames, we need to implement our own media port. 
     304 
     305Implementing media port should be easy. Basically we just need to implement these: 
     306 1. Create a media port structure, ''deriving'' from {{{pjmedia_port}}} structure: 
     307{{{ 
     308  struct my_media_port 
     309  { 
     310     pjmedia_port    base; 
     311 
     312     // Your data goes here: 
     313     ... 
     314  }; 
     315}}} 
     316 1. Fill in the media port information to describe the media port (like, the name, clock rate, bits per sample, etc.). Use [/pjmedia/docs/html/group__PJMEDIA__PORT__INTERFACE.htm#gb3259d2924c7a2243733391f6f8f0a9a pjmedia_port_info_init()] to initialize the port into. 
     317 1. Implement {{{get_frame()}}} callback (of the ''pjmedia_port'') if the media port is a source (that is, the media port feed audio frames to other media ports). 
     318 1. Implement {{{put_frame()}}} callback (of the ''pjmedia_port'') if the media port is a sink (that is, other media ports may feed audio frames to our media port). 
    193319 1. Implement {{{on_destroy()}}}, if you need to reclaim resources when the media port is destroyed. 
    194320 
     
    196322 
    197323For source only media ports, samples include: 
    198  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjsip-apps/src/samples/playsine.c playsine.c] from the {{{pjsip-apps/samples}}} directory. 
    199  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/mem_player.c mem_player.c] from pjmedia (media port to playback audio from a buffer). 
    200  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/wav_player.c wav_player.c] from pjmedia (media port to playback audio from WAVE file). 
    201  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/tonegen.c tonegen.c] from pjmedia (media port to generate sine waves/DTMF/multi-frequency tones). 
     324 - [/trac/browser/pjproject/trunk/pjsip-apps/src/samples/playsine.c playsine.c] from the {{{pjsip-apps/samples}}} directory. 
     325 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/mem_player.c mem_player.c] from pjmedia (media port to playback audio from a buffer). 
     326 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/wav_player.c wav_player.c] from pjmedia (media port to playback audio from WAVE file). 
     327 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/tonegen.c tonegen.c] from pjmedia (media port to generate sine waves/DTMF/multi-frequency tones). 
    202328 
    203329For sink only media ports, samples include: 
    204  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/mem_capture.c mem_capture.c] from pjmedia (media port to save audio to a buffer). 
    205  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/wav_writer.c wav_writer.c] from pjmedia (media port to save audio to a WAVE file). 
     330 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/mem_capture.c mem_capture.c] from pjmedia (media port to save audio to a buffer). 
     331 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/wav_writer.c wav_writer.c] from pjmedia (media port to save audio to a WAVE file). 
    206332 
    207333For media ports that manipulates audio and provide both sink and source callbacks: 
    208  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/resample_port.c resample_port.c] from pjmedia (to convert sampling rate) 
    209  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/echo_port.c echo_port.c] from pjmedia (the AEC) 
     334 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/resample_port.c resample_port.c] from pjmedia (to convert sampling rate) 
     335 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/echo_port.c echo_port.c] from pjmedia (the AEC) 
    210336 
    211337 
     
    224350 
    225351Have a look at: 
    226  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c transport_udp.c], the normal UDP media transport, and 
    227  - [http://www.pjsip.org/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c transport_ice.c], ICE media transport. 
     352 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c transport_udp.c], the normal UDP media transport, and 
     353 - [/trac/browser/pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c transport_ice.c], ICE media transport. 
    228354 
    229355There, it's quite easy to see where RTP/RTCP packets are received (that is in {{{on_rx_rtp()}}}/{{{on_rx_rtcp()}}} respectively) or sent (in {{{transport_send_rtp()}}}/{{{transport_send_rtcp()}}}). So these are the locations where you should call the decryption and encryption function of SRTP/ZRTP. 
     
    257383=== Does PJSIP support RFC XYZ? === #rfc 
    258384 
    259 The best way is to look at the [http://www.pjsip.org/sip_media_features.htm PJSIP Features] page and see if that particular feature is supported by PJSIP. 
     385The best way is to look at the [/sip_media_features.htm PJSIP Features] page and see if that particular feature is supported by PJSIP. 
    260386 
    261387=== I'm having problem with calling XYZ, please help! === #general-sip 
    262388 
    263 Please report your problem to [http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org PJSIP mailing list]. In order for us to help you, please provide the following information: 
     389Please report the problem to [http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org PJSIP mailing list]. Please provide the following information: 
    264390 1. Please describe in detail what are you trying to accomplish and how do you configure your equipments (for example, do you use proxy? What kind of proxy?). 
    265  1. It would be best to try to reproduce the problem with [http://www.pjsip.org/pjsua.htm pjsua], so that we can also try to reproduce your problem. 
     391 1. It would be best to try to reproduce the problem with [/pjsua.htm pjsua], so that we can also try to reproduce your problem. 
    266392 1. In any case, please provide the complete log file. If you use ''pjsua'', you can configure it to write log file with {{{--log-file}}} option. If you use your own application that is based on ''pjsua-lib'', you can write the log by setting {{{pjsua_logging_config.log_filename}}} field. 
    267393 
     
    269395=== I cannot login/REGISTER to my server. It complains about authentication error. === #authentication 
    270396 
    271 Most likely this is caused by wrong credential in your configuration. The remedy depends on what error was reported by PJSIP. 
    272  
    273 For [http://www.pjsip.org/pjsip/docs/html/group__PJSIP__CORE__ERRNO.htm#ga13bf24296c19bece7c0c9af051f89db PJSIP_ENOCREDENTIAL] error: 
     397Most likely this is caused by wrong credential in the configuration. The remedy depends on what error was reported by PJSIP. 
     398 
     399For [/pjsip/docs/html/group__PJSIP__CORE__ERRNO.htm#ga13bf24296c19bece7c0c9af051f89db PJSIP_ENOCREDENTIAL] error: 
    274400 - This error is caused by the realm specified in the credential doesn't match the realm challenged by the server in the 401/407 response. If you use PJSIP version 0.7-trunk or PJSIP version 0.7.1 or later, you can put wildcard ("*") as the realm to make PJSIP respond to any realms challenged by the server. If you use older PJSIP, you have to match the realm in the credential with the realm in the challenge. The realm normally would be equal to the domain name, but it doesn't have to. Asterisk, for example, always set the realm to "asterisk". 
    275401 
    276 For [http://www.pjsip.org/pjsip/docs/html/group__PJSIP__CORE__ERRNO.htm#ga935d4205ae50ad6f18a4df98b90d2f6 PJSIP_EFAILEDCREDENTIAL] error: 
     402For [/pjsip/docs/html/group__PJSIP__CORE__ERRNO.htm#ga935d4205ae50ad6f18a4df98b90d2f6 PJSIP_EFAILEDCREDENTIAL] error: 
    277403 - If you encounter this error, most likely it was caused by a wrong credential. Check if the username and password combination is correct. 
    278404 
     405=== How can I attach user specific data to a call? === #call-user-data 
     406 
     407It depends on what user specific data means. 
     408 
     409If user data means an application data, normally a pointer to your application data structure, to be associated with a call, which you want to retrieve later, you can attach this application data with one of these: 
     410 - For outgoing calls, specify the pointer in ''user_data'' argument when calling [/pjsip/docs/html/group__PJSUA__LIB__CALL.htm#g502b0a6449cc5f67517b72df6a88c727 pjsua_call_make_call()]. 
     411 - For incoming calls, call [/pjsip/docs/html/group__PJSUA__LIB__CALL.htm#g53b9be88398324d940bf484df371d7d2 pjsua_call_set_user_data()] in {{{on_incoming_call()}}} callback to attach your user data. 
     412 
     413Once application data is attached to a call, you can retrieve it at any time by calling [/pjsip/docs/html/group__PJSUA__LIB__CALL.htm#gfd0bf3368f982021cd9b9d3d1735ab6c pjsua_call_get_user_data()]. 
     414 
     415Now for a different view on the question. 
     416 
     417If by user data you mean to send custom SIP headers in outgoing SIP messages, you can put the custom headers in the [/pjsip/docs/html/structpjsua__msg__data.htm pjsua_msg_data] structure, which you can specify when sending SIP requests (for example, when sending INVITE, IM message, etc.). Here is a snippet on how to put a custom SIP header as ''pjsua_msg_data'': 
     418{{{ 
     419    .. 
     420    pjsua_msg_data msg_data; 
     421    pjsip_generic_string_hdr my_hdr; 
     422    pj_str_t hname = pj_str("My-Header"); 
     423    pj_str_t hvalue = pj_str("This is the content of My-Header"); 
     424 
     425    pjsua_msg_data_init(&msg_data); 
     426    pjsip_generic_string_hdr_init2(&my_hdr, &hname, &hvalue); 
     427    pj_list_push_back(&msg_data.hdr_list, &my_hdr); 
     428 
     429    // Specify the msg_data in pjsua_im_send(), for example 
     430    pjsua_im_send(.., &msg_data, NULL); 
     431}}} 
     432 
     433The above snippet will add "{{{My-Header: This is the content of My-Header}}}" to outgoing IM request. More than one headers can be added to {{{pjsua_msg_data}}}, of course. 
     434 
     435 
    279436=== With ICE enabled, INVITE packet can exceed MTU/1500 bytes. How can I reduce the message size? === #sip-msg-size 
    280437 
    281438Please see ticket #342 for info. Basically there are few settings to configure to make PJSIP sends smaller packet: 
    282  1. Configure PJSIP to send compact form of SIP headers, by setting {{{PJSIP_ENCODE_SHORT_HNAME}}} macro to 1 in your {{{config_site.h}}}. This will reduce SIP message size by approximately 50 bytes. 
     439 1. Configure PJSIP to send compact form of SIP headers, by setting {{{PJSIP_ENCODE_SHORT_HNAME}}} macro to 1 in {{{config_site.h}}}. This will reduce SIP message size by approximately 50 bytes. 
    283440 1. Suppress the inclusion of ''Allow'' header in outgoing requests, by setting {{{PJSIP_INCLUDE_ALLOW_HDR_IN_DLG}}} macro to 0 in {{{config_site.h}}}. This will reduce SIP message size by approximately 86 bytes. 
    284441 1. Suppress the inclusion of SDP {{{rtpmap}}} attribute for static payload types, by setting {{{PJMEDIA_ADD_RTPMAP_FOR_STATIC_PT}}} macro to 0 in {{{config_site.h}}}. Note that this setting should not cause bad effects for communication, since SDP {{{rtpmap}}} attributes for static payload types are optional. This will reduce SIP message size by approximately 65 bytes. 
    285442 1. Disable RTCP (advertisement) in SDP, by setting {{{PJMEDIA_ADVERTISE_RTCP}}} macro to 0 in {{{config_site.h}}}. When RTCP is disabled, no RTCP packets will be sent or received, and this will cause some RTCP TX statistics (including RTT report) to be unavailable. Other RTCP statistics such as RX statistics, as well as number of TX packets, will still be available since these values are generated locally. Disabling RTCP will reduce SIP message size by approximately 235 bytes for ICE with three candidates. 
    286  1. Last resort, disable some unused network interfaces in your system to reduce the number of ICE candidates advertised in SDP. On Windows for example, it's quite common to have some Loopback network interface, and disabling it doesn't seem to cause (too much) harm. 
     443 1. Last resort, disable some unused network interfaces in the system to reduce the number of ICE candidates advertised in SDP. On Windows for example, it's quite common to have some Loopback network interface, and disabling it doesn't seem to cause (too much) harm. 
    287444 
    288445 
    289446=== How can I instantiate multiple PJSIP stacks in my application? === #multi-stack 
    290447 
    291 You don't need to! This may be necessary with other SIP stacks, but PJSIP inherently supports multiple identities (or accounts) throughout the libraries, so one instance of the stack can be used to perform multiple, separate registration and invite sessions. 
     448You don't need to. This may be necessary with other SIP stacks, but PJSIP inherently supports multiple identities (or accounts) throughout the libraries, so one instance of the stack can be used to perform multiple, separate registration and invite sessions. 
    292449 
    293450---- 
     
    298455 
    299456There are few configuration settings to tweak to reduce the CPU usage of the application or to produce the best performance out of pjsip: 
    300  1. '''Echo canceller'''. The software AEC probably is the most CPU intensive module in PJSIP. To reduce the CPU usage, you can shorten the EC tail length to lower value (the {{{pjsua_media_config.ec_tail_len}}} setting), or you can even disable it altogether by setting {{{pjsua_media_config.ec_tail_len}}} to zero. 
    301  1. '''Codec'''. Use low complexity codec such as ''pcmu'' or ''pcma''. When you use ''pcmu'' or ''pcma'', make sure pjmedia chooses the table based implementation, by setting {{{PJMEDIA_HAS_ALAW_ULAW_TABLE}}} macro to 1 (the default is normally enabled, but it may worth double-checking). 
    302  1. '''Avoid resampling'''. Resampling is a CPU intensive process, thus you should avoid it if you can, by choosing uniform clock rate for all media components (sound device, conference bridge, codecs, WAV files, etc.). 
     457 1. '''Echo canceller'''. The software AEC probably is the most CPU intensive module in PJSIP. To reduce the CPU usage, shorten the EC tail length to lower value (the {{{pjsua_media_config.ec_tail_len}}} setting), or even disable it altogether by setting {{{pjsua_media_config.ec_tail_len}}} to zero. 
     458 1. '''Codec'''. Use low complexity codec such as ''pcmu'' or ''pcma''. When using ''pcmu'' or ''pcma'', make sure pjmedia chooses the table based implementation, by setting {{{PJMEDIA_HAS_ALAW_ULAW_TABLE}}} macro to 1 (the default is normally enabled, but it may worth double-checking). 
     459 1. '''Avoid resampling'''. Resampling is a CPU intensive process, thus it should be avoided if you can, by choosing uniform clock rate for all media components (sound device, conference bridge, codecs, WAV files, etc.). 
    303460 1. '''Logging'''. The default logging level is 5, which provides verbose information just in case some debugging is needed. When absolute performance is needed, you can decrease the logging verbosity level to 3 so that only vital information is displayed. This can be done by, either at compile time by setting {{{PJ_LOG_MAX_LEVEL}}} macro (in {{{config_site.h}}} as usual), or at run-time by calling {{{pj_log_set_level()}}}. 
    304  1. '''Threads'''. Use the optimum number of worker threads in your application. The optimum number would be equal to the number of processors (or processor cores) in the system. 
    305  1. '''Run-time checks'''. All the libraries are equipped with run-time checks to prevent bad parameters from crashing the software. You can disable this feature by setting {{{PJ_ENABLE_EXTRA_CHECK}}} to zero. 
    306  1. '''Stack checks'''. PJLIB is equipped with stack overflow detection. You can disable this feature by setting {{{PJ_OS_HAS_CHECK_STACK}}} to zero. 
    307  1. '''Safe module'''. PJSIP is equipped with mutex protection to protect PJSIP modules from being unregistered while they are still being accessed by PJSIP. If you don't plan to add/remove modules dynamically during run-time, you can disable this protection by setting {{{PJSIP_SAFE_MODULE}}} to zero. 
    308  1. '''Unescape in place'''. By default, PJSIP will make a copy of escaped message sequence before unescaping it. You can configure PJSIP to unescape in place by setting {{{PJSIP_UNESCAPE_IN_PLACE}}} to one. 
     461 1. '''Threads'''. Use the optimum number of SIP worker threads in the application. The optimum number would be equal to the number of processors (or processor cores) in the system. 
     462 1. '''Run-time checks'''. All the libraries are equipped with run-time checks to prevent bad parameters from crashing the software. This feature can be disabled by setting {{{PJ_ENABLE_EXTRA_CHECK}}} to zero. 
     463 1. '''Stack checks'''. PJLIB is equipped with stack overflow detection. This feature can be disabled by setting {{{PJ_OS_HAS_CHECK_STACK}}} to zero. 
     464 1. '''Safe module'''. PJSIP is equipped with mutex protection to protect PJSIP modules from being unregistered while they are still being accessed by PJSIP. If the application doesn't add/remove modules dynamically during run-time, you can disable this protection by setting {{{PJSIP_SAFE_MODULE}}} to zero. 
     465 1. '''Unescape in place'''. By default, PJSIP will make a copy of escaped message sequence before unescaping it. You can configure PJSIP to unescape in place by setting {{{PJSIP_UNESCAPE_IN_PLACE}}} to one. Note that unescaping in place will modify the original message, so don't do this if the application needs to access the original message after it has been parsed (pjsip does not need this access). 
    309466 1. '''Hash tolower optimization'''. By setting {{{PJ_HASH_USE_OWN_TOLOWER}}} to one, the hash function will convert the key to lower case and calculate the hash value in one loop. 
    310467 1. '''Release mode'''. Don't forget to set the appropriate compiler optimization flag, and disable assertion with '''-DNDEBUG'''. 
     
    315472There are few settings to tweak: 
    316473 1. First apply the CPU reduction techniques above to maximize the performance. 
    317  1. By default, PJSIP is configured to handle only 16384 simultaneous SIP transactions and dialogs. You should enlarge this to your requirement, by setting both {{{PJSIP_MAX_TSX_COUNT}}} and {{{PJSIP_MAX_DIALOG_COUNT}}} to the appropriate values (for example, 640*1024-1). 
    318  1. If you plan to support large number of TCP/TLS connections, then increase {{{PJ_IOQUEUE_MAX_HANDLES}}} to some large number (the default is only 64). 
     474 1. Do not use PJSUA-LIB, for now. Please see the issues with using PJSUA-LIB to serve large number of calls [#pjsua-lib-perf below]. 
     475 1. By default, PJSIP is configured to handle only 16384 simultaneous SIP transactions and dialogs. This should be enlargeed according to the requirement, by setting both {{{PJSIP_MAX_TSX_COUNT}}} and {{{PJSIP_MAX_DIALOG_COUNT}}} to the appropriate values (for example, 640*1024-1). 
     476 1. If large number of TCP/TLS connections are needed, increase {{{PJ_IOQUEUE_MAX_HANDLES}}} to some large number (the default is only 64). 
     477 
     478=== I try to use PJSUA-LIB to develop a server like application, but performance is poor === #pjsua-lib-perf 
     479 
     480That is quite expected, unfortunately. PJSUA-LIB was initially aimed to build user agent client applications, so we didn't design it to handle large number of calls. 
     481 
     482The main reason why scalability is bad with PJSUA-LIB is because it uses single conference bridge to terminate all media (calls, WAV files, tone generators, etc.). A conference bridge runs strictly on one thread, which can be the sound device thread (the so called sound device ''clock'') or just a thread if no sound device is initialized. Because of this single thread restriction, it's quite easy to understand why PJSUA-LIB does not scale very well. 
     483 
     484We are currently looking for other design possibilities to make PJSUA-LIB scale better (suggestions are welcome!). In the meantime, perhaps you can use this approach to make the application scale better. 
     485 
     486Basically 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. 
     487 
     488Some steps to accomplish this are as follow: 
     489 1. First thing we should do is to stop the PJSUA-LIB's conference bridge. This can be accomplished by calling [/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. 
     490 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 [/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. 
     491 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. 
     492 1. Since we're not using the main bridge anymore, the call's slot number in {{{pjsua_call_info.conf_slot}}} should not be used anymore. 
     493 1. Now that the main bridge has been stopped, we can manage the media ourselves. We can create one conference bridge for each call, and attach it to a master port to make it ''run'': 
     494{{{ 
     495struct call_data 
     496{ 
     497  pj_pool_t           *pool; 
     498  pjmedia_conf        *conf; 
     499  pjmedia_port        *cport; 
     500  pjmedia_port        *null; 
     501  pjmedia_master_port *m; 
     502  int                  call_slot; 
     503}; 
     504 
     505static void call_media_init(pjsua_call_id call_id) 
     506{ 
     507   pj_pool_t *pool; 
     508   struct call_data *cd; 
     509   pj_status_t status; 
     510 
     511   pool = pjsua_pool_create("mycall", 1000, 1000); 
     512   cd = PJ_POOL_ZALLOC_T(pool, struct call_data); 
     513   cd->pool = pool; 
     514 
     515   pjsua_call_set_user_data(call_id, (void*)cd); 
     516 
     517   status = pjmedia_conf_create(pool, ..., PJMEDIA_CONF_NO_DEVICE, &cd->conf); 
     518   cd->cport = pjmedia_conf_get_master_port(cd->conf); 
     519   status = pjmedia_null_port_create(pool, ..., &cd->null); 
     520   status = pjmedia_master_port_create(pool, cd->null, cd->cport, 0, &cd->m); 
     521   status = pjmedia_master_port_start(cd->m); 
     522} 
     523}}} 
     524 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: 
     525{{{ 
     526#include <pjsua-lib/pjsua_internal.h> 
     527 
     528.. 
     529  pjsua_call *call = &pjsua_var.calls[call_id]; 
     530  pjmedia_port *stream; 
     531 
     532  pjmedia_session_get_port(call->session, 0, &stream); 
     533  pjmedia_conf_add_port(cd->conf, cd->pool, stream, NULL, &cd->call_slot); 
     534}}} 
     535 1. Add other media ports to the conference bridge as necessary. 
     536 1. Since we're allocating resources for the call, don't forget to release these resources once the call is disconnected: 
     537{{{ 
     538static void call_media_deinit(pjsua_call_id call_id) 
     539{ 
     540  struct call_data *cd; 
     541 
     542  cd = (struct call_data*) pjsua_call_get_user_data(call_id); 
     543  if (!cd) 
     544     return; 
     545 
     546  pjmedia_master_port_stop(cd->m); 
     547  pjmedia_master_port_destroy(cd->m, PJ_FALSE); 
     548 
     549  pjmedia_conf_destroy(cd->conf); 
     550  pjmedia_port_destroy(cd->null); 
     551 
     552  ... 
     553 
     554  pjsua_call_set_user_data(call_id, NULL); 
     555} 
     556 
     557static void on_call_state(pjsua_call_id call_id, pjsip_event *e) 
     558{ 
     559   pjsua_call_info call_info; 
     560 
     561   pjsua_call_get_info(call_id, &call_info); 
     562 
     563   if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) { 
     564      call_media_deinit(call_id); 
     565   } 
     566} 
     567}}} 
     568 
     569As mentioned earlier, we are currently looking for alternative design to arrange the media for better scalability, so if you have more ideas, they're most welcome! 
    319570 
    320571---- 
     
    437688=== How can I use PJSIP in .NET applications? === #activex 
    438689 
    439 For this, you will need to have ActiveX wrapper for PJSIP. Unfortunately, at this point we don't provide ActiveX projects for PJSIP, but you can use one of the following projects: 
    440  
    441  - [http://sipekphone2.googlepages.com/ Sipek Phone project], by created Sasa Coh, is a project to build a SIP softphone using .NET, and it has an PJSIP ActiveX wrapper as part of the project. 
     690For this, you will need to have ActiveX wrapper for PJSIP. Unfortunately, at this point we don't provide ActiveX projects for PJSIP, but you can use one from this project: 
     691 
     692 - [http://sipekphone2.googlepages.com/ Sipek Phone project], created by Sasa Coh, is a project to build a SIP softphone using .NET, and it has an PJSIP ActiveX wrapper as part of the project. 
    442693 
    443694 
     
    448699=== How can I build PJSIP for WinCE/Windows Mobile? === #wm-build 
    449700 
    450 Have a look at this [http://www.pjsip.org/using.htm#evc Getting Started | Windows Mobile] page. 
     701Have a look at this [/using.htm#evc Getting Started | Windows Mobile] page. 
    451702 
    452703 
     
    457708=== How can I build PJSIP for Linux/uC-Linux? === #linux-build 
    458709 
    459 Have a look at this [http://www.pjsip.org/using.htm#gnu Getting Started | GNU] page. 
     710Have a look at this [/using.htm#gnu Getting Started | GNU] page. 
    460711 
    461712---- 
     
    465716=== How can I build PJSIP for MacOS X? === #osx-build 
    466717 
    467 Have a look at this [http://www.pjsip.org/using.htm#gnu Getting Started | GNU] page. 
     718Have a look at this [/using.htm#gnu Getting Started | GNU] page. 
    468719 
    469720---- 
     
    473724=== How can I build PJSIP for Symbian? === #symbian-build 
    474725 
    475 We have provided a thorough instructions at the [http://www.pjsip.org/sip_symbian.htm PJSIP for Symbian] page. 
    476  
    477 ---- 
    478  
    479 == Python == 
     726We have provided a thorough instructions at the [/sip_symbian.htm PJSIP for Symbian] page, please check it out. 
     727 
     728---- 
     729 
     730== Miscellaneous == 
    480731 
    481732=== How can I use PJSIP in Python? === #python 
    482733 
    483 Start at this small [wiki:Python_SIP_Tutorial PJSIP Python Tutorial] page. 
    484  
    485  
    486  
     734Start with this small [wiki:Python_SIP_Tutorial PJSIP Python Tutorial] page. It's not a comprehensive tutorial by any means, but hope that can give you a start. 
     735 
     736=== How can I use PJSIP in TCL? === #tcl 
     737 
     738Antonio F. Cano Damas and Mats Bengtsson have contributed TCL binding for PJSIP, please have a look in the [/contrib.htm PJSIP Contribution] page. 
     739