海康威视频监控设备Web查看系统(三):Web篇

声明:本系列文章只提供交流与学习使用。文章中所有涉及到海康威视设备的SDK均可在海康威视官方网站下载得到。文章中所有除官方SDK以为的代码均可随意使用,任何涉及到海康威视公司利益的非正常使用由使用者自己负责,与本人无关。

前言:

海康威视频监控设备Web查看系统(一):概要篇

海康威视频监控设备Web查看系统(二):服务器篇

本文是本系列三篇文章中的最后一篇,在前两篇文章中,介绍了开发海康监控的方案及中转服务器的实现,本篇文章介绍Web端的功能实现,经过本篇文章中的项目开发,我们就实现了最初的项目需求。 项目中需要海康官方播放器SDK,请各位根据项目需要下载相应版本。先来作者就带着大家一步步来实现客户端插件的开发。

播放器开发:

根据海康官方的SDK,我们要做的播放器其实只是将海康的播放库引入到我们自己的项目中,然后接收来自中转服务器的数据,最后播放显示到客户Web浏览器上。其实整个就是一个引入了海康播放库的ActiveX插件开发。下面按照开发流程一步步实现播放器插件开发。

  1. 新建C#类库项目
  2. 将播放器SDK中文件引入到项目中
  3. 在项目中添加Winform用户控件
  4. 新建安装项目
  5. 发布项目
  6. 数字签名
  7. 发布Web网站

关于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         #endregion
88     }

根据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.PlayM4_GetLastError(prot));
                        break;
                    }
                    if (!PlayCtrlSDK.PlayM4_SetDisplayBuf(prot, 15))
                    {
                        PageClose();
                        showError(PlayCtrlSDK.PlayM4_GetLastError(prot));
                        break;
                    }
                    this.Invoke(new MethodInvoker(delegate
                    {
                        //使用PictureBox控件句柄作为参数传给播放器,播放器将其作为容器进行图像渲染
                        if (!PlayCtrlSDK.PlayM4_Play(prot, this.pictureBox1.Handle))
                        {
                            PageClose();
                            showError(PlayCtrlSDK.PlayM4_GetLastError(prot));
                        }
                    }));
                    isPlayInit = true;
                    break;
                case StreamType.Body:
                    if (isPlayInit && !PlayCtrlSDK.PlayM4_InputData(prot, buffer, size))
                    {
                        PageClose();
                        showError(PlayCtrlSDK.PlayM4_GetLastError(prot));
                    }
                    break;
            }
        }
        /// <summary>
        /// 错误提示
        /// </summary>
        /// <param name="p"></param>
        private void showError(uint p)
        {
            MessageBox.Show(p.ToString());
        }

        #region IObjectSafety接口方法
        public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
        {
            pdwEnabledOptions = 2;
            pdwSupportedOptions = 1;
        }
        public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
        {
        }
        #endregion

        enum StreamType { Head, Body }
    }

如上文所提到的,PlayCtrlSDK.PlayM4_OpenStream(int nPort, byte[] pFileHeadBuf, UInt32 nSize, uint nBufPoolSize);方法必须以中转服务器发送的长度为40个字节的数据作为形参pFileHeadBuf的实参传入,否则播放器无法正常工作。另外,InitPlay(string ip, int iPprot)用JS直接调用,讲实参传入即可,利于中转服务调整和扩展。

到这里,Web浏览器插件的内容介绍完了。最后直接贴出Web网站的内容给大家,相信一看就明白,真的不用不用说什么了吧。。。

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 <html xmlns="http://www.w3.org/1999/xhtml">
  3 <head>
  4     <title>视频播放</title>
  5     <style type="text/css">
  6         *
  7         {
  8             padding: 0;
  9             margin: 0;
 10         }
 11         body
 12         {
 13             background: #000;
 14         }
 15         a
 16         {
 17             display: block;
 18             text-decoration: none;
 19             line-height: 40px;
 20             color: #fff;
 21             width: 293px;
 22             height: 40px;
 23             text-align: center;
 24             background: #333;
 25         }
 26         a:hover
 27         {
 28             color: #000;
 29             background: #eee;
 30         }
 31     </style>
 32     <script type="text/javascript" language="javascript">
 33         var channel = 1;
 34         window.onbeforeunload = function () {
 35             player.PageClose();
 36             var result = getServer("unload");
 37         };
 38
 39         function getServer(operate) {
 40             var xmlhttp;
 41             if (window.XMLHttpRequest) {
 42                 xmlhttp = new XMLHttpRequest();
 43             }
 44             else {
 45                 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
 46             }
 47             //说明:
 48             //******这里的方法是为取得视频中转服务器的IP以及端口***************
 49             xmlhttp.open("GET", "ServerHandler.ashx?channel=" + channel + "&operate=" + operate, false);
 50
 51             xmlhttp.send();
 52             return xmlhttp.responseText;
 53         }
 54
 55         function Show(ch) {
 56             getServer("unload");
 57             var ctrls = document.getElementsByTagName("a");
 58             for (var i = 0; i < ctrls.length; i++) {
 59                 ctrls[i].disabled = "";
 60             }
 61             channel = ch;
 62             var host = getServer("load").split(‘:‘);
 63             document.getElementById("errorDiv").innerHTML = "IP:" + host[0] + "   Port:" + host[1] + " Count:" + host[2];
 64             player.PageClose();
 65             player.InitPlay(host[0], host[1]);
 66             var result = player.ShowVideo();
 67             document.getElementById("but" + channel).disabled = result;
 68         }
 69
 70         function refreshSession() {
 71             getServer("refresh");
 72         }
 73
 74         setInterval("refreshSession()", 3000);
 75     </script>
 76 </head>
 77 <body>
 78     <table width="600" align="center">
 79         <tr>
 80             <td colspan="2" align="center">
 81                 <object id="player" classid="clsid:A4277AC0-7F3F-4950-9130-27025D6E18F8" width="600"
 82                     height="400" codebase="Setup.exe">
 83                 </object>
 84             </td>
 85         </tr>
 86         <tr>
 87             <td height="40" width="300" align="center">
 88                 <a href="#" onclick="Show(1)" id="but1">视频1</a>
 89             </td>
 90             <td width="300" align="center">
 91                 <a href="#" onclick="Show(2)" id="but2">视频2</a>
 92             </td>
 93         </tr>
 94         <tr>
 95             <td colspan="2">
 96                 <div id="errorDiv">
 97                 </div>
 98             </td>
 99         </tr>
100     </table>
101     <script language="javascript">
102         Show(1);
103     </script>
104 </body>
105 </html>

至此,关于海康威视视频中转系统的所有内容都已经介绍完了,希望本人的文章能给您带来一点帮助。如果您还有任何问题,非常欢迎发送邮件到[email protected]进行交流。

另外也非常欢迎大家加入QQ群:107943411来交流学习。

海康威视频监控设备Web查看系统(三):Web篇,布布扣,bubuko.com

时间: 2024-10-12 23:26:14

海康威视频监控设备Web查看系统(三):Web篇的相关文章

海康威视频监控设备Web查看系统(二):服务器篇

声明:本系列文章只提供交流与学习使用.文章中所有涉及到海康威视设备的SDK均可在海康威视官方网站下载得到.文章中所有除官方SDK意外的代码均可随意使用,任何涉及到海康威视公司利益的非正常使用由使用者自己负责,与本人无关. 前言: 上一篇文章<海康威视频监控设备Web查看系统(一):概要篇>笼统的介绍了关于海康视频中转方案的思路,本文将一步步实现方案中的视频中转服务端.文中会涉及到一些.net socket处理和基础的多线程操作.我用的是SDK版本是SDK_Win32_V4.2.8.1 .大家根

海康威视频监控设备Web查看系统(一):概要篇

声明:本系列文章只提供交流与学习使用.文章中所有涉及到海康威视设备的SDK均可在海康威视官方网站下载得到.文章中所有除官方SDK意外的代码均可随意使用,任何涉及到海康威视公司利益的非正常使用由使用者自己负责,与本人无关. 题外话: 为什么在开始之前先说题外话呢?主要是为了怕有人误会,以为这里要写的是一个关于视频流处理的文章.其实这个系列的几篇文章可能和视频流的处理半毛钱关系都没有,冲着视频技术来的看官们,可能让你们失望了.这个系列里主要涉及的技术大概有.net的socket处理,C#写Activ

海康视频监控---Demo

1,使用在页面中调用ActiveX控件 <object classid='clsid:E7EF736D-B4E6-4A5A-BA94-732D71107808' codebase='' standby='Waiting...' id='PreviewActiveX' width='100%' height='100%' name='ocx' align='center'> <param name='wndtype' value='1'> <param name='playmo

【云快讯】《选择视频监控云11个理由》

2015-08-28 张晓东 东方云洞察 点击上面的链接文字,可以快速关注"东方云洞察"公众号 VSaaS(视频监控作为一种服务),是指基于云托管的视频监控.该服务通常包括视频录制.存储.远程查看.管理警报.网络安全等内容.据统计,百分之93的企业已经采用了云解决方案.云计算技术的进步和更大的带宽使得VSaaS(也被称为云视频监控)越来越有吸引力. 本文节选自Dean Drako的白皮书<11 reasons Why VideoSurveillance is Moving to

一周集成行业智能监控应用,阿里云发布智能视频监控平台

在4月22-25日于上海举办的2019联通合作伙伴大会上,阿里云首次对外发布了智能视频监控平台,同时向参会的数千名伙伴及业界人士演示了一分钟视频监控上云系统,阐述了阿里云智能视频监控平台助力传统监控领域上云的优势和方法. 在视频监控领域,上云和AI是未来的趋势,阿里云智能视频监控解决方案无缝集成了视频监控产品和智能视觉产品.该平台依托遍布全球的边缘接入节点和出色的视频技术,面向监控设备提供统一开放的视频流接入.处理和分发服务.将传统的本地监控视频内容接入云端,进行存储.录制回看.全网分发,同时通

VSAM:视频监控系统 A System for Video Surveillance and Monitoring

VSAM(VideoSurveillance and Monitoring)视频监控系统 Robotics Institute CMU 1:引言 2:试验床介绍 3:基本的视频分析算法:运动目标检测,跟踪,分类,简单行为识别 4:地理空间模型,感知网络标定,三维地理位置估计,目标图形显示 5:多摄像机协作 6:成果展示及未来的研究计划 1 引言 VSAM可自动解析场景中的人和车,检测目标并按语义分类,如人.人群.车,以及在此基础上的行为分析,如走动.奔跑.利用VSAM,单个人即可监控复杂区域,跟

Qt编写安防视频监控系统18-云台控制

一.前言 云台控制是视频监控系统中必备的一个功能,对球机进行上下左右的移动,还有焦距的控制,其实核心就是控制XYZ三个坐标轴,为了开发这个模块,特意研究了各种云台控制的方法和开源库比如soap,有些厂家使用自家SDK控制云台,但是大部分都会选择onvif来控制,毕竟是国际标准的通用的,只要符合这个标准的都可以使用,onvif协议的解析通常用的开源库是soap,涵盖的内容比较全,包括获取各种设备信息和回控等,缺点就是比较臃肿,使用非常不容易,函数名实在是有点不顺手,很多新手都绕在其中不知所措最后放

高清网络视频监控系统中交换机的选择

目前视频监控系统已经完成从传统模拟视频监控到数字视频监控的全面升级,并逐渐发展到高清网络数字视频监控阶段,利用现有的办公网络.行业专网.光纤专网,甚至互联网和无线网络等基础架构,搭建以区域安防.生产监视等不同目的的高清网络视频监控系统.其中百万级像素网络摄像机的大规模普及,既解决了传统模拟视频监控系统清晰度不足的尴尬局面也提高了监控系统的便捷性和安全性. 高清网络视频监控系统优势 先进性:利用现有的综合布线网络传输图像,进行实时监控系统所需的前端设备少,连线简洁,后端仅需一套软件系统即可; 可靠

大规模视频监控系统将以云存储为主

随着高清技术的普及,720P.1080P视频已经遍地开花,同时基于对 清晰度的追求,时候智能分析的处理,500W.800W.甚至上千万更高分辨率的摄像机开始崭露头角:如此高清的监控,问题也伴随而来:高清视频数据动辄 几G到几十G的文件,对存储设备的容量.读写性能.可靠性.扩展性等都提出了更高的要求,对于存储厂商而言也面临着更大的挑战:如何在视频监控系统中选用 适宜的数据存储解决方案,显得格外重要.站在系统建设角度考虑,需要充分考虑功能集成度.数据安全性.数据稳定性,系统可扩展性.性能及成本各方面