Stream Media API

API Reference


Warning
This interface is experimental and unsupported.

The Stream Media API handles media streaming interfaces with real-time protocols like RTP.

The Real-time Transport Protocol is used to stream audio over IP/Ethernet. It is used to transport any audio stream through an IP or Ethernet network.

The RTP protocol is augmented by a control protocol called Real-Time Transport Control Protocol (RTCP), which provides monitoring capabilities on the data delivery and minimum control functionality.

More information on the protocol can be found in RFC-3550. A description of the RTP/AVP profile, which describes generic audio and video conferences, can be found in RFC-3551.

Note
The RTP interface does not provide the full Audio/Video Profile (AVP) profile : it can only handle a singlecast audio session.

Typically, the RTP interface can be used to redirect an audio call coming from an audio interface through an IP network. For example, an IP audio server (Legato platform) would retrieve audio from any audio interface (e.g. a Modem voice call), and connect it to the RTP interface that sends the data through an IP network. The data would be received by an IP client (PC, smartphone, Legato platform) that is able to decode the audio stream.

AudioOverIP.png

In order to start a RTP session, information on the local and remote IP address are required to set up UDP sockets. The local port corresponds to the UDP socket on which RTP packets will be sent and received, and the remote address and port correspond to the IP address and port on which RTP packets should be sent.

IPC interfaces binding

All the functions of this API are provided by the streamMedia sample service.

Here's a code sample binding to streamMedia service:

bindings:
{
   clientExe.clientComponent.streamMedia -> streamMedia.streamMedia
}

Open/Close an Audio Interface

The following functions let you select the desired interface attributes:

RTP

The streamMedia_OpenAudioRtpRx() and streamMedia_OpenAudioRtpTx() functions allow the application to set up a RTP session.

After opening and connecting a RTP interface, it has to be started using streamMedia_Start().

You can also register a handler function for RTCP packet reception management.

streamMedia_AddRtcpHandler() function installs a handler for RTCP Packet reception.

streamMedia_RemoveRtcpHandler() function removes the RTCP handler function.

The streamMedia_SendRtcpSdes() and streamMedia_SendRtcpBye() functions allow the application to send RTCP Session Description (SDES) or BYE packet.

The RTCP SDES packet can be used to mark the beginning of the RTP session. It is composed of several optional text fields that can provide information about the user's name, email address, etc... See streamMedia_SendRtcpSdes() for more details.

The RTCP BYE packet can be used to mark the end of the RTP session. It is possible to specify the reason. See streamMedia_SendRtcpBye() for more details.

More information on the RTCP SDES and BYE packets can be found in RFC-3550.

Before disconnecting and closing a RTP interface, it has to be stopped using streamMedia_Stop(). Then, after disconnecting the interface from the connector, streamMedia_Close() is called to close it.

Note
The RTP interface requires one more UDP socket in order to send and receive RTCP packets. The RTCP UDP socket port number is automatically set to the local RTP port plus one.

Sample code

The following samples illustrate the case described in the image above. It consists of two different devices that communicate through RTP over an IP network. One device handles a modem voice call, and the other one handles the microphone and speaker.

Warning
The following codes show a basic example of how to transmit audio through RTP between two peers. Quality of service is not provided in those samples. They just show how the streamMedia API should work and how it should be used.

This first sample code is related to the RTP peer that handles the modem voice call.

// Peer 1 : connection between a modem voice call and a RTP session.
 
static void MyCallEventHandler
(
le_mcc_CallRef_t callRef,
le_mcc_Event_t callEvent,
void* contextPtr
)
{
if (callEvent == LE_MCC_EVENT_TERMINATED)
{
le_mcc_TerminationReason_t term = le_mcc_GetTerminationReason(callRef);
le_mcc_Delete(callRef);
DisconnectAllAudio(); // Not showed here, would disconnect all audio.
}
else if (callEvent == LE_MCC_EVENT_INCOMING)
{
le_mcc_Answer(callRef);
}
else
{
LE_INFO("Other Call event.%d", callEvent);
}
}
 
static void MyRtcpEventHandler
(
le_audio_StreamRef_t streamRef,
streamMedia_RtcpEvent_t event,
void* contextPtr
)
{
switch (event)
{
case STREAMMEDIA_RTCP_BYE:
DisconnectAllAudio(); // Not showed here, would disconnect all audio.
break;
default:
LE_INFO("Other event");
break;
}
}
 
void ConnectModemToRtp
(
void
)
{
static le_audio_ConnectorRef_t audioInputConnectorRef = NULL;
static le_audio_ConnectorRef_t audioOutputConnectorRef = NULL;
static le_audio_StreamRef_t rtpInRef = NULL;
static le_audio_StreamRef_t rtpOutRef = NULL;
static le_audio_StreamRef_t mdmRxAudioRef = NULL;
static le_audio_StreamRef_t mdmTxAudioRef = NULL;
static le_mcc_CallRef_t callRef = NULL;
const char* remoteAddress = "10.40.58.2";
const char* destinationNumber = "0123456789";
int localPort = 4000;
int remotePort = 4000;
 
rtpInRef = streamMedia_OpenAudioRtpRx(localPort);
rtpOutRef = streamMedia_OpenAudioRtpTx(localPort, remoteAddress, remotePort);
 
mdmRxAudioRef = le_audio_OpenModemVoiceRx();
mdmTxAudioRef = le_audio_OpenModemVoiceTx();
 
audioInputConnectorRef = le_audio_CreateConnector();
audioOutputConnectorRef = le_audio_CreateConnector();
 
le_audio_Connect(audioOutputConnectorRef, mdmTxAudioRef);
le_audio_Connect(audioInputConnectorRef, mdmRxAudioRef);
 
le_audio_Connect(audioOutputConnectorRef, rtpInRef);
streamMedia_Start(rtpInRef);
 
le_audio_Connect(audioInputConnectorRef, rtpOutRef);
streamMedia_Start(rtpOutRef);
 
streamMedia_AddRtcpHandler(rtpInRef, MyRtcpEventHandler, NULL);
 
le_mcc_AddCallEventHandler(MyCallEventHandler, NULL);
callRef=le_mcc_Create(destinationNumber);
le_mcc_Start(callRef);
}

This sample code shows how to connect RTP to microphone and speaker.

// Peer 2 : connection between a RTP session and microphone and speaker.
 
static void MyRtcpEventHandler
(
le_audio_StreamRef_t streamRef,
streamMedia_RtcpEvent_t event,
void* contextPtr
)
{
switch (event)
{
case STREAMMEDIA_RTCP_BYE:
DisconnectAllAudio(); // Not showed here, would disconnect all audio.
break;
default:
LE_INFO("Other event");
break;
}
}
 
void RecordFileFromRtp
(
void
)
{
static le_audio_ConnectorRef_t audioInputConnectorRef = NULL;
static le_audio_ConnectorRef_t audioOutputConnectorRef = NULL;
static le_audio_StreamRef_t rtpInRef = NULL;
static le_audio_StreamRef_t rtpOutRef = NULL;
static le_audio_StreamRef_t micAudioRef = NULL;
static le_audio_StreamRef_t speakerAudioRef = NULL;
const char* remoteAddress = "10.40.58.2";
int localPort = 4000;
int remotePort = 4000;
 
rtpInRef = streamMedia_OpenAudioRtpRx(localPort);
rtpOutRef = streamMedia_OpenAudioRtpTx(localPort, remoteAddress, remotePort);
 
micAudioRef = le_audio_OpenMic();
speakerAudioRef = le_audio_OpenSpeaker();
 
audioInputConnectorRef = le_audio_CreateConnector();
audioOutputConnectorRef = le_audio_CreateConnector();
 
le_audio_Connect(audioOutputConnectorRef, speakerAudioRef);
le_audio_Connect(audioInputConnectorRef, micAudioRef);
 
le_audio_Connect(audioOutputConnectorRef, rtpInRef);
streamMedia_Start(rtpInRef);
 
le_audio_Connect(audioInputConnectorRef, rtpOutRef);
streamMedia_Start(rtpOutRef);
 
streamMedia_AddRtcpHandler(rtpInRef, MyRtcpEventHandler, NULL);
}

Known limitations

The RTP interface must be connected and disconnected in this specific order :

  • First connect the RTP reception stream, and then the transmission one.
  • When disconnecting it, start by the transmission stream, and then disconnect the reception one.

The streamMedia API provided by the streamMedia sample application is not suitable for real-time communication applications because of the too high latency. A delay of 500 ms has been measured on a one-sided RTP session (RTP transmission only) on a WP85 module. Thus, the "Audio over IP" use case described above shows a latency of more than one second due to the two-sided RTP session (transmission on one module and reception on the other). However, the streamMedia API can be used for any streaming purposes where a delay of one second is acceptable.

The streamMedia application has been tested on WP85 and AR8652.