简述

  使用海康摄像头采集图像时,需要在图像上添加图标、文字等额外数据。可选择使用海康SDK绘图回调函数叠加字符、图像等(请参考上一篇文章);也可使用海康SDK的解码回调函数,对视频流数据进行解码后处理。该方法流程为:调用视频预览函数NET_DVR_RealPlay_V40()时将第三个参数设置为实时数据回调函数RealDataCallBack()的函数指针,然后在RealDataCallBack()回调函数中注册视频流数据解码函数DecCallbackFUN(),最后在DecCallbackFUN()函数中对数据解析解码、叠加字符等处理。
  本文只调用解码回调函数将YV12格式视频流数据转换为RGB32格式数据,然后将RGB32格式数据转换为Image,并使用PictrueBox显示该Image数据,暂不做叠加字符、图像等处理。

代码

1、摄像头操作代码
    struct CameraInfo{public string strIP;public short nPort;public string strUserName;public string strPassword;}class IDeviceCamera{public Image m_img = null;public virtual bool InitCamera( CameraInfo stInfo ){return true;}}class DeviceCamera : IDeviceCamera{private CameraInfo m_stCameraInfo;private bool m_bInitSDK = false;private Int32 m_lUserID = -1;private Int32 m_lRealHandle = -1;private Int32 m_lPort = -1;CHCNetSDK.REALDATACALLBACK RealData = null; //必须得定义为成员变量public override bool InitCamera( CameraInfo stInfo ){m_stCameraInfo = stInfo;m_bInitSDK = CHCNetSDK.NET_DVR_Init();if ( !m_bInitSDK ){uint nError = CHCNetSDK.NET_DVR_GetLastError();}CHCNetSDK.NET_DVR_SetConnectTime( 5000, 1 );CHCNetSDK.NET_DVR_SetReconnect( 10000, 1 );if ( m_bInitSDK == false ){MessageBox.Show( "NET_DVR_Init error!" );return false;}else{//保存SDK日志 To save the SDK logCHCNetSDK.NET_DVR_SetLogToFile( 3, "C:\\SdkLog\\", true );}string DVRIPAddress = stInfo.strIP;     //设备IP地址或者域名 Device IPInt16 DVRPortNumber = stInfo.nPort;     //设备服务端口号 Device Portstring DVRUserName = stInfo.strUserName;//设备登录用户名 User name to loginstring DVRPassword = stInfo.strPassword;//设备登录密码 Password to loginCHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();m_lUserID = CHCNetSDK.NET_DVR_Login_V30( DVRIPAddress, DVRPortNumber, DVRUserName, DVRPassword, ref DeviceInfo );if ( m_lUserID < 0 ){MessageBox.Show( "登录失败!" );CHCNetSDK.NET_DVR_Cleanup();return false;}//CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();lpPreviewInfo.hPlayWnd = (IntPtr)null;lpPreviewInfo.lChannel = 1;lpPreviewInfo.dwStreamType = 0;       //码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推lpPreviewInfo.dwLinkMode = 0;         //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP lpPreviewInfo.bBlocked = true;        //0- 非阻塞取流,1- 阻塞取流lpPreviewInfo.dwDisplayBufNum = 15;   //播放库播放缓冲区最大缓冲帧数//使用回调函数取摄像头数据RealData = new CHCNetSDK.REALDATACALLBACK( RealDataCallBack );//预览实时流回调函数IntPtr pUser = new IntPtr();//用户数据m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40( m_lUserID, ref lpPreviewInfo, RealData, pUser );CHCNetSDK.NET_DVR_RigisterDrawFun( m_lRealHandle, new CHCNetSDK.DRAWFUN( cbDrawFun ), 0 );//回调函数:绘制图标return true;}private uint nLastErr = 0;private static PlayCtrl.DECCBFUN m_fDisplayFun = null;private IntPtr m_ptrRealHandle;public void RealDataCallBack( Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser ){//下面数据处理建议使用委托的方式switch ( dwDataType ){case CHCNetSDK.NET_DVR_SYSHEAD:     // sys headif ( dwBufSize > 0 ){if ( m_lPort >= 0 )return; //同一路码流不需要多次调用开流接口//获取播放句柄 Get the port to playif ( !PlayCtrl.PlayM4_GetPort( ref m_lPort ) ){nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );break;}//设置流播放模式 Set the stream mode: real-time stream modeif ( !PlayCtrl.PlayM4_SetStreamOpenMode( m_lPort, PlayCtrl.STREAME_REALTIME ) ){nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );//str = "Set STREAME_REALTIME mode failed, error code= " + nLastErr;//this.BeginInvoke( AlarmInfo, str );}//打开码流,送入头数据 Open streamif ( !PlayCtrl.PlayM4_OpenStream( m_lPort, pBuffer, dwBufSize, 2 * 1024 * 1024 ) ){nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );//str = "PlayM4_OpenStream failed, error code= " + nLastErr;//this.BeginInvoke( AlarmInfo, str );break;}//设置显示缓冲区个数 Set the display buffer numberif ( !PlayCtrl.PlayM4_SetDisplayBuf( m_lPort, 15 ) ){nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );//str = "PlayM4_SetDisplayBuf failed, error code= " + nLastErr;//this.BeginInvoke( AlarmInfo, str );}//设置显示模式 Set the display mode//if ( !PlayCtrl.PlayM4_SetOverlayMode( m_lPort, 0, 0) ) //play off screen //{//    nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );//    //str = "PlayM4_SetOverlayMode failed, error code= " + nLastErr;//    //this.BeginInvoke( AlarmInfo, str );//}//设置解码回调函数,获取解码后音视频原始数据 Set callback function of decoded datam_fDisplayFun = new PlayCtrl.DECCBFUN( DecCallbackFUN );if ( !PlayCtrl.PlayM4_SetDecCallBackEx( m_lPort, m_fDisplayFun, IntPtr.Zero, 0 ) ){//this.BeginInvoke( AlarmInfo, "PlayM4_SetDisplayCallBack fail" );}//开始解码 Start to play                       if ( !PlayCtrl.PlayM4_Play( m_lPort, m_ptrRealHandle ) ){nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );//str = "PlayM4_Play failed, error code= " + nLastErr;//this.BeginInvoke( AlarmInfo, str );break;}}break;case CHCNetSDK.NET_DVR_STREAMDATA: // video stream datadefault: //the other dataif ( dwBufSize > 0 && m_lPort != -1 ){for ( int i = 0; i < 999; i++ ){//送入码流数据进行解码 Input the stream data to decodeif ( !PlayCtrl.PlayM4_InputData( m_lPort, pBuffer, dwBufSize ) ){nLastErr = PlayCtrl.PlayM4_GetLastError( m_lPort );//str = "PlayM4_InputData failed, error code= " + nLastErr;Thread.Sleep( 2 );}elsebreak;}}break;}}//解码回调函数private void DecCallbackFUN( int nPort, IntPtr pBuf, int nSize, ref PlayCtrl.FRAME_INFO pFrameInfo, int nReserved1, int nReserved2 ){if ( pFrameInfo.nType == 3 ) //#define T_YV12   3{byte[] byteBuffYV12 = new byte[ nSize ];Marshal.Copy( pBuf, byteBuffYV12, 0, nSize );long lRGBSize = (long)pFrameInfo.nWidth * pFrameInfo.nHeight * 4;byte[] bufferRGB32 = new byte[ lRGBSize ];CommonFun.YV12_to_RGB32( byteBuffYV12, bufferRGB32, pFrameInfo.nWidth, pFrameInfo.nHeight );byteBuffYV12 = null;Bitmap bmpFromGRB32 = CommonFun.RGB32_to_Image( bufferRGB32, pFrameInfo.nWidth, pFrameInfo.nHeight );bufferRGB32 = null;if ( null == bmpFromGRB32 )return;m_img = bmpFromGRB32;}}}

注:得到的m_img用于PictureBox进行显示。

2、YV12转换为RGB32、RGB32转换为Image代码
class CommonFun{public static bool YV12_to_RGB32(  byte[] buffYV12, byte[] bufferRGB32, int nWidth, int nHeight ){if( buffYV12.Length < 0 || bufferRGB32.Length < 0 )return false;long nYLen = (long)nWidth * nHeight;int nHfWidth = ( nWidth >> 1 );if ( nYLen < 1 || nHfWidth < 1 )return false;byte[] byteYData = buffYV12.Skip( 0 ).Take( nWidth*nHeight ).ToArray();byte[] byteUData = buffYV12.Skip( nWidth*nHeight ).Take( (nHeight/2)*(nWidth/2) ).ToArray();byte[] byteVData = buffYV12.Skip( nWidth*nHeight + (nHeight/2)*(nWidth/2) ).Take( (nHeight/2)*(nWidth/2) ).ToArray();if ( byteYData.Length < 0 || byteVData.Length < 0 || byteUData.Length < 0 )return false;int[] nRgb = new int[4];for( int nRow = 0; nRow < nHeight; nRow++ ){for( int nCol = 0; nCol < nWidth; nCol++ ){int Y = byteYData[nRow*nWidth + nCol];int U = byteUData[(nRow / 2)*(nWidth / 2) + (nCol / 2)];int V = byteVData[(nRow / 2)*(nWidth / 2) + (nCol / 2)];int R = Y + (U - 128) + (((U - 128) * 103) >> 8);int G = Y - (((V - 128) * 88) >> 8) - (((U - 128) * 183) >> 8);int B = Y + (V - 128) + (((V - 128) * 198) >> 8);// r分量值 R = R<0 ? 0 : R;nRgb[2] = R > 255 ? 255 : R;// g分量值G = G<0 ? 0 : G;nRgb[1] = G > 255 ? 255 : G;// b分量值 B = B<0 ? 0 : B;nRgb[0] = B > 255 ? 255 : B;//A分量值nRgb[ 3 ] = 255;//Out RGB BufferbufferRGB32[4 * (nRow*nWidth + nCol) + 0] = (byte)nRgb[0];bufferRGB32[4 * (nRow*nWidth + nCol) + 1] = (byte)nRgb[1];bufferRGB32[4 * (nRow*nWidth + nCol) + 2] = (byte)nRgb[2];bufferRGB32[4 * (nRow*nWidth + nCol) + 3] = (byte)nRgb[3];}}return true;}public static Bitmap RGB32_to_Image( byte[] byteBuff, int nWidth, int nHeight ){if ( byteBuff.Length <= 0 || byteBuff.Length < nWidth*nHeight )return null;Bitmap bmp = new Bitmap( nWidth, nHeight, PixelFormat.Format32bppArgb );//锁定内存数据BitmapData bmpData = bmp.LockBits( new Rectangle( 0, 0, nWidth, nHeight ), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb );//输入颜色数据System.Runtime.InteropServices.Marshal.Copy( byteBuff, 0, bmpData.Scan0, byteBuff.Length );//解锁bmp.UnlockBits( bmpData );return bmp;}}

效果

转载于:https://blog.51cto.com/weiyuqingcheng/2323546

C#:使用海康SDK解码回调函数DecCallbackFUN()相关推荐

  1. 海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP)

    海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP) 问题分析 转码推rtmp PS流转封装 码云(Gitee)主页:https://gitee.com/banmaj ...

  2. Qt音视频开发02-海康sdk解码(支持句柄/回调/GPU模式/支持win/linux)

    一.前言 为何还要选用使用海康sdk,之前不是ffmpeg已经牛皮吹上天了吗?这个问题问得好,那是因为无论ffmpeg也好还是vlc/mpv之类的,都是实现的播放相关,不同的监控硬件厂家对应设备还有很 ...

  3. 海康SDK开发实时读取摄像头图像

    1.概述 最近项目需要实时读取网络摄像头,并对图像做处理,参考网络资料和海康SDK开发文档,文档中给了两种方式(1)SDK直接解码显示(2)实时流数据回调,用户自行处理码流数据(开发文档上以软解显示为 ...

  4. 海康sdk docker虚拟化

    海康sdk docker虚拟化 主要使用sdk 对接IPC,对外提供视频播放的功能.在容器内运行了海康的sdk对接程序和tcp server. sdk使用的标准码流回调函数,将视频码流拿到后,利用tc ...

  5. 海康SDK/大华SDK安防视频智能分析平台EasyCVR如何将通道视频流推送至CDN分发?

    EasyCVR视频协议融合平台不仅支持常规协议的接入,我们还拓展了海康SDK.大华SDK.Ehome等私有协议.如果前端设备协议不同且数量较多,则可以通过EasyCVR平台来对所有视频通道做整合和统一 ...

  6. 海康摄像头二次开发python_python实现海康sdk二次开发,移动侦测事件(一)

    1.概述 最近一段时间要从海康摄像头读取数据,作为程序的输入源,c++版本有海康有自己的demo,较为简单,很容易就实现了,但是为我们其他的程序都是基于python的,因此,需要使用Python调用海 ...

  7. 应用海康SDK获取设备图片A fatal error has been detected by the Java Runtime Environment:

    海康SDK版本:CH-HCNetSDKV6.1.6.45 add message # # A fatal error has been detected by the Java Runtime Env ...

  8. ubuntu 通过 海康sdk调用摄像头抓图片

    https://blog.csdn.net/ding977921830/article/details/75272384 在本文中我的电脑是使用的Ubuntu16.04 64位,使用工具是QT5.7. ...

  9. Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)

    关于在Windows环境中对海康威视工业相机SDK进行二次开发的话,可以参考这两篇博客. 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一) 海康威视工业相机SDK二 ...

最新文章

  1. 计算机视觉的“惨胜”:反思大型图像数据集
  2. Python 笔试集(1):关于 Python 链式赋值的坑
  3. android高效加载网络图片
  4. C#串口上位机软件--IOT串口调试精灵
  5. Tomcat/weblogic session失效时间的几种设置方法
  6. 归并排序的实现-代码
  7. map multimapc++_黑马C++视频笔记《STL之map/multimap》
  8. Python网络爬虫开发实战,关于过程中的异常处理
  9. C#串口通信工作笔记0001---嵌入式_串口通信_数据发送
  10. Atitit 自然语言与人工语言的语法构建ast的异同点 目录 1. 语言节点gaishu。。 2 1.1. 节点、函数数量大约200个 2 1.2. 关键词节点 是 有 的 3 1.3. 标识符
  11. 【开发工具】【Java开发工具 IDEAIU-2017.3】【安装和激活】
  12. 推荐10款最好的免费项目管理工具
  13. mysql,php,redis,jq小记
  14. 计算机年龄测试题,我的世界:五道测试题,看看你游戏时间是否和MC年龄相当...
  15. matlab 二阶低通滤波器,二阶无源RC滤波的MATLAB仿真
  16. 欧盟玩具标准EN71-3更新至2019版
  17. Packet Tracer--配置帧中继
  18. 《三级医院评审标准(2020年版)》解读
  19. zookeeper --马士兵
  20. 胖虎白话学习设计模式之外观设计模式(Facade)

热门文章

  1. 调用免费API查询全年工作日、周末、法定节假日、节假日调休补班数据
  2. 标准POE的供电距离究竟有多远?
  3. 刀模绘图软件 圆刀绘图软件 圆棍绘图软件 CAD插件 外挂
  4. 提供软件注册功能-Autocad2014zcj提供下载
  5. jquery 判断元素下是不是有子元素
  6. Pico 的安卓自启动
  7. HTML谷歌字体服务
  8. Elasticsearch:fuzzy 搜索 (模糊搜索)
  9. 数据挖掘:R语言k均值聚类
  10. nb信号和4g信号_【和你一起聊聊NB-IoT】NB信号强度的那些事