声明:本系列文章只提供交流与学习使用。文章中所有涉及到海康威视设备的SDK均可在海康威视官方网站下载得到。文章中所有除官方SDK以为的代码均可随意使用,任何涉及到海康威视公司利益的非正常使用由使用者自己负责,与本人无关。
前言:
《海康威视频监控设备Web查看系统(一):概要篇》
《海康威视频监控设备Web查看系统(二):服务器篇》
本文是本系列三篇文章中的最后一篇,在前两篇文章中,介绍了开发海康监控的方案及中转服务器的实现,本篇文章介绍Web端的功能实现,经过本篇文章中的项目开发,我们就实现了最初的项目需求。 项目中需要海康官方播放器SDK,请各位根据项目需要下载相应版本。先来作者就带着大家一步步来实现客户端插件的开发。
播放器开发:
根据海康官方的SDK,我们要做的播放器其实只是将海康的播放库引入到我们自己的项目中,然后接收来自中转服务器的数据,最后播放显示到客户Web浏览器上。其实整个就是一个引入了海康播放库的ActiveX插件开发。下面按照开发流程一步步实现播放器插件开发。
关于C#开发ActiveX的详细过程,园子里有好多文章写的非常详细,我这里不在累述,有不太了解的朋友,我这里推荐一篇比较详细的文章《asp.net C# 之 Activex用C#编写ActiveX控件》。本篇文章写播放器插件的核心功能。
首先来看SDK的C#调用的内容:
1 public class PlayCtrlSDK 2 { 3 #region 解码库 4 [DllImport("PlayCtrl.dll")] 5 public static extern uint PlayM4_GetLastError(int nPort); 6 [DllImport("PlayCtrl.dll")] 7 public static extern int PlayM4_GetCaps(); 8 /// <summary> 9 /// 获取未使用的通道号10 /// </summary>11 /// <param name="nPort"></param>12 /// <returns></returns>13 [DllImport("PlayCtrl.dll")]14 public static extern bool PlayM4_GetPort(ref int nPort);15 /// <summary>16 /// 设置流播放模式17 /// </summary>18 /// <param name="port"></param>19 /// <param name="mode"></param>20 /// <returns></returns>21 [DllImport("PlayCtrl.dll")]22 public static extern bool PlayM4_SetStreamOpenMode(int nPort, int mode);23 /// <summary>24 /// 打开流25 /// </summary>26 /// <param name="nPort"></param>27 /// <param name="pFileHeadBuf"></param>28 /// <param name="nSize"></param>29 /// <param name="nBufPoolSize"></param>30 /// <returns></returns>31 [DllImport("PlayCtrl.dll")]32 public static extern bool PlayM4_OpenStream(int nPort, byte[] pFileHeadBuf, UInt32 nSize, uint nBufPoolSize);33 /// <summary>34 /// 设置播放缓冲区最大缓冲帧数35 /// </summary>36 /// <param name="nPort"></param>37 /// <param name="nNum"></param>38 /// <returns></returns>39 [DllImport("PlayCtrl.dll")]40 public static extern bool PlayM4_SetDisplayBuf(int nPort, uint nBufPoolSize);41 /// <summary>42 /// 开启播放43 /// </summary>44 /// <param name="nPort"></param>45 /// <param name="hWnd"></param>46 /// <returns></returns>47 [DllImport("PlayCtrl.dll")]48 public static extern bool PlayM4_Play(int nPort, IntPtr hWnd);49 /// <summary>50 /// 开始倒放51 /// </summary>52 /// <param name="nPort"></param>53 /// <returns></returns>54 [DllImport("PlayCtrl.dll")]55 public static extern bool PlayM4_ReversePlay(int nPort);56 /// <summary>57 /// 输入流数据58 /// </summary>59 /// <param name="nPort"></param>60 /// <param name="pBuf"></param>61 /// <param name="nSize"></param>62 /// <returns></returns>63 [DllImport("PlayCtrl.dll")]64 public static extern bool PlayM4_InputData(int nPort, byte[] pBuf, uint nSize);65 /// <summary>66 /// 关闭播放67 /// </summary>68 /// <param name="nPort"></param>69 /// <returns></returns>70 [DllImport("PlayCtrl.dll")]71 public static extern bool PlayM4_Stop(int nPort);72 /// <summary>73 /// 关闭流74 /// </summary>75 /// <param name="nPort"></param>76 /// <returns></returns>77 [DllImport("PlayCtrl.dll")]78 public static extern bool PlayM4_CloseStream(int nPort);79 /// <summary>80 /// 释放已使用的通道号81 /// </summary>82 /// <param name="nPort"></param>83 /// <returns></returns>84 [DllImport("PlayCtrl.dll")]85 public static extern bool PlayM4_FreePort(int nPort);86 87 #endregion88 }
根据SDK文档内的说明,这几个函数的调用顺序如下:
下面就该组织我们自己的程序接收来自中转服务器的数据,并将这些数据交给播放库的方法来处理。
[Guid("A4277AC0-7F3F-4950-9130-27025D6E18F8")] public partial class Player : UserControl, IObjectSafety { int PRot = -1; static Socket socket; bool isPlayInit = false; ipEndPoint iep; Thread thread; #region Web页面调用的接口 /// <summary> /// 释放Socket连接和SDK播放库资源 /// </summary> public void PageClose() { isPlayInit = false; if (thread != null && thread.IsAlive) { thread.Abort(); } if (socket != null && socket.Connected) { socket.Shutdown(SocketShutdown.Both); socket.Close(); socket = null; } if (prot != -1) { PlayCtrlSDK.PlayM4_CloseStream(prot); } } //插件初始化 public Player() { InitializeComponent(); } /// <summary> /// 初始化网络连接 /// </summary> /// <param name="ip">中转服务器IP</param> /// <param name="iPprot">中转服务器端口</param> public void InitPlay(string ip, int iPprot) { PageClose(); iep = new IPEndPoint(IPAddress.Parse(ip), iPprot); socket = new Socket(iep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); thread = new Thread((object o) => { socket.Connect(iep); byte[] bt = new byte[262144]; while (true) { int count = socket.Receive(bt); StreamType st = count == 40 ? StreamType.Head : StreamType.Body; setPlay(bt, (uint)count, st); Thread.Sleep(100); } }); thread.IsBackground = true; } /// <summary> /// 开始播放 /// </summary> /// <returns></returns> public bool ShowVideo() { thread.Start(); return true; } #endregion /// <summary> /// 调用SDK播放库 /// </summary> /// <param name="buffer">从中转服务器接收到的数据</param> /// <param name="size">中转服务器发送的数据大小</param> /// <param name="type">数据类型</param> private void setPlay(byte[] buffer, uint size, StreamType type) { switch (type) { case StreamType.Head: if (size > 40) { return; } if (!PlayCtrlSDK.PlayM4_GetPort(ref prot)) { PageClose(); showError(PlayCtrlSDK.PlayM4_GetLastError(prot)); break; } if (!PlayCtrlSDK.PlayM4_SetStreamOpenMode(prot, 0)) { PageClose(); showError(PlayCtrlSDK.PlayM4_GetLastError(prot)); break; } if (!PlayCtrlSDK.PlayM4_OpenStream(prot, buffer, size, 1024 * 1024)) { PageClose(); showError(PlayCtrlSDK.Pla
新闻热点
疑难解答