live555项目里面有个sip client模块,一直不知道他是用来干什么的,也始终没有搞明白live555把这个代码加进来干什么,实在想不出来他的应用场景;做音视频通话?做会议?做播放器?事实上,他啥都做不了,真的要做这些应用我估计只有傻子才会用live555来做sip协议栈吧!唯一可能的应用场景就是视频监控的gb28181客户端,但是里面的代码并不支持gb28181,再说老外好似也不清楚我们大天朝的国标吧!好吧,我暂且认为,这是live555团队的个人嗜好吧!
闲话扯了这么多,那好吧!步入正题。前面的文章,我们使用live555实现了rtsp代理服务器,这个东西在视频监控行业里面,应用比较广泛;但是视频监控里面还有gb28181规范,刚好live555里面也有个简单的sipclient,那我就把它用来实现接入gb28181规范的IPC相机吧!总体上达到:rtsp->sip和rtsp<->rtsp的多协议接入流媒体网关的产品形态;流程如下所示:
live555的sipclient代码写的不敢恭维,感觉思路有些混乱,只能大刀阔斧的改了。
首先扩展一个测试的rtsp url格式:
rtsp://192.168.18.65/streamid/real?ipcurl=sip:32050100001320000001@192.168.18.202:5060
其实这个格式在其他文章里面讲的做rtsp代理也是一样可用的,扩展方式是:
rtsp://192.168.18.65/streamid/real?ipcurl=rtsp:\\192.168.18.202\streamid
实际项目中,是通过streamId到vms上查询到sip:32050100001320000001@192.168.18.202:5060这个地址。
有了地址就可以贴代码了
在rtspServer的describe消息处理函数里面:
session = ProxyServerMediaSession::createNew(envir(),
&fOurServer,
(char *)fClientUrl,//注意这里是sip:gb28181Id@ip:port
urlPreSuffix,
fUsername,
fPassword,
rtpOverMode,
fOurRTSPServer.fVerbosityLevelForProxying);
fOurServer.addServerMediaSession(session);
这个代码前面已经贴过了,这里只是说明处理从这里开始了。
接一下做协议解析:
ProxyServerMediaSession::ProxyServerMediaSession(UsageEnvironment &env, GenericMediaServer *ourMediaServer,
char const *inputStreamURL, char const *streamName,
char const *username, char const *password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer,
MediaTranscodingTable *transcodingTable,
createNewProxyRTSPClientFunc *ourCreateNewProxyRTSPClientFunc,
portNumBits initialPortNum, Boolean multiplexRTCPWithRTP)
: ServerMediaSession(env, streamName, NULL, NULL, False, NULL, True),
describeCompletedFlag(0), fOurMediaServer(ourMediaServer), fClientMediaSession(NULL),
fVerbosityLevel(verbosityLevel),
fPresentationTimeSessionNormalizer(new PresentationTimeSessionNormalizer(envir())),
fCreateNewProxyRTSPClientFunc(ourCreateNewProxyRTSPClientFunc),
fTranscodingTable(transcodingTable),
fInitialPortNum(initialPortNum), fMultiplexRTCPWithRTP(multiplexRTCPWithRTP),
fProxyClients(HashTable::create(STRING_HASH_KEYS)), fOriginalProxyStreamId(NULL),
fProxyRTSPClient(NULL), fProxySIPClient(NULL), fRefereceCheck(NULL), fDuraiton(0)
{
if(inputStreamURL && strstr(inputStreamURL, "sip:")) {
fProxySIPClient = ProxySIPClient::createNew(*this, inputStreamURL, username, password);
} else {
// Open a RTSP connection to the input stream, and send a "DESCRIBE" command.
// We'll use the SDP description in the response to set ourselves up.
fProxyRTSPClient = (*fCreateNewProxyRTSPClientFunc)(*this, inputStreamURL, username, password,
tunnelOverHTTPPortNum,
verbosityLevel > 0 ? verbosityLevel - 1 : verbosityLevel,
socketNumToServer);
/*这里的describe消息放到rtspServer里面发送,并且同步等待其响应, add by xx*/
//ProxyRTSPClient::sendDESCRIBE(fProxyRTSPClient);
}
noteLiveness();
}
实现ProxySIPClient类,参照ProxyRTSPClient实现即可。
ProxySIPClient *ProxySIPClient::createNew(class ProxyServerMediaSession &ourServerMediaSession, char const *url,
char const *username, char const *password, unsigned char desiredAudioRTPPayloadFormat,
char const *mimeSubtype, int verbosityLevel,