zoukankan      html  css  js  c++  java
  • 获取海康威视实时流用平台支持的RTMP推流组件libEasyRTMP向服务器推流数据的处理方法

    背景分析

    RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写,该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMP/RTMPS/RTMPE等多种变种。RTMP是一种设计用来进行实时数据通信的网络下ieyi,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。RTMP推流,就是将直播内容推送到服务器的过程。

    EasyRTMP是结合了多种音视频缓存及网络技术的一个rtmp直播推流端,包括:圆形缓冲区(circular buffer)、智能丢帧、自动重连、rtmp协议等等多种技术,能够非常有效地适应各种平台(Windows、Linux、ARM、Android、iOS),各种网络环境(有线、wifi、4G),以及各种情况下的直播恢复(服务器重启、网络重启、硬件设备重启)。

    获取海康威视实时流用libEasyRTMP向服务器推流数据处理

    1、根据SDK接入方式先进行设备登录

    NET_DVR_Login_V30(DeviceIP,m_nLoginPort,cUserName,cPassword,&devInfo)
    

    2、启动实时预览

    NET_DVR_RealPlay_V40(m_lUserID[nI],&struPlayInfo,fRealDataCallBack, this)
    

    3、在fRealDataCallBack回调函数中处理视频流数据(包括复合流和音视频分开的视频流数据),类型定义为NET_DVR_STREAMDATA。

    详细处理过程:
    判断回调数据类型(NET_DVR_STREAMDATA ——> 海康PS数据Demux成音视频ES数据(GetH246FromPS) ——> 对关键帧数据做缓存和处理(bIsKeyFrame ) ——> 进入转推RTMP缓存队列(WriteH264DataToChace)
    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;
    					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;
    					}
    					m_mFrameCacheLenth[lRealHandle] = 0;
    				}
    			}
    		}
    	}
    
    //从PS流中取H264数据
    //返回值:是否为数据包 
    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缓存队列
    //H264数据写入写文件缓存队列
    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;
    }
    

     

  • 相关阅读:
    case when then else end
    spark读文件写入mysql(scala版本)
    mysql语句
    spark读文件写mysql(java版)
    spark的广播变量
    hive,把一个表中计算好的数据,存到另一个外部表中
    spark操作hive方式(scala)
    spark sql启动优化
    hive on spark (spark2.0.0 hive2.3.3)
    hive优化,开启压缩功能
  • 原文地址:https://www.cnblogs.com/TSINGSEE/p/11970835.html
Copyright © 2011-2022 走看看