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

  1. case NET_DVR_STREAMDATA:
  2. {
  3. BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);
  4. while (!inData)
  5. {
  6. Sleep(10);
  7. inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);
  8. OutputDebugString("PlayM4_InputData failed \n");
  9. }
  10. //PS流数据解析处理
  11. {
  12. int nI = 0;
  13. int nCacheSize = 0;
  14. nI = m_mFrameCacheLenth[lRealHandle];
  15. //直接--提取H264数据
  16. BOOL bVideo = FALSE;
  17. BOOL bPatialData = FALSE;
  18. bPatialData = GetH246FromPS(pBuffer,dwBufSize, &m_pFrameCache[lRealHandle][nI].pCacheBuffer,
  19. m_pFrameCache[lRealHandle][nI].nCacheBufLenth, bVideo);
  20. if (bVideo)
  21. {
  22. if (bPatialData)//部分包数据
  23. {
  24. //缓存数据
  25. m_pFrameCache[lRealHandle][nI].lTimeStamp = clock();
  26. m_mFrameCacheLenth[lRealHandle]++;
  27. }
  28. else//包头
  29. {
  30. int i = 0;
  31. if(m_mFrameCacheLenth[lRealHandle]>0)
  32. {
  33. long lH264DataLenth = m_mFrameCacheLenth[lRealHandle]*MAX_PACK_SIZE;
  34. BYTE* pH264Nal = NULL;
  35. pH264Nal = new BYTE[lH264DataLenth];
  36. memset(pH264Nal, 0x00, lH264DataLenth);
  37. BYTE* pTempBuffer = pH264Nal;
  38. int nTempBufLenth = 0;
  39. //TRACE("m_mFrameCacheLenth==%d\r\n", pDemoDlg->m_mFrameCacheLenth);
  40. // 最大缓存数据个数设为pDemoDlg->m_mFrameCacheLenth,程序会过程中报错,Why? [5/6/2014-13:19:51 Dingshuai]
  41. for (i=0; i</*MAX_FRAME_LENTH*/m_mFrameCacheLenth[lRealHandle]; i++)
  42. {
  43. if(m_pFrameCache[lRealHandle][i].pCacheBuffer!=NULL&&m_pFrameCache[lRealHandle][i].nCacheBufLenth>0)
  44. {
  45. // memcpy(pTempBuffer, m_pFrameCache[i].pCacheBuffer, m_pFrameCache[i].nCacheBufLenth);
  46. // pTempBuffer = pTempBuffer + m_pFrameCache[i].nCacheBufLenth;
  47. memcpy(pH264Nal+nTempBufLenth, m_pFrameCache[lRealHandle][i].pCacheBuffer,
  48. m_pFrameCache[lRealHandle][i].nCacheBufLenth);
  49. nTempBufLenth += m_pFrameCache[lRealHandle][i].nCacheBufLenth;
  50. }
  51. if (m_pFrameCache[lRealHandle][i].pCacheBuffer)
  52. {
  53. delete [](m_pFrameCache[lRealHandle][i].pCacheBuffer);
  54. m_pFrameCache[lRealHandle][i].pCacheBuffer = NULL;
  55. }
  56. m_pFrameCache[lRealHandle][i].nCacheBufLenth = 0;
  57. }
  58. if (m_bRtmpRunning && pH264Nal && nTempBufLenth>0)
  59. {
  60. BOOL bIsKeyFrame = FALSE;
  61. //查找是否为关键帧
  62. if(pH264Nal[4]==0x67)
  63. {
  64. bIsKeyFrame = TRUE;
  65. }
  66. long lTimeStamp = clock();
  67. WriteH264DataToChace(lRealHandle, pH264Nal, nTempBufLenth, bIsKeyFrame, lTimeStamp);
  68. }
  69. if (pH264Nal)
  70. {
  71. delete []pH264Nal;
  72. pH264Nal = NULL;
  73. }
  74. // 缓存数据个数 清0
  75. m_mFrameCacheLenth[lRealHandle] = 0;
  76. }
  77. }
  78. }
  79. }
  80. }

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

海康PS流解析:

  1. BOOL CDecCallBack_DemoDlg::GetH246FromPS(IN BYTE* pBuffer, IN int nBufLenth, BYTE** pH264, int& nH264Lenth, BOOL& bVideo)
  2. {
  3. if (!pBuffer || nBufLenth<=0)
  4. {
  5. return FALSE;
  6. }
  7. BYTE* pH264Buffer = NULL;
  8. int nHerderLen = 0;
  9. if( pBuffer
  10. && pBuffer[0]==0x00
  11. && pBuffer[1]==0x00
  12. && pBuffer[2]==0x01
  13. && pBuffer[3]==0xE0)//E==视频数据(此处E0标识为视频)
  14. {
  15. bVideo = TRUE;
  16. nHerderLen = 9 + (int)pBuffer[8];//9个为固定的数据包头长度,pBuffer[8]为填充头部分的长度
  17. pH264Buffer = pBuffer+nHerderLen;
  18. if (*pH264 == NULL)
  19. {
  20. *pH264 = new BYTE[nBufLenth];
  21. }
  22. if (*pH264&&pH264Buffer&&(nBufLenth-nHerderLen)>0)
  23. {
  24. memcpy(*pH264, pH264Buffer, (nBufLenth-nHerderLen));
  25. }
  26. nH264Lenth = nBufLenth-nHerderLen;
  27. return TRUE;
  28. }
  29. else if(pBuffer
  30. && pBuffer[0]==0x00
  31. && pBuffer[1]==0x00
  32. && pBuffer[2]==0x01
  33. && pBuffer[3]==0xC0) //C==音频数据
  34. {
  35. *pH264 = NULL;
  36. nH264Lenth = 0;
  37. bVideo = FALSE;
  38. }
  39. else if(pBuffer
  40. && pBuffer[0]==0x00
  41. && pBuffer[1]==0x00
  42. && pBuffer[2]==0x01
  43. && pBuffer[3]==0xBA)//视频流数据包 包头
  44. {
  45. bVideo = TRUE;
  46. *pH264 = NULL;
  47. nH264Lenth = 0;
  48. return FALSE;
  49. }
  50. return FALSE;
  51. }

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

  1. int CDecCallBack_DemoDlg::WriteH264DataToChace(int nDevId, BYTE* pBuffer, int nBufSize, BOOL bIsKeyFrame, long lTimeStamp)
  2. {
  3. if (!pBuffer || nBufSize<=0 || lTimeStamp<0)
  4. {
  5. return -1;
  6. }
  7. BOOL bKeyFrame = bIsKeyFrame;
  8. int nDeviceType = nDevId+1;
  9. if (m_RtmpHandle && m_bRtmpRunning)
  10. {
  11. //H264推送RTMP
  12. EASY_AV_Frame avFrame;
  13. memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
  14. avFrame.pBuffer = (unsigned char*)pBuffer;
  15. avFrame.u32AVFrameLen = nBufSize;
  16. avFrame.u32VFrameType = (bKeyFrame)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;
  17. avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;
  18. avFrame.u32TimestampSec = lTimeStamp/1000000;
  19. avFrame.u32TimestampUsec = (lTimeStamp%1000000);
  20. //EnterCriticalSection(&m_cs);
  21. EasyRTMP_SendPacket(m_RtmpHandle, &avFrame);
  22. }
  23. return 1;
  24. }

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

本文中所述详细代码见:https://github.com/EasyDSS/EasyRTMP/tree/master/EasyRTMP_HIK

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

  1. 海康威视摄像机Java SDK拉流(二)开启关闭实时预览

    本篇介绍海康威视摄像机通过SDK开启关闭实时预览接口 下篇介绍实时预览的回调函数及解码库 测试环境: 系统:Centos 7 SDK:设备网络SDK Linux64 实时预览模块流程: 图中虚线框部分 ...

  2. iOS - 创建可以在 InterfaceBuilder 中实时预览的自定义控件

    一.需求实现一个前后带图标的输入框 这是一个简单的自定义控件,很容易想到自定义一个视图(UIView),然后前后的图标使用 UIImageView 或者 UIButton 显示,中间放一个 UITex ...

  3. Sublime写MarkDown实时预览

    [TOC] Sublime写MarkDown实时预览 Sublime作为神器,实至名归. 首先 1.安装Sublime,并安装Package Control,这里不多说. 2.安装MarkDown P ...

  4. Sublime、Webstorm等在APICloud平台上全面支持WiFi真机同步和实时预览功能

    APICloud工具插件包括APICloud Studio.Sublime Text和Webstorm全面为开发者提供iOS和Android平台真机同步调试功能,不仅可以通过USB方式进行APP真机同 ...

  5. MWeb 1.4 新功能介绍一:引入文件夹到 MWeb 中管理,支持 Octpress、Jekyll 等静态博客拖拽插入图片和实时预览

    之前在 MWeb 中打开非文档库中的 Markdown 文档,如果文档中有引用到本机图片,是没办法在 MWeb 中显示出来和预览的.这是因为 Apple 规定在 Mac App Store(MAS) ...

  6. TypeWonder – 在任何网站上实时预览字体效果

    TypeWonder 让网页字体的选择过程变得轻松愉快.它可以帮助您在任何网站上快速测试 Web 字体效果!输入网站网址,就能够即时预览的字体的实际效果,还可以从数百种字体中进行挑选,您还可以得到所需 ...

  7. APICloud全面支持WiFi真机同步和实时预览功能

    APICloud工具插件包括APICloud Studio.Sublime Text和Webstorm全面为开发者提供iOS和Android平台真机同步调试功能,不仅可以通过USB方式进行APP真机同 ...

  8. 新增WiFi真机同步与实时预览功能 简化真机调试步骤

    APICloud工具插件为开发者提供iOS和Android平台真机同步调试功能,不仅可以通过USB方式进行APP真机同步功能,更新增WiFi真机同步和WiFi真机实时预览两大功能,方便开发者在开发过程 ...

  9. UI实时预览最佳实践(转)

    UI实时预览最佳实践 概要:Android中实时预览UI和编写UI的各种技巧.本文的例子都可以在结尾处的示例代码中看到并下载.如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以 ...

随机推荐

  1. Mysql 的使用方法

    一 .Mysql 优势: 1.程序稳定性 :这样任意一台服务所在的机器崩溃了都不会影响数据和另外的服务. 2.数据一致性 :所有的数据都存储在一起,所有的程序操作的数据都是统一的,就不会出现数据不一致 ...

  2. TPC-H简介

    TPC-H是事务处理性能委员会( Transaction ProcessingPerformance Council )制定的基准程序之一,TPC- H 主要目的是评价特定查询的决策支持能力,该基准模 ...

  3. MongoDB 查看集合的统计信息

    和 RDBMS 一样, MongoDB 同样存储集合的统计信息,通过调用命令 db.collection.stats() 可以方便的查看集合的统计信息. --1 查看集合 things 的统计信息 r ...

  4. 【angularJS】学习笔记

    一.一个html中多个ng-app //对于ng-app初始化一个AngularJS程序属性的使用需要注意,在一个页面中AngularJS自动加载第一个ng-app,其他ng-app会忽略 //如果需 ...

  5. cube.js 学习(七)cube.js type 以及format 说明

      cube.js 对于measure以及dimension 提供了丰富的数据类型,基本满足我们常见应用的开发,同时对于不同类型也提供了 格式化的操作 measure类型 number 格式 purc ...

  6. Flower(规律+逆向思维)

    Flower: 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6486 题解: 逆向思维+规律 因为每次剪n-1,所以逆向就是控制n-1朵不变,每次增高1 ...

  7. Windows下Apache配置多域名项目

    <VirtualHost www.a.com:80> DocumentRoot "C:\object\a\web" ServerName http://www.a.co ...

  8. Spring MVC国际化配置

    Spring MVC国际化配置 前言 项目开发中要考虑支持国际化,框架选用的是Spring MVC框架,那么问题来了Spring MVC如何配置并实现国际化. 实现过程(Maven项目) 对于Spri ...

  9. 在应用中显示的图片很多情况不满足业务需求,我们需要动态根据图片的宽高进行缩放或加载中显示的缺省图片,这是我没就需要监听图片加载完成回调,来看看微信小程序怎么实现图片加载完成回调。

    <swiper-item> <image src="{{item.image}}" class="slide-image" mode=&quo ...

  10. cnetos7--zabbix(3.4)-server安装

    1.安装前准备 (1)关闭防火墙 [root@localhost ~]#Systemctl stop firewalld.service (2)开机关闭防火墙 [root@localhost ~]#S ...