分类: C/C++
2008-04-23 21:55:09
用微软的实时通信API集成丰富的客户端通信
翻译:
Duane Burton
Sr. Technical Marketing Engineer
Intel Corporation
Jim Huang
Sr. Technical Marketing Engineer
Intel Corporation
2002 年 6 月
应用于:Microsoft Windows? XP
原文出处:
摘要
学习如何创建或集成实时通信(RTC)应用编程接口(API)的基本知识以实现音视频会议、应用程序共享、白板、简单的点对点聊天和音视频调节向导。RTC
API 提供了卓越的基于PC的通信革新,这可应用于所有基于 Microsoft Windows XP的应用程序。
源代码下载 .
目录
微软的实时通信(RTC)应用编程接口(API)提供了卓越的基于PC的通信革新——即时消息、音视频会议和应用程序共享/协作,这可应用于所有基于 Microsoft
Windows XP 的应用程序。
使用RTC的API来进行通信是一个非常简单的过程。

图一、音视频会议例子界面
本文描述了怎样为一个应用程序添加 PC-to-PC 的 RTC 基本能力;我们假定你对使用COM对象开发Windows应用程序已经很熟悉。本文所讨论的源代码可在本文开始所给出的连接里获得。我们以后将会讨论PC-to-Phone、
出席和XML配置。
例子代码展示了使用实时通信API实现音视频会议、应用程序共享、白板、简单的点对点聊天和音视频调节向导的基本要素。其他RTC
支持但本文没有讨论的特征有回波抵消(AEC)、前向错误校验(FEC)、
带宽估计、动态抖动缓冲管理、自动增益控制(AGC)和服务质量(QC)控制算法。在《Microsoft
Windows 实时通信(RTC)客户端的媒体支持》中描述了上述特征。
所需头文件:
rtccore.h
你的应用程序需要通过 CoCreateInstance()来获得RTC接口,CLSID_RTCClient(GUID = {7a42ea29-a2b7-40c4-b091-f6f024aa89be})作为参数。一旦获得了接口,用Initialize()来初始化COM对象,以确定该平台的通信能力。
// Initialize the RTC COM object
hr = CoCreateInstance (CLSID_RTCClient, NULL,
CLSCTX_INPROC_SERVER, IID_IRTCClient,
(LPVOID *)&m_pClient);
// Initialize the client interface
hr = m_pClient->Initialize();
m_pClient->SetPreferredMediaTypes ( RTCMT_ALL, VARIANT_TRUE );
会议参与者的平台性能和可用带宽决定了使用哪一种codec。
| CODEC | Sampling Rate (kHz) | Bit Rate (Kbps) | Frame Size (msec) |
|---|---|---|---|
| G.711 | 8 | 64 | 20 |
| G.722.1 | 16 | 24 | 20 |
| G.723 | 8 | 6.4 | 30, 60, or 90 |
| GSM | 8 | 13 | 20 |
| DVI4 | 8 | 32 | 20 |
| SIREN | 16 | 16 | 20, or 40 |


// Set the event filter to listen for RTC events
// Using RTCEF_ALL will listen for all events
// For the sample application, we will demonstrate how to set the
// event listener for a limited set of events.
long lEventMask = RTCEF_SESSION_STATE_CHANGE |
RTCEF_MESSAGING |
RTCEF_MEDIA |
RTCEF_INTENSITY |
RTCEF_CLIENT;
hr = m_pClient->put_EventFilter( lEventMask );
// Create the event sink object
m_pEvents = new CRTCEvents;
// initialize the event handler
hr = m_pEvents->Advise( m_pClient, m_hWnd );
// Set the listen mode for RTC client
// RTCLM_BOTH opens the standard SIP port 5060, as well as
// a dynamic port.
hr = m_pClient->put_ListenForIncomingSessions(RTCLM_BOTH);
音视频的媒体类型可在会话过程中添加或删除,因此客户端必须能监听这些类型的事件。在"处理实时流会话事件"这一节中可获得关于状态改变和事件处理的更多信息。
OnRTCEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
// Based on the RTC_EVENT type, query for the
// appropriate event interface and call a helper
// method to handle the event
switch ( wParam )
{
...
case RTCE_MEDIA:
{
IRTCMediaEvent * pEvent = NULL;
hr = pDisp->QueryInterface( IID_IRTCMediaEvent,
(void **)&pEvent );
if (SUCCEEDED(hr))
{
OnRTCMediaEvent(pEvent);
SAFE_RELEASE(pEvent);
}
}
break;
...
}
HRESULT CAVDConfDlg::MakeCall(RTC_SESSION_TYPE enType, BSTR bstrURI)
{
...
// Create the session
IRTCSession * pSession = NULL;
hr = m_pClient->CreateSession(enType, NULL, NULL, 0, &pSession);
// Add the participant to the session
hr = pSession->AddParticipant(bstrURI, NULL, &m_Participant);
...
return S_OK;
}
void CAVDConfDlg::OnRTCMediaEvent(IRTCMediaEvent *pEvent)
{
...
hr = pEvent->get_MediaType(&lMediaType);
hr = pEvent->get_EventType(&enType);
hr = pEvent->get_EventReason(&enReason);
if ((m_AVDlg) && (m_AVDlg.GetState () != RTCSS_IDLE))
{
// Deliver the media state to the session window
m_AVDlg.DeliverMedia(lMediaType, enType, enReason);
}
}
音量事件void CAVDConfDlg::OnRTCIntensityEvent(IRTCIntensityEvent *pEvent)
{
...
hr = pEvent->get_Direction(&enDevice);
hr = pEvent->get_Level(&lLevel);
hr = pEvent->get_Min(&lMin);
hr = pEvent->get_Max(&lMax);
if (m_AVDlg.GetState () != RTCSS_IDLE)
{
// Deliver the intensity state to the session window
m_AVDlg.DeliverIntensity(enDevice, lLevel);
}
}
即时消息事件HRESULT CAVDConfDlg::OnRTCMessagingEvent(IRTCMessagingEvent *pEvent)
{
...
hr = pEvent->get_Session(&pSession);
hr = pEvent->get_EventType(&enType);
hr = pEvent->get_Participant(&pParticipant);
if (enType == RTCMSET_MESSAGE)
{
hr = pEvent->get_MessageHeader(&bstrContentType);
hr = pEvent->get_Message(&bstrMessage);
// Deliver the message to the session window
if (m_cMessageDlg)
m_cMessageDlg.DeliverMessage(pParticipant, bstrContentType,
bstrMessage);
}
else if (enType == RTCMSET_STATUS)
{
hr = pEvent->get_UserStatus(&enStatus);
// Deliver the user status to the session window
m_cMessageDlg.DeliverUserStatus(pParticipant, enStatus);
}
return S_OK;
}
会话状态改变事件Void CAVDConfDlg::OnRTCSessionStateChangeEvent(IRTCSessionStateChangeEvent *pEvent)
{
...
hr = pEvent->get_State(&enState);
hr = pEvent->get_Session(&pSession);
switch ( enState )
{
case RTCSS_INCOMING:
{
...
// This event is called when an incoming call occurs
RTC_SESSION_TYPE enType;
hr = pSession->get_Type(&enType);
// Ring the bell
m_pClient->PlayRing(RTCRT_PHONE, VARIANT_TRUE);
// Accept the session
hr = pSession->Answer();
}
}
...
}
应用程序共享:hr = m_pClient->StartT120Applet ( RTCTA_APPSHARING );
白板支持:
在应用程序中支持白板,需要调用 StartT120Applet 方法,使用 RTCTA_WHITEBOARD 枚举作为参数。
hr = m_pClient->StartT120Applet ( RTCTA_WHITEBOARD );
要关闭一个会话,所有正在运行T120的应用程序必须被关闭。然后RTC 客户端接口调用ShutDown()并完成关闭会话的过程。
使用RTC进行通信需要处理器具有适当的性能。下列例子中,一个1 GHz的Pentium? III处理器和一个2.2 GHz的Pentium
4处理器用于确定当使用RTC特征时处理器的利用率。下表描述了使用本文介绍的RTC特征时处理器的利用率。
| 任务 | P4 处理器 at 2.2-GHz (% CPU 占用率n)1 | P III 处理器 at 1.0-GHz (% CPU 占用率)2 |
|---|---|---|
| 仅音/视频会议 | 9% | 22% |
| 添加程序共享(共享IE浏览器) | 10% | 35% |
| 增加白板 | 12% | 37% |
| 增加即时消息 | 12% | 37% |
通过使用实时通信客户端API,在 Windows
XP 下开发通信工具已变得相当简单。开发者可迅速设计、配置和开发他们的应用程序。现有的音视频会议应用程序可通过添加 RTC 丰富的通信特征而获益。使用 RTC
API 进行开发的程序也可以从一个统一的通信协议中获益。这提高了你的程序与其它文本消息和音视频会议程序互相合作的能力。将 RTC
API 与 Intel 的处理器以及 Microsoft Windows XP 相结合,从而向最终用户传达一种创新的通信体验。