一个朋友做监控,用的海康威视的设备,海康威视本身自己有Android客户端,但朋友想开发一款自己的软件,配合硬件一起销售,还可以进行定制化开发,所以应朋友之请,就研究了下海康威视的相关SDK开发。

研究后发现,要实现上述功能,需要用到两个SDK:

1、海康威视android 网络库

2、海康威视android 播放库

问题马上来了,海康威视的官网只有android 播放库下载,没有android 网络库下载,通过400电话联系了海康威视的技术人员,对方说请和当时销售联系索取,联系了销售,说了半天对方也没听懂我们要什么,这可能就是做技术的和做市场的不同。

没有办法,只能在网上找,网海茫茫,找个sdk可真是费了牛劲,终于在“程序员”联合开发网上找到一个“hone_Monitor_SDK(android)”,介绍说:“海康威视android手机监控SDK,对想做android视频监控程序的朋友作用会很大,欢迎下载”,着实兴奋了一下,注册、下载,一气呵成,下载下来后因为没有sdk使用说明,又从海康威视官网下载了liunx版的网络库sdk使用说明(想着应该大同小异,可以参考),研究后,捣鼓出一个demo,运行后,连接服务器、登录设备都没有问题,可以看到监控点数量、设备序列号,但死活无法播放,一调用实时预览,就返回失败7,使用说明上解释说是网络故障,再怎么折腾也无济于事。

于是又开始研究海康威视自己的android客户端(IVMS-4500),看着人家这个连接一点问题没的,怀疑可能我下的sdk版本太老(那个上面介绍支持android1.5,应该是2011年以前的)或者调用方法不对,想着干脆把他这个客户端反编译了看看,如果没有混淆,可以好好研究研究,即使混淆了,有些地方也能看个大概,说干就干,反编译后发现竟然没有混淆,哈哈,他自身sdk的调用看个一清二楚,仔细研究后,发现我的写法没有问题,基本可以肯定我下的sdk版本太老,可能现在的设备都不支持了,突发奇想:他这个反编译的结果是个jar包,如果我直接引用的话,不是他调用的功能、函数、类、接口什么的我都可以用么,呵呵,ok,直接导入我的demo工程,把我之前的sdk删掉,运行,哈哈,大功告成!

好了,讲了这么多,步入正题,先介绍下为什麽要用两个sdk,海康威视android 网络库是用来与设备建立远程连接,音、视频解码,进行实时预览、回放等等功能的,但是它所得到的仅仅是二进制的音、视频数据而已,要真正的显示到手机界面上,还需要海康威视android 播放库sdk得支持,通过播放库sdk,才可以将视频显示到SurfaceView之上。也就是下面的结构:

//上代码

//sdk定义  private Player myPlayer = null;  private HCNetSDK videoCtr;  //******************************************************************  //sdk初始化  videoCtr = new HCNetSDK();  //实例化网络库SDK  videoCtr.NET_DVR_Init();  //初始化网络库SDK    //******************************************************************  连接服务器,登录,实时预览代码示例:    videoHolder = videoView.getHolder();  //获取视频显示窗口(SurfaceView对象)的Holder  myPlayer = Player.getInstance();  //实例话播放库对象  playPort = myPlayer.getPort();   //获取播放端口  ///关于播放库SDK的使用海康威视官网有详细说明    // 登录服务器  NET_DVR_DEVICEINFO_V30 deviceInfo = new NET_DVR_DEVICEINFO_V30();  int userid = videoCtr.NET_DVR_Login_V30(cameraInfo.serverip,  cameraInfo.serverport, cameraInfo.username, cameraInfo.userpwd,  deviceInfo);  System.out.println("下面是设备信息************************");  System.out.println("通道开始=" + deviceInfo.byStartChan);  System.out.println("通道个数=" + deviceInfo.byChanNum);  System.out.println("设备类型=" + deviceInfo.byDVRType);  System.out.println("ip通道个数=" + deviceInfo.byIPChanNum);    byte[] snByte = deviceInfo.sSerialNumber;  String sNo = "";  for (int i = 0; i < snByte.length; i++) {      sNo += String.valueOf(snByte[i]);  }  System.out.println("设备序列号=" + sNo);  System.out.println("************************");    NET_DVR_CLIENTINFO clientInfo = new NET_DVR_CLIENTINFO();  clientInfo.lChannel = 1;   //需要打开的通道(可以参考通道开始序号和通道个数,一般从1开始)  clientInfo.lLinkMode = 0x80000000;  //子码流(保证图像连续性),tcp连接方式,如果要保证图像清晰度,可选用主码流 (值全改为0:0x00000000) clientInfo.sMultiCastIP = null;    int playFlag = videoCtr.NET_DVR_RealPlay_V30(userid, clientInfo,  mRealDataCallback, false);   //mRealDataCallback即为数据回传回掉函数 



//******************************************************************

数据回传回掉函数定义代码:

注意,函数中的videoHolder变量即为要显示视频的SurfaceView的Holder,通过SurfaceView对象的getHolder()方法获得

private RealPlayCallBack mRealDataCallback = new RealPlayCallBack() {      @Override      public void fRealDataCallBack(int arg0, int dataType,              byte[] paramArrayOfByte, int byteLen) {          // TODO Auto-generated method stub          // 回掉函数            switch (dataType) {          case 1: // 头数据                if (myPlayer.openStream(playPort, paramArrayOfByte, byteLen,                      1024 * 1024)) {                  if (myPlayer.setStreamOpenMode(playPort, 1)) {                      if (myPlayer.play(playPort, videoHolder)) {                          playFlag = true;                      } else {                          playError(3);                      }                  } else {                      playError(2);                  }              } else {                  playError(1);              }                break;          case 2:         case 4:               if (playFlag                      && myPlayer.inputData(playPort, paramArrayOfByte,                              byteLen)) {                  playFlag = true;              } else {                  playError(4);                  playFlag = false;              }            }        }  };  



另外要注意的是调用顺序:

1、sdk实例话及初始化

2、在要显示视频的SurfaceView对象创建完成后(即surfaceCreated()方法被触发)再连接服务器,进行实时预览,否则在实时预览时可能会出现SurfaceView尚未完全加载成功,导致调调数据显示异常。

3、关于SurfaceView对象的使用,可以参考的资料很多,此处不再说明。

4、demo源码直接传上:http://download.csdn.net/detail/a358763471/6746599

更多相关文章

  1. Android自定义实现圆形播放进度条
  2. adb 无线调试
  3. Android实现视频播放的3种实现方式
  4. Android(安卓)adb(Android(安卓)Debug Bridge)常用命令
  5. Android之Media播放器源码分析(framework——native)
  6. Android(安卓)USB HID设备通信controlTransfer 接口参数
  7. 屏幕适配全攻略
  8. 将写好的软件安装到Android手机
  9. 为Android应用程序读取/dev下设备而提权(二)

随机推荐

  1. Android应用程序获取ROOT权限的方法 (基础
  2. 建本地 repo server
  3. 折磨死我的conversion to dalvik format
  4. Android在子线程中更新UI的方法汇总(共七
  5. android自带图片资源图标一览,android.R.d
  6. Android 使用View的旋转实现漂亮的动画效
  7. android studio 简单二维码扫描实现
  8. Android之解析Android Map地图返回的Json
  9. 基于 Android(安卓)NDK 的学习之旅-----
  10. Android架构分析之硬件抽象层(HAL)