随笔 - 936  文章 - 0  评论 - 3  阅读 - 30万

实现国标GB/T2818视频流媒体解决方案EasyGBS国标GB28181-2016版的sip协议tcp沾包流程说明介绍

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视频流媒体解决方案播放效果可见下图:

posted on   EasyGBS  阅读(1948)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示