GB/T2818視頻流媒體解決方案是基於GB/T28181協議進行模塊化設計、支持分布式部署;具有設備管理模塊、信令模塊、流媒體模塊;支持多個中心信令服務器部署、支持多個流媒體負載均衡;流媒體模塊支持RTSP、RTMP、FLV、HLS多種協議訪問;支持對攝入攝像機的雲台控制;完全滿足全新建設的數字監控網絡和已經部分建設的數字監控兼容部署。
由於GB28181設計的時候基本很少使用tcp包,只有在資源推送和錄像檢索查詢返回的時候才會使用的tcp消息,下面簡單說一下tcp消息使用,首先建立一個tcp短連接,然后將消息發送出去,消息長度盡量在2M以下。
下面粘貼一段sip消息tcp沾包的代碼,希望對您有所幫助。
void CUvSocketTransMgr::sip_tcp_sticky_packet(TUvSocketItem * pSocketItem, const char *pData, int len, const char *pSrcIP, int SrcPort,const char* pDestIP,int DestPort)
{
if(len > 0)
{
char *end_sip = NULL;
char *cl_header = NULL;
int cl_size = 0;
if(pSocketItem->pTcpRecvData != NULL)
{
/* concat old data with new data */
pSocketItem->pTcpRecvData = (char *)realloc(pSocketItem->pTcpRecvData, pSocketItem->nTcpRecvLen+len+1);
if(NULL == pSocketItem->pTcpRecvData)
{
printf("realloc pTcpRecvData failed!\n");
pSocketItem->nTcpRecvLen = 0;
return;
}
strncpy(pSocketItem->pTcpRecvData+pSocketItem->nTcpRecvLen, pData, len);
pSocketItem->pTcpRecvData[pSocketItem->nTcpRecvLen+len] = '\0';
pSocketItem->nTcpRecvLen = pSocketItem->nTcpRecvLen + len;
}
if(NULL == pSocketItem->pTcpRecvData)
{
pSocketItem->pTcpRecvData = (char *)malloc(len+1);
if(pSocketItem->pTcpRecvData != NULL)
{
memset(pSocketItem->pTcpRecvData, 0, len+1);
}
strncpy(pSocketItem->pTcpRecvData, pData, len);
pSocketItem->pTcpRecvData[len] = '\0';
pSocketItem->nTcpRecvLen = len;
}
end_sip = strstr(pSocketItem->pTcpRecvData, "\r\n\r\n");
while(end_sip != NULL)
{
cl_header = mystrcasestr(pSocketItem->pTcpRecvData, "\ncontent-length ");
if (cl_header == NULL || cl_header > end_sip)
cl_header = mystrcasestr(pSocketItem->pTcpRecvData,"\ncontent-length:");
if (cl_header == NULL || cl_header > end_sip)
cl_header =mystrcasestr(pSocketItem->pTcpRecvData,"\r\nl ");
if (cl_header == NULL || cl_header > end_sip)
cl_header =mystrcasestr(pSocketItem->pTcpRecvData,"\r\nl:");
if (cl_header != NULL && cl_header < end_sip)
cl_header = strchr(cl_header, ':');
if (cl_header == NULL || cl_header >= end_sip)
{
/* remove data up to crlfcrlf and restart */
memmove(pSocketItem->pTcpRecvData, end_sip+4,pSocketItem->nTcpRecvLen -(end_sip + 4 -pSocketItem->pTcpRecvData) + 1);
pSocketItem->nTcpRecvLen = pSocketItem->nTcpRecvLen - (end_sip +4 -pSocketItem->pTcpRecvData);
pSocketItem->pTcpRecvData = (char *)realloc(pSocketItem->pTcpRecvData, pSocketItem->nTcpRecvLen+1);
if(pSocketItem->pTcpRecvData == NULL)
{
pSocketItem->nTcpRecvLen = 0;
break;
}
end_sip =strstr(pSocketItem->pTcpRecvData,"\r\n\r\n");
continue; /* and restart from new CRLFCRLF */
}
/* header content-length was found before CRLFCRLF -> all headers are available */
cl_header++; /* after ':' char */
cl_size = atoi(cl_header);
if (cl_size == 0|| (cl_size >0 && (end_sip + 4 + cl_size <=pSocketItem->pTcpRecvData+pSocketItem->nTcpRecvLen)))
{
uv_mutex_lock(&mutex_data_);
RecvPacketCallBack(pSocketItem->socketfd,pSocketItem->pTcpRecvData, (end_sip + 4 + cl_size -pSocketItem->pTcpRecvData),\
pSrcIP,SrcPort,pDestIP,DestPort, true);
uv_mutex_unlock(&mutex_data_);
if (pSocketItem->nTcpRecvLen -(end_sip + 4 + cl_size -pSocketItem->pTcpRecvData) == 0)
{
end_sip = NULL;
pSocketItem->nTcpRecvLen = 0;
free(pSocketItem->pTcpRecvData);
pSocketItem->pTcpRecvData = NULL;
continue;
}
memmove(pSocketItem->pTcpRecvData,end_sip + 4 + cl_size, pSocketItem->nTcpRecvLen -(end_sip + 4 + cl_size -pSocketItem->pTcpRecvData) + 1);
pSocketItem->nTcpRecvLen = pSocketItem->nTcpRecvLen - (end_sip +4 +cl_size -pSocketItem->pTcpRecvData);
pSocketItem->pTcpRecvData = (char *)realloc(pSocketItem->pTcpRecvData,pSocketItem->nTcpRecvLen + 1);
if (pSocketItem->pTcpRecvData == NULL)
{
printf("realloc pSocketItem->pTcpRecvDatapSocketItem->pTcpRecvDatapSocketItem->pTcpRecvData!!\n");
pSocketItem->nTcpRecvLen = 0;
break;
}
end_sip =strstr(pSocketItem->pTcpRecvData,"\r\n\r\n");
continue; /* and restart from new CRLFCRLF */
}
/* uncomplete SIP message */
end_sip = NULL;
}
if (pSocketItem->nTcpRecvLen== 0)
{
/* all data consumed are reallocation error ? */
return;
}
}
else if(len< 0)
{
printf("Could not read socket (%d)- close it\n",pSocketItem->socketfd);
//DelSocketItem(pSocketItem);
//close(pSocketItem->sock);
}
else if (len == 0)
{
printf("End of stream (read 0 byte from %s:%i)\n", pSocketItem->srcip, pSocketItem->srcport);
//DelSocketItem(pSocketItem);
//close(pSocketItem->sock);
}
else
{
printf("Dummy SIP message received (size=%d)\n", len);
}
}
GB/T28181視頻流媒體解決方案播放效果可見下圖: