Android端实现Onvif IPC开发(一)——gSoap移植NDK尝试

@[toc]

Android端实现Onvif IPC开发:

【Android音视频】Onvif-IPC开发(一)——gSoap-onvif移植到Android》
【Android音视频】Onvif-IPC开发(二)——JAVA版本onvif服务器构建Onvif-IP-Camera
【Android音视频】Onvif IPC开发(三)——YUV格式深入浅出
[【Android音视频】Onvif IPC开发(四)——Onvif移植Android架构与补全方案(更新中...) ]

阅读说明(必读)

改动,在我2018年12月1日前,博客一直没跟新这条,前面又说onvif ndk移植失败,不过我后面又调通了,相比于java版本,用java实现显得有点生硬,且容易漏下一些协议内容,导致识别或者控制上的问题,最稳妥的还是用gosap生成的onvif server端去处理协议

移植NDK最主要的问题是生成的OnvifServer工程太大,而关键便在于如何缩小工程量,这边文章整个配置是没有问题的,在环境搭建第5步,根据wsdl生成onvif.h时,需要相应的裁切。我会专门写一篇文章来介绍如何做

本文详解,在android端通过java搭建的server去模拟IPC,达到需求(实现Android端可供Onvif检测的IPC),以下是我移植的步骤及碰到的问题,你可以尝试阅读或者直接跳转到《Android端实现Onvif IPC开发(二)——在Android端搭建服务器模拟Onvif IP Camera》,以下问题留待有时间会继续解决,尽请关注后续文章,如果你已经有解决办法请务必指点一下,不甚感激 ####

一、本篇项目简介

  • 大家都知道Onvif在安防领域占有牢牢领先的地位,ONVIF标准为网络视频设备之间的信息交换定义通用协议,包括装置搜寻、实时视频、音频、元数据和控制信息等,Onvif在现实中的应用,大多是嵌入式开发中使用。于是我在想,能否降Onvif协议集成到Android设备上呢,并且打包成SDK,这样的话也许很有趣,让我们来动手吧!
  • Onvif协议的内容:
    • ONVIF规范中设备管理和控制部分所定义的接口均以Web Services的形式提供。ONVIF规范涵盖了完全的XML及WSDL的定义。每一个支持ONVIF规范的终端设备均须提供与功能相应的Web Service。服务端与客户端的数据交互采用SOAP协议
    • 音视频流则通过RTP/RTSP进行
  • Onvif协议模板的生成可以通过gSoap去自动生成,SOAP协议是基于XML的,需要通过他生成的.c和.h去集成到我们的项目中
  • 了解一些基本概念:
    • xml:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言
    • http:超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议
    • soap:简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息
    • WS-discovery:你在预先不知道目标服务的情况下,可以动态的探测可用的服务并调用
    • wsdl:网络服务描述语言是Web Service的描述语言,它包含一系列描述某个web service的定义。这里可以通俗的理解为协议定义。

二、环境搭建

  1. 我的开发环境是Ubuntu 16.04 LTS 内存 8G I5 4核

  2. gSoap下载地址:http://www.cs.fsu.edu/~engelen/soap.html,我下载的版本是2.8.66

  3. 下载好解压到工程目录ipc_project

     $:./configure
     $:make
     $:make install
     安装完成后执行:wsdl2h或者soapcpp2查看gSOAP是否已经安装成功
     然后需要安装以下基本库:
         sudu apt install libssl-dev
         sudo apt-get install cmake
         sudo apt-get install build-essential
         sudo apt-get install libgtk2.0-dev liblib2.0-dev
         sudo apt-get install checkinstall 
    
     将wsa5.h的SOAP_ENV__Fault改名,因为其它地方也存在这个结构体,随意改,不冲突即可
     修改typemap.dat,在
     wstop     = "http://docs.oasis-open.org/wsn/t-1"
     后面加:
     #     WS-Discovery 1.0 remapping
     wsdd10__HelloType          = | wsdd__HelloType
     wsdd10__ByeType               = | wsdd__ByeType
     wsdd10__ProbeType          = | wsdd__ProbeType
     wsdd10__ProbeMatchesType     = | wsdd__ProbeMatchesType
     wsdd10__ProbeMatchType          = | wsdd__ProbeMatchType
     wsdd10__ResolveType          = | wsdd__ResolveType
     wsdd10__ResolveMatchesType     = | wsdd__ResolveMatchesType
     wsdd10__ResolveMatchType     = | wsdd__ResolveMatchType
     #     SOAP-ENV mapping
     SOAP_ENV__Envelope     = struct SOAP_ENV__Envelope { struct SOAP_ENV__Header *SOAP_ENV__Header; _XML SOAP_ENV__Body; }; | struct SOAP_ENV__Envelope
     SOAP_ENV__Header     = | struct SOAP_ENV__Header
     SOAP_ENV__Fault          = | struct SOAP_ENV__Fault
     SOAP_ENV__Detail     = | struct SOAP_ENV__Detail
     SOAP_ENV__Code          = | struct SOAP_ENV__Code
     SOAP_ENV__Subcode     = | struct SOAP_ENV__Subcode
     SOAP_ENV__Reason     = | struct SOAP_ENV__Reason
    
  4. 此处可对应查看以下工程的指令含义

     $:wsdl2h -help
     Usage: wsdl2h [-a] [-b] [-c|-c++|-c++11] [-D] [-d] [-e] [-f] [-g] [-h] [-I path] [-i] [-j] [-k] [-l] [-m] [-M] [-N name] [-n name] [-O1|-O2|-O3] [-P|-p] [-q name] [-R] [-r proxyhost[:port[:uid:pwd]]] [-r:userid:passwd] [-s] [-Sname] [-t typemapfile] [-U] [-u] [-V] [-v] [-w] [-W] [-x] [-y] [-z#] [-_] [-o outfile.h] infile.wsdl infile.xsd http://www... ...
     
     -a      generate indexed struct names for local elements with anonymous types
     -b      bi-directional operations (duplex ops) added to serve one-way responses
     -c      generate C source code
     -c++    generate C++ source code (default)
     -c++11  generate C++11 source code
     -d      use DOM to populate xs:any, xs:anyType, and xs:anyAttribute
     -D      make attribute members with default values optional with pointers
     -e      don't qualify enum names
     -f      generate flat C++ class hierarchy
     -g      generate global top-level element declarations
     -h      display help info
     -Ipath  use path to find files
     -i      don't import (advanced option)
     -j      don't generate SOAP_ENV__Header and SOAP_ENV__Detail definitions
     -k      don't generate SOAP_ENV__Header mustUnderstand qualifiers
     -l      display license information
     -m      use xsd.h module to import primitive types
     -M      suppress error "must understand element with wsdl:required='true'"
     -Nname  use name for service prefixes to produce a service for each binding
     -nname  use name as the base namespace prefix instead of 'ns'
     -O1     optimize by omitting duplicate choice/sequence members
     -O2     optimize -O1 and omit unused schema types (unreachable from roots)
     -O3     optimize -O2 and omit unused schema root attributes
     -O4     optimize -O3 and omit unused schema root elements (use only with WSDLs)
     -ofile  output to file
     -P      don't create polymorphic types inherited from xsd__anyType
     -p      create polymorphic types inherited from base xsd__anyType
     -qname  use name for the C++ namespace of all declarations
     -R      generate REST operations for REST bindings specified in a WSDL
     -rhost[:port[:uid:pwd]]
             connect via proxy host, port, and proxy credentials
     -r:uid:pwd
             connect with authentication credentials (digest auth requires SSL)
     -s      don't generate STL code (no std::string and no std::vector)
     -Sname  use name instead of 'soap' for the C++ class members with soap contexts
     -tfile  use type map file instead of the default file typemap.dat
     -U      allow UTF8-encoded Unicode C/C++ identifiers when mapping XML tag names
     -u      don't generate unions
     -V      display the current version and exit
     -v      verbose output
     -W      suppress warnings
     -w      always wrap response parameters in a response struct (<=1.1.4 behavior)
     -x      don't generate _XML any/anyAttribute extensibility elements
     -y      generate typedef synonyms for structs and enums
     -z1     compatibility with 2.7.6e: generate pointer-based arrays
     -z2     compatibility with 2.7.7 to 2.7.15: qualify element/attribute references
     -z3     compatibility with 2.7.16 to 2.8.7: qualify element/attribute references
     -z4     compatibility up to 2.8.11: don't generate union structs in std::vector
     -z5     compatibility up to 2.8.15: don't include minor improvements
     -z6     compatibility up to 2.8.17: don't include minor improvements
     -z7     compatibility up to 2.8.59: don't generate std::vector of class of union
     -_      don't generate _USCORE (replace with UNICODE _x005f)
     infile.wsdl infile.xsd http://www... list of input sources (if none reads stdin)
    
     $ soapcpp2 -help
     Usage: soapcpp2 [-0|-1|-2] [-C|-S] [-T] [-Ecdt] [-L] [-a] [-A] [-b] [-c|-c++|-c++11] [-d path] [-e] [-f N] [-g] [-h] [-i] [-I path:path:...] [-l] [-m] [-n] [-p name] [-Q name] [-q name] [-r] [-s] [-t] [-u] [-V] [-v] [-w] [-x] [-y] [-z#] [infile]
     
     -1      generate SOAP 1.1 bindings
     -2      generate SOAP 1.2 bindings
     -0      no SOAP bindings, use REST
     -C      generate client-side code only
     -S      generate server-side code only
     -T      generate server auto-test code
     -Ec     generate extra routines for deep copying
     -Ed     generate extra routines for deep deletion
     -Et     generate extra routines for data traversals with walker functions
     -L      don't generate soapClientLib/soapServerLib
     -a      use SOAPAction with WS-Addressing to invoke server-side operations
     -A      require SOAPAction to invoke server-side operations
     -b      serialize byte arrays char[N] as string
     -c      generate C source code
     -c++    generate C++ source code (default)
     -c++11  generate C++ source code optimized for C++11 (compile with -std=c++11)
     -dpath  use path to save files
     -e      generate SOAP RPC encoding style bindings (also use -1 or -2)
     -fN     multiple soapC files, with N serializer definitions per file (N>=10)
     -g      generate XML sample messages in template format
     -h      display help info
     -Ipath  use path(s) for #import (paths separated with ':')
     -i      generate C++ service proxies and objects inherited from soap struct
     -j      generate C++ service proxies and objects that share a soap struct
     -l      generate linkable modules (experimental)
     -m      generate Matlab(tm) code for MEX compiler (deprecated)
     -n      use service name to rename service functions and namespace table
     -pname  save files with new prefix name instead of 'soap'
     -Qname  use name as the C++ namespace for decls, including custom serializers
     -qname  use name as the C++ namespace for decls, excluding custom serializers
     -r      generate soapReadme.md report
     -s      generate deserialization code with strict XML validation checks
     -t      generate code for fully xsi:type typed SOAP/XML messaging
     -u      uncomment comments in WSDL/schema output by suppressing XML comments
     -V      display the current version and exit
     -v      verbose output
     -w      don't generate WSDL and schema files
     -x      don't generate sample XML message files
     -y      include C/C++ type access information in sample XML messages
     -z1     compatibility: generate old-style C++ service proxies and objects
     -z2     compatibility with 2.7.x: omit XML output for NULL pointers
     -z3     compatibility with <= 2.8.30: _param_N indexing; nillable pointers
     infile  header file to parse (if none reads stdin)
    
  5. 再在该目录下创建ipc目录,将gsoap-2.8\gsoap下的typemap.dat复制到ipc目录

  6. 在ipc目录执行,生成onvif.h

     wsdl2h -s -t typemap.dat -o onvif.h http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl http://www.onvif.org/onvif/ver10/deviceio.wsdl http://www.onvif.org/onvif/ver10/display.wsdl http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl http://www.onvif.org/onvif/ver10/recording.wsdl http://www.onvif.org/onvif/ver10/replay.wsdl http://www.onvif.org/onvif/ver10/search.wsdl http://www.onvif.org/onvif/ver10/receiver.wsdl http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
    
  7. 在执行以下指令生成对应soapC.c文件等,注空格

     soapcpp2 -c onvif.h -x -I import路径 -I gsoap路径
    
  8. 将目录拷贝到工程

    • 将生成的.nsmap修改其中一个为.h,其他删除即可
    • 拷贝gsoap/custom中的duration.c/h、gsoap/ stdsoap2.c/h到工程目录,
  1. 需要注意的点
    • 以上指令都是在su权限下执行
    • 对应的生成server或者client即可,无需全部生成,不然工程浩大

三、测试工具

  1. 我这边使用的测试工具是:ONVIF Device Test Tool
  2. 给一个我的版本下载地址: ONVIF Device Test Tool
  3. 使用介绍: onvif工具使用简介

Android jni工程

Android端实现Onvif IPC开发(一)——gSoap移植NDK尝试_第1张图片
onvif_dr.png

通过以上可以看到,在soapC.cpp,soapH.h,onvif.h,soapStub.h几个文件,资源占用很大,我这边碰到的第一个问题是工程太大,编译内存不够
GCC编译静态库最多支持2g内存的,故此涉及到库的裁切问题,需要对应删选自己需要的wsdl匹配的代码生成,不然根本编译不过来,我调式了半个小时,发现方案上可行,只是暂时放弃裁切这一块转了另一个方向

还有一个方案是在android上集成ksoap2的库,留待有时间慢慢尝试

四、gSoap生成代码中的主要的坑

  • 在安装libssl-dev时会出现包的版本冲突问题,这里我们需要使用aptitude来下载

      $ sudo apt-get install libssl-dev
      Reading package lists... Done
      Building dependency tree     
      Reading state information... Done
      Some packages could not be installed. This may mean that you have
      requested an impossible situation or if you are using the unstable
      distribution that some required packages have not yet been created
      or been moved out of Incoming.
      The following information may help to resolve the situation:
      The following packages have unmet dependencies:
       libssl-dev : Depends: libssl1.0.0 (= 1.0.1-4ubuntu5) but 1.0.1-4ubuntu5.3 is to be installed
                    Recommends: libssl-doc but it is not going to be installed
      E: Unable to correct problems, you have held broken packages.
    
  • 解决办法:

      $sudo apt-get install aptitude
      $sudo aptitude install libssl-dev (这些命令都是su下执行)
      //此处对应的选择安装如下:
      The following NEW packages will be installed:
        libssl-dev{b}
      The following packages are RECOMMENDED but will NOT be installed:
        libssl-doc
      0 packages upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
      Need to get 1,528 kB of archives. After unpacking 6,179 kB will be used.
      The following packages have unmet dependencies:
       libssl-dev : Depends: libssl1.0.0 (= 1.0.1-4ubuntu5) but 1.0.1-4ubuntu5.3 is installed.
                    Depends: zlib1g-dev but it is not going to be installed.
      The following actions will resolve these dependencies:
           Keep the following packages at their current version:
      1)     libssl-dev [Not Installed]                       
      Accept this solution? [Y/n/q/?] n
      The following actions will resolve these dependencies:
           Install the following packages:                                         
      1)     zlib1g-dev [1:1.2.3.4.dfsg-3ubuntu4 (precise)]                        
           Downgrade the following packages:                                       
      2)     libssl1.0.0 [1.0.1-4ubuntu5.3 (now) -> 1.0.1-4ubuntu5 (precise-updates)]
      Accept this solution? [Y/n/q/?] y
      The following packages will be DOWNGRADED:
        libssl1.0.0
      The following NEW packages will be installed:
        libssl-dev zlib1g-dev{a}
      The following packages are RECOMMENDED but will NOT be installed:
        libssl-doc
      0 packages upgraded, 2 newly installed, 1 downgraded, 0 to remove and 0 not upgraded.
      Need to get 2,707 kB of archives. After unpacking 6,575 kB will be used.
      Do you want to continue? [Y/n/?] y
      Get: 1 http://mirror.lupaworld.com/ubuntu/ precise-updates/main libssl1.0.0 amd64 1.0.1-4ubuntu5 [1,013 kB]
      Get: 2 http://mirror.lupaworld.com/ubuntu/ precise/main zlib1g-dev amd64 1:1.2.3.4.dfsg-3ubuntu4 [165 kB]
      Get: 3 http://mirror.lupaworld.com/ubuntu/ precise-updates/main libssl-dev amd64 1.0.1-4ubuntu5 [1,528 kB]
      Fetched 2,707 kB in 5s (503 kB/s)     
      Preconfiguring packages ...
      dpkg: warning: downgrading libssl1.0.0 from 1.0.1-4ubuntu5.3 to 1.0.1-4ubuntu5.
      (Reading database ... 150648 files and directories currently installed.)
      Preparing to replace libssl1.0.0 1.0.1-4ubuntu5.3 (using .../libssl1.0.0_1.0.1-4ubuntu5_amd64.deb) ...
      Unpacking replacement libssl1.0.0 ...
      Setting up libssl1.0.0 (1.0.1-4ubuntu5) ...
      Processing triggers for libc-bin ...
      ldconfig deferred processing now taking place
      Selecting previously unselected package zlib1g-dev.
      (Reading database ... 150648 files and directories currently installed.)
      Unpacking zlib1g-dev (from .../zlib1g-dev_1%3a1.2.3.4.dfsg-3ubuntu4_amd64.deb) ...
      Selecting previously unselected package libssl-dev.
      Unpacking libssl-dev (from .../libssl-dev_1.0.1-4ubuntu5_amd64.deb) ...
      Processing triggers for man-db ...
      Setting up zlib1g-dev (1:1.2.3.4.dfsg-3ubuntu4) ...
      Setting up libssl-dev (1.0.1-4ubuntu5) ...
    
      安装完成之后的验证:
      $dpkg -l *libssl*
    

参考文档:

  • onvif规范的实现:使用gSOAP创建SOAP调用实例
  • ONVIF协议摄像机管理平台开发

推荐文档:

  1. 剪裁Onvif:减小soapC.cpp文件的大小(一)
  2. 剪裁Onvif:减小soapC.cpp文件的大小(二)

你可能感兴趣的:(Android端实现Onvif IPC开发(一)——gSoap移植NDK尝试)