EasyRTMP:RTMP推流海康威视实时预览回调PS流用EasyRTMP向RTMP服务器推流中视频数据处理的代码

在上一篇方案《EasyRTMP结合海康HCNetSDK获取海康摄像机H.264实时流并转化成为RTMP直播推流(附源码)》中我们介绍了将海康安防摄像机进行互联网直播的整体方案流程,其中有一个“数据处理与分析”流程我们没有详细描述,今天我们将详细介绍一下海康HCNetSDK实时预览回调接口数据处理的过程,尤其是在RealDataCallback中对AVData的处理过程:

  ```
	case NET_DVR_STREAMDATA:
		{
			BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);
			while (!inData)
			{
				Sleep(10);
				inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);
				OutputDebugString("PlayM4_InputData failed \n");	
			}	
			//PS流数据解析处理		
			{
				int nI = 0;
				int nCacheSize = 0;
				nI = m_mFrameCacheLenth[lRealHandle];

				//直接--提取H264数据
				BOOL bVideo = FALSE;
				BOOL bPatialData = FALSE;
				bPatialData = GetH246FromPS(pBuffer,dwBufSize, &m_pFrameCache[lRealHandle][nI].pCacheBuffer, 
					m_pFrameCache[lRealHandle][nI].nCacheBufLenth, bVideo);

				if (bVideo)
				{
					if (bPatialData)//部分包数据
					{
						//缓存数据
						m_pFrameCache[lRealHandle][nI].lTimeStamp = clock();
						m_mFrameCacheLenth[lRealHandle]++;
					} 
					else//包头
					{
						int i = 0;
						if(m_mFrameCacheLenth[lRealHandle]>0)
						{
							long lH264DataLenth = m_mFrameCacheLenth[lRealHandle]*MAX_PACK_SIZE;
							BYTE* pH264Nal =  NULL;
							pH264Nal = new BYTE[lH264DataLenth];
							memset(pH264Nal, 0x00, lH264DataLenth);
							BYTE* pTempBuffer = pH264Nal;
							int nTempBufLenth = 0;

							//TRACE("m_mFrameCacheLenth==%d\r\n", pDemoDlg->m_mFrameCacheLenth);

							// 最大缓存数据个数设为pDemoDlg->m_mFrameCacheLenth,程序会过程中报错,Why? [5/6/2014-13:19:51 Dingshuai]
							for (i=0; i</*MAX_FRAME_LENTH*/m_mFrameCacheLenth[lRealHandle]; i++)
							{
								if(m_pFrameCache[lRealHandle][i].pCacheBuffer!=NULL&&m_pFrameCache[lRealHandle][i].nCacheBufLenth>0)
								{
									// 										memcpy(pTempBuffer, m_pFrameCache[i].pCacheBuffer, m_pFrameCache[i].nCacheBufLenth);
									// 										pTempBuffer = pTempBuffer + m_pFrameCache[i].nCacheBufLenth;

									memcpy(pH264Nal+nTempBufLenth, m_pFrameCache[lRealHandle][i].pCacheBuffer, 
										m_pFrameCache[lRealHandle][i].nCacheBufLenth);
									nTempBufLenth += m_pFrameCache[lRealHandle][i].nCacheBufLenth;
								}
								if (m_pFrameCache[lRealHandle][i].pCacheBuffer)
								{
									delete [](m_pFrameCache[lRealHandle][i].pCacheBuffer);
									m_pFrameCache[lRealHandle][i].pCacheBuffer = NULL;
								}	
								m_pFrameCache[lRealHandle][i].nCacheBufLenth = 0; 
							}

							if (m_bRtmpRunning && pH264Nal && nTempBufLenth>0)
							{
								BOOL bIsKeyFrame = FALSE;
								//查找是否为关键帧
								if(pH264Nal[4]==0x67)
								{
									bIsKeyFrame = TRUE;
								}
								long lTimeStamp = clock();
								WriteH264DataToChace(lRealHandle, pH264Nal, nTempBufLenth, bIsKeyFrame, lTimeStamp);
							}

							if (pH264Nal)
							{
								delete []pH264Nal;
								pH264Nal = NULL;
							}
							// 缓存数据个数 清0
							m_mFrameCacheLenth[lRealHandle] = 0;
						}
					}
				}
			}
		}
```

通过对上述代码的分析,整个视频流回调过程还是比较简单的:判断回调数据类型(NET_DVR_STREAMDATA)–》海康PS流数据Demux成音视频ES流数据(GetH246FromPS)–》对关键帧数据做缓存和处理(bIsKeyFrame )–》进入转推RTMP缓存队列(WriteH264DataToChace)

海康PS流解析:

```
BOOL CDecCallBack_DemoDlg::GetH246FromPS(IN BYTE* pBuffer, IN int nBufLenth, BYTE** pH264, int& nH264Lenth, BOOL& bVideo)
{
if (!pBuffer || nBufLenth<=0)
{
	return FALSE;
}

BYTE* pH264Buffer = NULL;
int nHerderLen = 0;

if( pBuffer
	&& pBuffer[0]==0x00
	&& pBuffer[1]==0x00 
	&& pBuffer[2]==0x01
	&& pBuffer[3]==0xE0)//E==视频数据(此处E0标识为视频)
{
	bVideo = TRUE;
	nHerderLen = 9 + (int)pBuffer[8];//9个为固定的数据包头长度,pBuffer[8]为填充头部分的长度
	pH264Buffer = pBuffer+nHerderLen;
	if (*pH264 == NULL)
	{
		*pH264 = new BYTE[nBufLenth];
	}
	if (*pH264&&pH264Buffer&&(nBufLenth-nHerderLen)>0)
	{	
		memcpy(*pH264, pH264Buffer, (nBufLenth-nHerderLen));
	}	
	nH264Lenth = nBufLenth-nHerderLen;

	return TRUE;
}	
else if(pBuffer 
	&& pBuffer[0]==0x00
	&& pBuffer[1]==0x00
	&& pBuffer[2]==0x01
	&& pBuffer[3]==0xC0) //C==音频数据
{
	*pH264 = NULL;
	nH264Lenth = 0;
	bVideo = FALSE;
}
else if(pBuffer 
	&& pBuffer[0]==0x00
	&& pBuffer[1]==0x00
	&& pBuffer[2]==0x01
	&& pBuffer[3]==0xBA)//视频流数据包 包头
{
	bVideo = TRUE;
	*pH264 = NULL;
	nH264Lenth = 0;
	return FALSE;
}
return FALSE;
}
```

海康音视频数据进行RTMP推流:

```
int CDecCallBack_DemoDlg::WriteH264DataToChace(int nDevId, BYTE* pBuffer, int nBufSize, BOOL bIsKeyFrame, long lTimeStamp)
{
if (!pBuffer || nBufSize<=0 || lTimeStamp<0)
{
	return -1;
}

BOOL bKeyFrame  = bIsKeyFrame;
int nDeviceType = nDevId+1;
if (m_RtmpHandle && m_bRtmpRunning)
{
	//H264推送RTMP
	EASY_AV_Frame	avFrame;
	memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));

	avFrame.pBuffer = (unsigned char*)pBuffer;
	avFrame.u32AVFrameLen = nBufSize;
	avFrame.u32VFrameType = (bKeyFrame)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;
	avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;
	avFrame.u32TimestampSec = lTimeStamp/1000000;
	avFrame.u32TimestampUsec = (lTimeStamp%1000000);

	//EnterCriticalSection(&m_cs);
	EasyRTMP_SendPacket(m_RtmpHandle, &avFrame);	
}

return 1;
}
```

经过上述步骤,基本完成了对一路SDK数据回调的处理,如果需要一个完整的、系统的、中间级别的流转服务,则需要一套完整的控制机制和配套接口以及前端界面,就类似于EasyNVR一样。

EasyNVR方案架构

在这里插入图片描述

方案一
  • 服务器在本地,与IPCamera/NVR/编码器同在一个局域网,拥有一个内网IP地址又具有外网访问地址
  • 多个IPCamera/NVR/编码器仅有内网IP地址(无外网IP),EasyNVR通过内网拉取IPCamera/NVR/编码器的流数据

在这里插入图片描述

方案二
  • 服务器在公网(比如云主机、公网服务器),与设备不在同在一个局域网内
  • IPCamera/NVR/编码器单独或者共有固定的公网IP地址,EasyNVR服务器可以直接访问到设备

在这里插入图片描述

方案三
  • EasyNVS服务器部署在公网(比如云主机、公网服务器)
  • 有多个内网现场的直播设备需要进行公网直播
  • EasyNVR对接EasyNVS可以利用网络实现按需直播,同时屏蔽各种网络环境问题,适用于有线、WIFI、4G、专网
  • 支持云端运维,公网具体运维每个现场EasyNVR设备
  • EasyNVS管理平台能获取到EasyNVR的所有能力,并进行互联网化输出,同时进行统一化的管理和接口输出。

EasyNVR应用场景

EasyNVR可以说已经成为国内视频互联网化基础建设的排头兵,几乎各个民生行业都已经有了EasyNVR视频能力输出的身影,EasyNVR多年服务于各行各业视频基础建设,EasyNVR的可靠性、完整性、稳定性已经受到了业界的广泛认可!

EasyNVR稳定可靠
在这里插入图片描述

雪亮工程

在这里插入图片描述

水利监控

在这里插入图片描述

网络直播

在这里插入图片描述

智慧农业

EasyNVR安防摄像机网页流媒体服务

EasyNVR是一款拥有完整、自主、可控知识产权,同时又能够具备软硬一体功能的安防互联网化流媒体服务器,能够通过简单的网络摄像机通道配置,将传统监控行业里面的高清网络摄像机IP Camera、NVR等具有RTSP、Onvif协议输出的设备接入到EasyNVR,EasyNVR能够将这些视频源的音视频数据进行拉取,转换为RTMP/HLS,进行全平台终端H5直播(Web、Android、iOS),并且EasyNVR能够将视频源的直播数据对接到第三方CDN网络,实现互联网级别的直播分发。详情可访问EasyNVR官网:http://www.easynvr.com

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值