/********************此文可以被转发,但请转发者保留作者的署名权
****李浩
****msn:lihao_nx@hotmail.com
****
****email:lihaoyxj@gmail.com
****出处:lihaoyxj.cublog.cn
*****************/
例子为5rd中的,而帮助为3rd,有一些接口在3rd帮助中是没有的,而针对RTP传输在SYMBIAN上我也没做过,现在只是整理,待后边验证,如果有什么错再改
假设要连接的相关参数为
远程IP:92.168.0.6
远程端口: 8000
本地端口: 7000
包大小:4096,分析NOKIA的RTP例子
1. 以Udp初始化RhostResolver,并获取与远程地址的一个连接
RHostResolver resolver;
User::LeaveIfError(resolver.Open(iSockServ,KAfInet,KProtocolInetUdp));
CleanupClosePushL(resolver);
TNameEntry entry;
TRequestStatus status;
resolver.GetByName(KDestAddr,entry,status);
User::WaitForRequest(status);
User::LeaveIfError(status.Int());
CleanupStack::PopAndDestroy(1);//close resolver
TSockAddr remote = entry().iAddr;
remote.SetPort(dport);
2. 创建一个本地连接地址
TInetAddr localAddr;
localAddr.SetPort(iLocalPort);
3. 创建一个本地的SOCKET并创建一个RTCP
User::LeaveIfError(iSocket.Open(iSocketServ, KAfInet,KSockDatagram, KProtocolInetUdp));
User::LeaveIfError(iSocket.Bind(localAddr));
localAddr.SetPort(iLocalPort + 1);
User::LeaveIfError(iRtcpSocket.Open(iSocketServ, KAfInet,KSockDatagram, KProtocolInetUdp));
User::LeaveIfError(iRtcpSocket.Bind(localAddr));
4. 本地socket连到到用程,并用rtpsession打开它,同时打开rtcp
TRequestStatus stat;
iSocket.Connect(iDestAddr,stat);
User::WaitForRequest(stat);
User::LeaveIfError(stat.Int());
iDestAddr.SetPort(iDestAddr.Port() + 1);
iRtcpSocket.Connect(iDestAddr,stat);
User::WaitForRequest(stat);
User::LeaveIfError(stat.Int());
iRtpSession.OpenL(iSocket, aPacketSize+12, iRtcpSocket);
5. 后边有一个没查出功能的
iRtpSession.SetRTPTimeConversion(100, 100);
6. 注册RTP回调
iRtpSession.PrivRegisterEventCallbackL(ERtpNewSource, (TRtpCallbackFunction)CRtpFileStreamer::NewSource, this);
在此处注册后就可以处理收到的信息,处理接口如下:
void CRtpFileStreamer::NewSource(CRtpFileStreamer* aPtr, const TRtpEvent& aEvent)
{
if (aPtr->ReceiveSrc().IsOpen())
{
aPtr->ReceiveSrc().Close();
}
TRAPD(err,
aPtr->ReceiveSrc() = aEvent.Session().NewReceiveSourceL();
aPtr->ReceiveSrc().PrivRegisterEventCallbackL(ERtpPacketReceived, (TRtpCallbackFunction)CRtpFileStreamer::PacketArrived, aPtr);)
if (err!=KErrNone)
{
__DEBUGGER();
}
}
/**
A callback method that is called on packet arrival.
*/
void CRtpFileStreamer::PacketArrived(CRtpFileStreamer* aPtr, const TRtpEvent& aEvent)
{
aPtr->iRecvPacket.Close();
aPtr->iRecvPacket = aEvent.ReceiveSource().Packet();
if (aEvent.ReceiveSource().Packet().IsOpen())
{
__DEBUGGER();
}
TRAPD(err,aPtr->HandleReceivedPacketL());
if (err!=KErrNone)
{
__DEBUGGER();
}
}
7. 现在需要创建一个RRtpSendPacket
RRtpSession& iSession;
RRtpSendSource iSendSrc;
RRtpSendPacket iSendPacket;
iSendSrc = iSession.NewSendSourceL();
iSendSrc.SetDefaultPayloadSize(iPacketSize);
iSendSrc.PrivRegisterEventCallbackL(ERtpSendSucceeded, (TRtpCallbackFunction)CRtpFileSender::PacketSent, this);
iSendSrc.PrivRegisterEventCallbackL(ERtpSendFail, (TRtpCallbackFunction)CRtpFileSender::SendError, this);
iSendPacket = iSendSrc.NewSendPacketL();
8. 现在可以通过iSendPacket来进行数据发送了
TInt tmp = iPayloadDesC.Length();
iSendPacket.WritePayload().SetLength(tmp);
iSendPacket.Send();
9. 由于这个是一个读文件并传输的,故内存区域是固定的
iPayloadDesC.Set(const_cast
(iSendPacket.WritePayload().Ptr()),iPacketSize,iPacketSize);
User::LeaveIfError(iFile.Read(iPayloadDesC));
10. 发送结束后的清理工作
iSendPacket.Close();
iSendSrc.Close();
iRtpSession.Close();
iSocket.Close();
iRtcpSocket.Close();
iSockServ.Close();