Hi,
I need to be able to stream an audio conference to a web page. The call is audio only and the web page only plays back the call without the listener participating in the call. I am using HMP 3.0 for Windows
Currently I have non-secure version up and running where I am using ipm_StartMedia() from the IP Media API to stream the conference to a port, while the VLC web plugin for Firefox to plays back the audio from the RTP url.
Server side:
IPM_MEDIA_INFO mediaInfo;
int mediaCount = 0;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTP_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.unPortId = port;
strncpy_s(mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.cIPAddress, ipAddress.c_str(), IP_ADDR_SIZE);
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTCP_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.unPortId = port + 1;
strncpy_s(mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.cIPAddress, ipAddress.c_str(), IP_ADDR_SIZE);
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_REMOTE_CODER_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_30;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unFramesPerPkt = 1;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_DISABLE;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unCoderPayloadType = 0;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unRedPayloadType = 0;
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_LOCAL_CODER_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_30;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unFramesPerPkt = 1;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_DISABLE;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unCoderPayloadType = 0;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unRedPayloadType = 0;
mediaInfo.unCount = mediaCount + 1;
eIPM_DATA_DIRECTION direction = DATA_IP_SENDONLY;
const unsigned short mode = EV_SYNC;
if (ipm_StartMedia(ipm, &mediaInfo, direction, mode) == 0) ...
In the browser:
<embed type="application/x-vlc-plugin" pluginspage="http://www.videolan.org" name="vlc" id="vlc" controls="false" height="0"/>
<script type="text/javascript">
function playStream(ipAddress, port) {
var vlc = document.getElementById("vlc");
vlc.playlist.add("rtp://" + ipAddress + ":" + port);
vlc.playlist.play();
}
</script>
This works, but I want to have security (encryption, etc) and better cross browser support.
WebRTC seems to fit the bill. Both it and the Dialogic API support DTLS-SRTP (although the Dialogic API documentation makes no direct reference to the DTLS functionality anywhere I could find).
I know to add SRTP and DTLS on the server side goes a bit like this:
IPM_MEDIA_INFO mediaInfo;
char masterKey[30];
char masterSaltKey[30];
char masterBase64Key[40];
unsigned char *remoteDtlsFingerprint = ...;
IPM_SRTP_PARMS srtpParameters;
IPM_SECURITY_KEY securityKey[2];
IPM_SECURITY_BINARY_KEY securityBinaryKey;
IPM_SECURITY_BASE64_KEY securityBase64Key;
memset(&mediaInfo, 0, sizeof(IPM_MEDIA_INFO));
INIT_IPM_SRTP_PARMS(&srtpParameters);
INIT_IPM_SECURITY_KEY(securityKey);
INIT_IPM_SECURITY_KEY(securityKey+1);
INIT_IPM_SECURITY_BINARY_KEY(&securityBinaryKey);
INIT_IPM_SECURITY_BASE64_KEY(&securityBase64Key);
securityBinaryKey.pcMasterKey = masterKey;
securityBinaryKey.pcMasterSaltKey = masterSaltKey;
securityBase64Key.pcMasterBase64Key = masterBase64Key;
securityKey[0].eKeyType = IPM_SECURITY_KEYTYPE_BINARY;
securityKey[0].pvMasterKey = &securityBinaryKey;
securityKey[1].eKeyType = IPM_SECURITY_KEYTYPE_BASE64;
securityKey[1].pvMasterKey = &securityBase64Key;
if (ipm_SecurityGenMasterKeys(ipm, securityKey, 1, EV_SYNC) == -1)
{
// error
}
int mediaCount = 0;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTP_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.unPortId = port;
strncpy_s(mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.cIPAddress, ipAddress.c_str(), IP_ADDR_SIZE);
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_AUDIO_REMOTE_RTCP_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.unPortId = port + 1;
strncpy_s(mediaInfo.MediaData[mediaCount].mediaInfo.PortInfo.cIPAddress, ipAddress.c_str(), IP_ADDR_SIZE);
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_REMOTE_CODER_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_30;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unFramesPerPkt = 1;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_DISABLE;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unCoderPayloadType = 0;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unRedPayloadType = 0;
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_LOCAL_CODER_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eCoderType = CODER_TYPE_G711ULAW64K;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eFrameSize = CODER_FRAMESIZE_30;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unFramesPerPkt = 1;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.eVadEnable = CODER_VAD_DISABLE;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unCoderPayloadType = 0;
mediaInfo.MediaData[mediaCount].mediaInfo.CoderInfo.unRedPayloadType = 0;
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_AUDIO_REMOTE_SECURITY_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.unVersion = IPM_SECURITY_INFO_VERSION;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.unNumKeys = 1;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.pParms = &srtpParameters;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.pKeys = &securityKey[0];
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.eInfoMode = IPM_SECURITY_INFO_MODE_IMMEDIATE;
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_AUDIO_LOCAL_SECURITY_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.unVersion = IPM_SECURITY_INFO_VERSION;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.unNumKeys = 1;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.pParms = &srtpParameters;
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.pKeys = &securityKey[1];
mediaInfo.MediaData[mediaCount].mediaInfo.SecurityInfo.eInfoMode = IPM_SECURITY_INFO_MODE_IMMEDIATE;
++mediaCount;
mediaInfo.MediaData[mediaCount].eMediaType = MEDIATYPE_DTLS_SRTP_INFO;
mediaInfo.MediaData[mediaCount].mediaInfo.DtlsSrtpInfo.unVersion = IPM_DTLS_SRTP_INFO_VERSION;
mediaInfo.MediaData[mediaCount].mediaInfo.DtlsSrtpInfo.unLocalRole = DTLS_SRTP_ROLE_SERVER;
mediaInfo.MediaData[mediaCount].mediaInfo.DtlsSrtpInfo.pRemoteFingerprint = remoteDtlsFingerprint;
mediaInfo.unCount = mediaCount + 1;
eIPM_DATA_DIRECTION direction = DATA_IP_TDM_BIDIRECTIONAL;
const unsigned short mode = EV_SYNC;
if (ipm_StartMedia(ipm, &mediaInfo, direction, mode) == 0) ...
but I am still unsure how the client side would look.
My research is giving me the impression that getting this to work will require a lot of work on the server side to support WebRTC.
So wondered if anyone here can suggest any Dialogic examples that interact with a WebRTC client?
Or can anyone suggest a better/easier way to implement secure streaming to the browser?
Thanks!