声明:本系列文章只提供交流与学习使用。文章中所有涉及到海康威视设备的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. windows 下 gcc/g++ 的安装(有图,一步一步)

    下载 mingw 首先打开 www.mingw.org .(注意版本,建议64bit) www.mingw.org 直接点击右上方的 Download Installer 即可下载. 点击 Downl ...

  2. matlab、sklearn 中的数据预处理

    数据预处理(normalize.scale) 0. 使用 PCA 降维 matlab: [coeff, score] = pca(A); reducedDimension = coeff(:,1:5) ...

  3. WPF 通过位处理合并图片

    原文:WPF 通过位处理合并图片 本文告诉大家,在使用 WPF 合并两张图片的处理,可以使用像素之间的与或和异或的方式,对三个颜色的通道进行处理. 先给大家看一下软件的界面 这就是通过将左边的两张图片 ...

  4. options.parse === void 0

    if (options.parse === void 0) options.parse = true; https://developer.mozilla.org/zh-CN/docs/Web/Jav ...

  5. node lesson4--eventproxy不懂

    var express = require('express'); var superagent = require('superagent'); var cheerio = require('che ...

  6. 用java写的后台方法可以提供给C#调用吗?(转)

    最近和公司搞C#的同事联合搞了一个项目,我把我这边的数据加密之后传给C#,然后C#在对接收到的数据解密.可是问题来了,我这边用JAVA加密的数据C#的同事怎么也解密不出来,于是我就想到了可不可以将JA ...

  7. s3c2410 cs8900a 网卡驱动程序

    /* CS8900a.h */ #define CONFIG_CERF_CS8900A 1 /* * cs8900a.c: A Crystal Semiconductor (Now Cirrus Lo ...

  8. eclipse中JUnit工具的使用

  9. Customize Acrylic Brush in UWP Applications(在UWP中自定义亚克力笔刷)

    原文 Customize Acrylic Brush in UWP Applications(在UWP中自定义亚克力笔刷) Windows 10 Fall Creators Update(Build ...

  10. sql语句计算出每个月的天数

    原文:sql语句计算出每个月的天数   从当前月-11个月开始,到当前月为止,用一个sql语句计算出每个月的天数. SELECT TO_CHAR(ADD_MONTHS(SYSDATE,-LEVEL+1 ...