声明:本系列文章只提供交流与学习使用。文章中所有涉及到海康威视设备的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#调用的内容:

 public class PlayCtrlSDK
{
#region 解码库
[DllImport("PlayCtrl.dll")]
public static extern uint PlayM4_GetLastError(int nPort);
[DllImport("PlayCtrl.dll")]
public static extern int PlayM4_GetCaps();
/// <summary>
/// 获取未使用的通道号
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_GetPort(ref int nPort);
/// <summary>
/// 设置流播放模式
/// </summary>
/// <param name="port"></param>
/// <param name="mode"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_SetStreamOpenMode(int nPort, int mode);
/// <summary>
/// 打开流
/// </summary>
/// <param name="nPort"></param>
/// <param name="pFileHeadBuf"></param>
/// <param name="nSize"></param>
/// <param name="nBufPoolSize"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_OpenStream(int nPort, byte[] pFileHeadBuf, UInt32 nSize, uint nBufPoolSize);
/// <summary>
/// 设置播放缓冲区最大缓冲帧数
/// </summary>
/// <param name="nPort"></param>
/// <param name="nNum"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_SetDisplayBuf(int nPort, uint nBufPoolSize);
/// <summary>
/// 开启播放
/// </summary>
/// <param name="nPort"></param>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_Play(int nPort, IntPtr hWnd);
/// <summary>
/// 开始倒放
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_ReversePlay(int nPort);
/// <summary>
/// 输入流数据
/// </summary>
/// <param name="nPort"></param>
/// <param name="pBuf"></param>
/// <param name="nSize"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_InputData(int nPort, byte[] pBuf, uint nSize);
/// <summary>
/// 关闭播放
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_Stop(int nPort);
/// <summary>
/// 关闭流
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_CloseStream(int nPort);
/// <summary>
/// 释放已使用的通道号
/// </summary>
/// <param name="nPort"></param>
/// <returns></returns>
[DllImport("PlayCtrl.dll")]
public static extern bool PlayM4_FreePort(int nPort); #endregion
}

根据SDK文档内的说明,这几个函数的调用顺序如下:

下面就该组织我们自己的程序接收来自中转服务器的数据,并将这些数据交给播放库的方法来处理。

    [Guid("A4277AC0-7F3F-4950-9130-27025D6E18F8")]
public partial class Player : UserControl, IObjectSafety
{
int prot = -;
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 != -)
{
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[];
while (true)
{
int count = socket.Receive(bt);
StreamType st = count == ? StreamType.Head : StreamType.Body;
setPlay(bt, (uint)count, st);
Thread.Sleep();
}
});
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 > )
{
return;
}
if (!PlayCtrlSDK.PlayM4_GetPort(ref prot))
{
PageClose();
showError(PlayCtrlSDK.PlayM4_GetLastError(prot));
break;
}
if (!PlayCtrlSDK.PlayM4_SetStreamOpenMode(prot, ))
{
PageClose();
showError(PlayCtrlSDK.PlayM4_GetLastError(prot));
break;
}
if (!PlayCtrlSDK.PlayM4_OpenStream(prot, buffer, size, * ))
{
PageClose();
showError(PlayCtrlSDK.PlayM4_GetLastError(prot));
break;
}
if (!PlayCtrlSDK.PlayM4_SetDisplayBuf(prot, ))
{
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 = ;
pdwSupportedOptions = ;
}
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网站的内容给大家,相信一看就明白,真的不用不用说什么了吧。。。

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>视频播放</title>
<style type="text/css">
*
{
padding: 0;
margin: 0;
}
body
{
background: #000;
}
a
{
display: block;
text-decoration: none;
line-height: 40px;
color: #fff;
width: 293px;
height: 40px;
text-align: center;
background: #333;
}
a:hover
{
color: #000;
background: #eee;
}
</style>
<script type="text/javascript" language="javascript">
var channel = 1;
window.onbeforeunload = function () {
player.PageClose();
var result = getServer("unload");
}; function getServer(operate) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//说明:
//******这里的方法是为取得视频中转服务器的IP以及端口***************
xmlhttp.open("GET", "ServerHandler.ashx?channel=" + channel + "&operate=" + operate, false); xmlhttp.send();
return xmlhttp.responseText;
} function Show(ch) {
getServer("unload");
var ctrls = document.getElementsByTagName("a");
for (var i = 0; i < ctrls.length; i++) {
ctrls[i].disabled = "";
}
channel = ch;
var host = getServer("load").split(':');
document.getElementById("errorDiv").innerHTML = "IP:" + host[0] + " Port:" + host[1] + " Count:" + host[2];
player.PageClose();
player.InitPlay(host[0], host[1]);
var result = player.ShowVideo();
document.getElementById("but" + channel).disabled = result;
} function refreshSession() {
getServer("refresh");
} setInterval("refreshSession()", 3000);
</script>
</head>
<body>
<table width="600" align="center">
<tr>
<td colspan="2" align="center">
<object id="player" classid="clsid:A4277AC0-7F3F-4950-9130-27025D6E18F8" width="600"
height="400" codebase="Setup.exe">
</object>
</td>
</tr>
<tr>
<td height="40" width="300" align="center">
<a href="#" onclick="Show(1)" id="but1">视频1</a>
</td>
<td width="300" align="center">
<a href="#" onclick="Show(2)" id="but2">视频2</a>
</td>
</tr>
<tr>
<td colspan="2">
<div id="errorDiv">
</div>
</td>
</tr>
</table>
<script language="javascript">
Show(1);
</script>
</body>
</html>

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

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

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

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

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

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

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

  3. 海康视频监控---Demo

    1,使用在页面中调用ActiveX控件 <object classid='clsid:E7EF736D-B4E6-4A5A-BA94-732D71107808' codebase='' stan ...

  4. 视频监控——从其他浏览器打开低版本IE方案

    1. 方案背景 由于低版本IE浏览器并不支持很多新的页面技术,导致部分页面效果难以实现;另一方面IE浏览器版本与操作系统绑定,难以统一,不同版本IE间的不兼容导致多种兼容性问题,因此本项目暂定采用Ch ...

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

    VSAM(VideoSurveillance and Monitoring)视频监控系统 Robotics Institute CMU 1:引言 2:试验床介绍 3:基本的视频分析算法:运动目标检测, ...

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

    一.前言 云台控制是视频监控系统中必备的一个功能,对球机进行上下左右的移动,还有焦距的控制,其实核心就是控制XYZ三个坐标轴,为了开发这个模块,特意研究了各种云台控制的方法和开源库比如soap,有些厂 ...

  7. 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 开源倾情奉献系列链接 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码 开源倾 ...

  8. 基于.NET打造IP智能网络视频监控系统

    开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码   开源倾情奉献系列链接 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码 开源倾情奉献:基于.NET打造 ...

  9. EasyCamera Android安卓移动视频监控单兵设备接入EasyDarwin开源流媒体云平台

    前言 随着Android系统的不断更新和发展,现在越来越多的硬件产品选择用安卓系统作为运行环境,电视机,机顶盒.门禁.行车记录仪.车载系统.单兵设备等等,Android系统底层还是Linux,但对上层 ...

随机推荐

  1. 通过maven下载jar包

    准备 你得先安装Maven如果不会点击后面的连接查看一二步.http://www.cnblogs.com/luoruiyuan/p/5776558.html 1.在任意目录下创建一个文件夹,其下创建一 ...

  2. 《GK101任意波发生器》升级固件发布(版本:1.0.1build803)

    一.固件说明: 硬件版本:0,logic.3 固件版本:1.0.1.build803 编译日期:2014-08-06 ====================================== 二. ...

  3. hdu 1081(最大子矩阵和)

    题目很简单,就是个最大子矩阵和的裸题,看来算法课本的分析后也差不多会做了.利用最大子段和的O(n)算法,对矩阵的行(或列)进行 i和j的枚举,对于第 i到j行,把同一列的元素进行压缩,得到一整行的一维 ...

  4. $(&#39;div&#39;,&#39;li&#39;)

    要搞清楚$('div','li') 和 $('div , li') 和 $('div  li') 区别$('div','li')是$(子,父),是从父节点里找子,而不是找li外面的div $('div ...

  5. android学习笔记五

    Android中的category大全 Api Level 3(SDK 1.5)和Api Level 4(SDK 1.6): android.intent.category.ALTERNATIVE a ...

  6. stap-prep 需要安装那些内核符号

    [root@server-mysql ~]# Need to install the following packages:kernel-debuginfo-2.6.32-279.el6.x86_64 ...

  7. Dreamweaver显示花括号匹配

    按Ctrl+' 可以显示对应括号内的代码.dreamweaver没办法高亮显示花括号.而且没有块选择功能.个人认为Dreamweaver的编辑功能很糟糕.

  8. MULE-ET0 、 ET1、ET2、PT1、PT2

    设计验证阶段中的五个样车试制概念 骡子车( mule car ) ET0 第一轮设计工程样车试制 ET1 第二轮设计工程样车试制 ET2 第一轮产品工装样车试制 PT1 第二轮产品工装样车试制 PT2 ...

  9. bzoj 2120 带修改莫队

    2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 7340  Solved: 2982[Submit][Status][Discuss] ...

  10. 表单传参,在action中的参数得不到

    写上面这个的时候,发现传过去的url路径是这样的 在action后面的pro=login得不到. 只需要将method中的get改成post就可以了