What’s new in Real time Communication (RTC) 1.5?


Updates to RTC APIs on CE, has been prolonged for some time and there has been many updates to it and thus a blog to cover some high level overview of changes in RTC 1.5:


RTC Overview


RTC is mainly used for real time communication mechanisms like IM, Voice over IP and other real time sharing applications. RTC internally uses standard IETF RFC based protocols like SIP, SDP, RTP, RTCP, etc.


RTC 1.5 Changes


RTC APIs & Session Initiation Protocol (SIP) changes


In addition to service & features of RTC 1.3 of Window Client RTC API set, there has been several interface additions to RTC 1.5, for services like:


1.      Subscription/Notification


2.      Privacy


3.      Support for PRACK in SIP and support for early media scenarios because of that.


4.      Symmetric UDP support on SIP for NAT traversal.


5.      Port manager API extensions for NAT traversal, for transactions like Registration and IM, which were not supported before. Port manager is also supported for new transactions like Subscribe/Notify


6.      Enhanced SIP interoperability


 


Using Subscription/Notification API, one can implement Message waiting Indication and other subscription based services. MWI is available as a service with the public VOIP app available in Yamazaki.


Using Privacy API, OEM and user can implement and achieve telephony kind of privacy like blocking ID and more.


With PRACK or Provisional acknowledgement support, early media scenarios like announcements or special ring tones, before the call gets connected can be enabled.


RTC 1.5 now supports SIP on Symmetric UDP. This helps NAT traversal, especially when dealing with border gateway controllers. There have been enhancements to Port Manager APIs of RTC as well to enable NAT traversal.


 


RTC Media Stack changes


Internally, there is a completely new media stack. The new media stack has following audio related features for VOIP:



  1. Audio Healing – Smooth playback (like packet loss concealment, jitter control, etc)

  2. Silence Suppression.

  3. Voice Activity Detection

  4. Comfort Noise Generation

  5. Automatic Gain Control to avoid clipping and when sound is too low.

  6. Soft Mute functionality

  7. Support for built-in and pluggable codecs

  8. DTMF Events (OOB and InBand)

 


The new media stack has silence suppression logic and voice activity detection built-in to avoid unnecessary traffic on the network for prolonged silence periods. These features are registry configurable.


The new media stack uses a special audio healing algorithm to compensate for network related issues like packet losses, jitter, comfort noise generation on the audio receiver end, etc.


 


The pluggable audio architecture is the same as I CE RTC 1.2 . An ACM compatible audio codec can be plugged in  to the RTC media stack. We have added registry keys to let user choose whether internal audio healing should be used with pluggable codecs or not. This is because some advanced codec may have their own healing mechanism or the healing might be done in hardware or some other mechanism and hence the user may choose to disable the internal audio healer per pluggable codec.


 


RTC Media stack supports sending & receiving of in-band and out of band( OOB) DTMFs. The duration & time gap between in-band DTMF packets are controllable through registries to match the resolution of media gateways for in-band DTMF tone detection. RTC media stack also supports playback of tones, for received OOB  DTMF events. The playback can be disabled using a registry if desired.


The Media stack also supports basic NAT traversal techniques by sending & receiving RTP/RTCP packets over symmetric UDP. This means that it sends & receives RTP packet using a single source port, and same for RTCP. This helps traversing any type of NAT, if a media gateway is present in between the caller & the callee, which is a normal scenario for most of the VOIP service providers these days.


The media stack also sends “early” UDP packets using RTP/RTCP source port, as soon as the remote address/port is learnt. This helps in “punching” holes through the NAT, which enables receiving of media from outside the NAT, thus enabling early media kind of scenarios.

Comments (19)

  1. Annapureddy Thirupathaiah says:

    Hi,

    Are there any standard ACM interfaces to enable dynamic bit rate adaptation? For ex: AMR-NB supports 8 bit rate modes. Based on the network conditions bit rate mode can be changed on the fly. Do you enable this feature in RTC 1.5?

    Is there any way at the wave driver level to know whether there is a VoIP call started or not? In case of Cicuit switched (CS) base band calls, there are two ways to know this

    – RIL driver automatically informs the wave driver or

    – wave driver subscribe to the RIL notifications like any other application.

    But i do not see any way at the wave driver level to know about VoIP call started or not?

    What is the bitstream format exchanged between RTC and ACM codec? In other words, are the bit stream data buffers frame aligned or contain variable amount of frames (ex: 1, 1.5, 2 frames in  a single buffer)?

    If we disable internal (RTC) audio healing, what is the format of the data exchanged between RTC and ACM codec? i.e. do you pass the RTP packets or just speech frames?

    Thanks in advance

    Thiru

  2. cenet says:

    Are there any standard ACM interfaces to enable dynamic bit rate adaptation?

    <<RAJESH>> ACM is defined on MSDN. Though not specifcally designed for adaptable bit rate, I think it can be used for AMR as there are user defined fields that can be passed to codec driver.

    For ex: AMR-NB supports 8 bit rate modes. Based on the network conditions bit rate mode can be changed on the fly. Do you enable this feature in RTC 1.5?

    <<RAJESH>>  No we do not fully support AMR kind of pluggable codec, which may expect network condtions or info from remote AMR decoder to be fed to the encoder function.

    Is there any way at the wave driver level to know whether there is a VoIP call started or not? In case of Cicuit switched (CS) base band calls, there are two ways to know this

    • RIL driver automatically informs the wave driver or
    • wave driver subscribe to the RIL notifications like any other application.

    But i do not see any way at the wave driver level to know about VoIP call started or not?

    <<Rajesh>> WaveXXXSetProperty can be used to inform the wave driver of the VOIP mode, if the wave driver supports such a property for VOIP.

    What is the bitstream format exchanged between RTC and ACM codec? In other words, are the bit stream data buffers frame aligned or contain variable amount of frames (ex: 1, 1.5, 2 frames in  a single buffer)?

    <<Rajesh>>RTC always feeds a single frame buffer.

    If we disable internal (RTC) audio healing, what is the format of the data exchanged between RTC and ACM codec? i.e. do you pass the RTP packets or just speech frames?

    <Rajesh>>RTC always passes & retrives single frame buffers to/from the ACM codec.

  3. Annapureddy Thirupathaiah says:

    Thanks for your answers.

    Regarding Dynamic Bit Rate Adaptation, as a codec developer i can define and implement an ACMDM_XXX message to set the bit rate dynamically. What is important here is interoperability and usability. For ex: If we define ACMDM_SET_BITRATE and implement it, the clients such as RTC 1.5 of ACM Codec should be able to use this ACMDM_XXX message.  If they (clients) do not use it, then there is no use of implementing it. More over the message needs to be standadized for interoperability.

    WaveXXXSetProperty can be used to inform the wave driver of the VoIP mode. But WaveXXXSetProperty takes property set, property id and the relevant params as input. What is the property set id and property id to be implemented at wave driver level to be informed of VoIP mode?

    During media negoitation using SDP, it is quite possible to negotiate the RTP Packetization interval i.e. whether a single RTP packet contains a single frame or 2 frames or multiple frames. Generally for conversational services, it is single frame to reduce the overall latency. To be generic, it should be possible to indicate the ACM codec, wave driver about the packetization interval instead of hardcoding/assuming it to be single frame. Depending upon packetization interval, wave driver can adjust the DMA buffer size and hence DMA interrupt interval. This can increase the overall system response.

  4. Michael says:

    When can we download this new API?  I cannot find a release date or a download location.

  5. cenet says:

    Regarding Dynamic Bit Rate Adaptation, as a codec developer i can define and implement an ACMDM_XXX message to set the bit rate dynamically. What is important here is interoperability and usability. For ex: If we define ACMDM_SET_BITRATE and implement it, the clients such as RTC 1.5 of ACM Codec should be able to use this ACMDM_XXX message.  If they (clients) do not use it, then there is no use of implementing it. More over the message needs to be standadized for interoperability.

    <<RAJESH>> Agreed. As I said before, currently this is not supported by RTC.

    WaveXXXSetProperty can be used to inform the wave driver of the VoIP mode. But WaveXXXSetProperty takes property set, property id and the relevant params as input. What is the property set id and property id to be implemented at wave driver level to be informed of VoIP mode?

    <<Rajesh>> This is dependent on the driver. I dont believe there is any well defined property for this. I just suggested this mechanism, if you have some control on the driver code. Currently, RTC does not do anything to let driver know of VOIP mode.

    During media negoitation using SDP, it is quite possible to negotiate the RTP Packetization interval i.e. whether a single RTP packet contains a single frame or 2 frames or multiple frames. Generally for conversational services, it is single frame to reduce the overall latency. To be generic, it should be possible to indicate the ACM codec, wave driver about the packetization interval instead of hardcoding/assuming it to be single frame. Depending upon packetization interval, wave driver can adjust the DMA buffer size and hence DMA interrupt interval. This can increase the overall system response.

    <<RAJESH>> RTC’s pluggable codec interface supports frame duration reg key. Depending on how much this is set, RTC will take care of giving the right size of buffer to the ACM codec.

  6. cenet says:

    When can we download this new API?  I cannot find a release date or a download location.

    <<RAJESH>> RTC 1.5 is available as a part of Windows Embedded CE 6.0 release. Getting access to Windows Embedded CE 6.0 should give you access to RTC 1.5 as well.

  7. Srikanth Nori says:

    Hi,

    I’m looking for a way to change the source port from which SIP messages originate. How do I set the source port for SIP sessions initiated by the local UA?

    I’m able to set the listen address using IRTCClientPortManagement::StartListenAddressAndPort. RTC is able to listen When a remote user connects to this UA on this port, and responses are sent from that port.

    But this does not change the address for messages generated in sessions initiated by this UA. e.g. If I send the first INVITE, it goes out from the default port.

    I also tried Initializing the IRTCClient2 with RTCIF_ENABLE_SYMMETRIC_UDP_SIGNALING ,along with setting the port using IRTCClientPortManagement::StartListenAddressAndPort, but it did not help.

    Any pointers on what I can do to set the source port?

  8. Andy says:

    Can RTC1.5 send NOTIFY? Reception is fine, how about sending?

  9. cenet says:

    Can RTC1.5 send NOTIFY? Reception is fine, how about sending?

    <<Rajesh>> In Windows CE 6.0, RTC 1.5 can only receive Notify messages with the help of subscription APIs

  10. cenet says:

    Hi,

    I’m looking for a way to change the source port from which SIP messages originate. How do I set the source port for SIP sessions initiated by the local UA?

    I’m able to set the listen address using IRTCClientPortManagement::StartListenAddressAndPort. RTC is able to listen When a remote user connects to this UA on this port, and responses are sent from that port.

    But this does not change the address for messages generated in sessions initiated by this UA. e.g. If I send the first INVITE, it goes out from the default port.

    I also tried Initializing the IRTCClient2 with RTCIF_ENABLE_SYMMETRIC_UDP_SIGNALING ,along with setting the port using IRTCClientPortManagement::StartListenAddressAndPort, but it did not help.

    Any pointers on what I can do to set the source port?

    <<Rajesh>> One way to do this would be to initialize symmetric UDP signaling (as you are doing) and use port manager APIs to specify the local address/src port info. Agreed, It’s not the best way to to this, but you will achieve what you want to.

  11. Hi says:

    How about supporting for Push to Talkwith RTC 1.3/1.5? I’m looking for a way to control Talk-burst. It need to S/R TBCP bundle as RTCP method. Refer to SDK help, looks there is no any way to send RTCP bundle customed. So do I need to do this by other way what co-working with RTC?

    Thanks!

     

    <<Rajesh>> RTC does not provide APIs control or customize RTP/RTCP streams. However, you can use RTC for SIP signaling and use a 3rd party media stack with RTC for your scenario.

  12. I’m trying to send instant messages from an application using RTC on WinCE to

    Windows Messenger (5.1). Both are registered to a central server (MS

    LCS 2005)

    My sequence of calls is this

    1) IRTCClient_CreateSession of type RTCST_IM

    2) Register with LCS (IRTCClientProvisioning_GetProfile followed by

    IRTCClientProvisioning_EnableProfile)

    3) IRTCSession_AddParticipant (with the URI of windows messenger)

    4) IRTCSession_SendMessage (“text/plain”, “message1”, 42) (42 is the

    cookie value)

    5) IRTCSession_SendMessage (“text/plain”, “message2”, 43)

    6) IRTCSession_SendMessage (“text/plain”, “message3”, 44)..

    and so on.

    What I see is that the first message gets posted, and WM receives it

    succesfully (I get a RTCE_SESSION_STATE_CHANGE indicating

    RTCSS_CONNECTED with a session type of RTCST_IM. Then I get

    RTCE_SESSION_OPERATION_COMPLETE after the (4)th call in the list

    above).

    On the second message I get no events. Nothing happens at all. I also

    see no messages being generated (since there are no packets going out

    over the network interface). The SendMessage call doesn’t indicate any

    error either.

    Any ideas what could be happening?

     

    <<Rajesh>> Try using session type: RTCST_MULTIPARTY_IM and see if that resolves the issue.

  13. kings says:

    hi there

    any body knows to implement portmanager using rtc client

     

    <Rajesh>> Check Prathap’s blog:

    http://blogs.msdn.com/cenet/archive/2006/11/10/real-time-communications-rtc-1-5-port-manager.aspx

     

  14. divya.varadarajan says:

    We’re using RTC on WinCE 1.5 to develop a SIP application, and we’re trying to change the SIP port on which we send and receive messages.

     

    <<Rajesh>> You meant WinCE 5.1, right?

    To start receiving:

    IRTCClient2_put_ListenForIncomingSessions(RTCLM_DYNAMIC)

    <<Rajesh>> This alone should work, though it will not let you control which dynamic port RTC will use.

    IRTCClientPortManagement_StartListenAddressAndPort(CPM, local_ip_bstr, sip_port);

    <<Rajesh>> This should also work provided the port# falls in the min/max port range of RTC (Default values are listed on MSDN – on reg key settings page)

    These calls succeed, but RTC is unable to listen on the new port. It continues to listen on 5060!

    <<Rajesh>> Do you mean you continue to see 5060 listed in your REGISTER message? 

     

    We also tried to do

    IRTCClient2_put_AllowedPorts(RTCTR_UDP,  RTCLM_DYNAMIC);

    IRTCClientPortManagement_StartListenAddressAndPort(CPM, local_ip_bstr, sip_port);

    This didn’t work either.

    In case it matters, we are able to change the “from” port using the PortManager3 interface on Sessions that we create.

  15. divya.varadarajan says:

    We’re using RTC 1.5 on WinCE and it is not able to receive SIP INFO messages generated by 3rd party softphones. RTC responds with a 500 Server Internal Error SIP message, and no event is generated for the local device to handle.

    However, we’re able to send INFO messages succesfully.

    Do we need to do anything special to allow RTC to receive INFO messages succesfully?

     

    <<Rajesh>> Have you enabled the RTCE_INFO event in RTC?

  16. <<Rajesh>> Try using session type: RTCST_MULTIPARTY_IM and see if that resolves the issue.

    Rajesh, thanks  a lot. This solved the problem.

  17. I tried to run an application that uses RTC 1.5 on WinCE 6.0 through Application Verifier to remove any memory leaks in the application. Application Verifier reports many unfreed heap allocations inside RTC calls during initialization of RTC.

    This is the code that I’m using to initialize. This function runs as a thread (which loops forever at the message pump till it gets a message requesting it to shut down).

    void init_wince_sip_lib(LPVOID param)

    {

       IRTCClient *irtc_client;

       HRESULT    status;

       /* Event notification Vars */

       int                    EventCookie;

       IConnectionPointContainer *CPC       = NULL;

       IConnectionPoint          *CP        = NULL;

       IRTCEventNotification     *Notif;

       /* Initialize COM */

       CoInitializeEx(NULL, COINIT_MULTITHREADED);

       /* Create instance of RTC Client */

       CoCreateInstance(&CLSID_RTCClient,         /* RTC Clients ID   */

                                 NULL,                     /* Not aggregate    */

                                 CLSCTX_INPROC_SERVER,     /* Only valid value */

                                 &IID_IRTCClient,          /* Interface ID     */

                                 (void **)&irtc_client);   /* Return pointer   */

       IRTCClient_QueryInterface

                   (irtc_client,               /* Base pointer   */

                   &IID_IRTCClient2,           /* Interface ID   */

                   (LPVOID )&g_rtc_client2); / Return pointer */

       IRTCClient_Release(irtc_client);

       IRTCClient2_InitializeEx(g_rtc_client2,

                                         RTCIF_DISABLE_MEDIA |

                                         RTCIF_ENABLE_SYMMETRIC_UDP_SIGNALING |

                                         RTCIF_PREFER_STATIC_PORT_FOR_SYMMETRIC_UDP);

       IRTCClient_QueryInterface(g_rtc_client2,

                                          &IID_IConnectionPointContainer,

                                          (void**) (&CPC));

       IConnectionPointContainer_FindConnectionPoint(

                    CPC,

                    &IID_IRTCEventNotification,

                    &CP);

       IConnectionPointContainer_Release(CPC);

       /* Initialize the event notification – this is a custom function we use to create an event handler*/

       IRTCEventNotification_Initialize(&g_RTCEvents);

       /* Get the notification interface */

       IRTCEventNotification_QueryInterface(g_RTCEvents,

                                                     &IID_IRTCEventNotification,

                                                     (void **)&Notif);

       /* Call the Advise method to give RTC the IUnknown pointer for the event */

       IConnectionPoint_Advise(CP,

                                        (IUnknown *)Notif,

                                        &EventCookie);

       IConnectionPoint_Release(CP);

       IRTCEventNotification_Release(Notif);

       /* Filter to receive ALL events */

       IRTCClient_put_EventFilter(g_rtc_client2, RTCEF_ALL);

       /* Start listening */

       IRTCClient2_put_ListenForIncomingSessions(g_rtc_client2,

                                                          RTCLM_BOTH);

       /* Message pump */

       while(1)

       {

          MSG msg;

          GetMessage(&msg, NULL, 0, 0);

          if(WM_APP == msg.message)

          {

              break;

          }

          TranslateMessage(&msg);

          DispatchMessage(&msg);

       }

       printf("CoUninitializing init_wince_sip_libn");

       CoUninitialize();

       printf("done init wince sip libn");

    }

    At the end of the application, I do IRTCClient2_PrepareForShutdown(g_rtc_client2), IRTCClient2_Shutdown(g_rtc_client2) and IRTCClient2_Release(g_rtc_client2) (from another thread). The Event notification interfaces are also freed up cleanly.

    App verifier reports about 15kilobytes of unfreed heap allocations in this thread alone…

    Is there something I can do to make these unfreed allocations go away?

  18. divya.varadarajan says:

    Thanks for replying

    We’re using RTC 1.5 on WinCE to develop a SIP application

    Yes all the RTC events have been enabled using

    IRTCClient::put_EventFilter(RTCEF_ALL).

    I am still unable to detect any incoming RTCE_INFO event.

    Is there any other RTC API that needs to be called to enable RTCE_INFO event?

     

    <<Rajesh>> Sorry, for the late reply. What is the content type/sub-type that you are using for the INFO packet? It may be colliding with certain internal type/sub-type that RTC uses and may find it invalid.

  19. Hi Rajesh,

    Some progress on the memory leaks issue: I’ve used CoRegisterMallocSpy to check up on the allocations that RTC does for each operation. (I have disabled BSTR caching)

    I’m creating a session by calling IRTCClient2_CreateSessionWithDescription, followed by IRTCSession2_AddParticipant.

    By examining the IMallocSpy calls I see that RTC makes three allocations in AddParticipant. One of them is freed immediately, leaving two unfreed allocs. (I think these correspond to the SDP and content type)

    These two allocs seem to get freed only when I call IRTCClient_Shutdown. This behaviour is repeatable. i.e. if I make 10 calls, all 10*2 allocs get freed only in IRTCClient_Shutdown.

    This causes problems with my application, because it slowly runs out of memory as I keep making calls.

    What should I do to make these two allocations get freed immediately (or when the call is terminated)?

     

    <<Rajesh>> What RTC version are you using and what CE OS is this? Are you using the latest CE 6.0 R2 release? If not, please try that. Thanks.

Skip to main content