精华内容
下载资源
问答
  • onvif开发

    千次阅读 2013-10-15 17:51:21
    onvif开发要到gsoap库,下载不需要安装。   1 生成c文件有如下两种方式。 1.1自己写头文件用“soapcpp2.exe”解释; 1.2下载wsdl文件,用“wsdl2h.exe”解释生成头文件,然后用“soapcpp2.exe”解释生成c文件。

    gsoap

    onvif开发要到gsoap库,下载不需要安装,简单例子参见gsoap-2.8\gsoap\samples\calc,实现一个服务端做加减乘除的例子,把运算结果发给客户端(代码见:http://download.csdn.net/detail/evsqiezi/6647303)。

    1 gsoap首先要定义“功能”,并解释成C文件。

    使用gSOAP生成代码框架。我们有两种做法:

    编写WSDL,使用wsdl2h生成头文件,再soapcpp2生成框架代码;
    编写头文件,使用soapcpp2生成框架代码;
    方法1比较通用,可方便使用其他语言开发,但是编写wsdl语法复杂;方法2比较简单,但不能与其他语言通用。
    下载ONVIF的所有WSDL文件,并生成onvif.h的命令如下:

    wsdl2h -o onvif.h -c -s -t .\typemap.dat http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl http://www.onvif.org/onvif/ver10/display.wsdl http://www.onvif.org/onvif/ver10/deviceio.wsdl http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl  http://www.onvif.org/onvif/ver10/receiver.wsdl http://www.onvif.org/onvif/ver10/recording.wsdl  http://www.onvif.org/onvif/ver10/search.wsdl http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl http://www.onvif.org/onvif/ver10/replay.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/schema/onvif.xsd  

     参数的解释如下:

                -S 仅生成客户端代码

               -t 文件名,指定type map文件,默认为typemap.dat

                            -c    产生纯C代码,否则是C++代码,默认是cpp代码
                            -L    不要产生soapClientLib.c和soapServerLib.c文件
                            -I      指定import路径
                            -x  不要产生XML示例文件
                  -j     不要产生soap_Heade..等详细定义
                            -i    生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)
               -e 禁止为enum成员加上名空间前缀

               typemap.dat文件用于指定SOAP/XML中的类型与C/C++之间的转换规则,比如在wsmap.dat里写xsd__string = | std::wstring | wchar_t* ,那么SOAP/XML中的string将转换成std::wstring或wchar_t*,这样能更好地支持中文。

    2 修改生成的onvif.h,增加一句#import "wsse.h",用“soapcpp2.exe”解释生成c文件(例如:soapcpp2.exe x.h -I ..\..\import)。

    遇到的问题:

    生成的过程中会出现SOAP_ENV__Fault重复定义,注视掉wsa5.h中得内容就行了

    ONVIF模块

    设备发现
    设备管理
    设备输入输出服务
    图像配置
    媒体配置
    实时流媒体
    接收端配置
    显示服务
    事件处理

    PTZ控制

    入门例子

     搜索设备

    注:只能搜到统一网段的设备。

    获取媒体信息

    2013.12.5

    获取设备能力
    GetCapabilities(DeviceMgmt)
    从报文中提取出媒体信息URI  :http://192.168.15.240/onvif/Media,将用于查询具体的视频源、编码器配置参数。
    如果设备具备用户名、密码,那么查询设备能力可能需要鉴权过程。
    获取RTSP的URL的步骤:
    GetProfiles(media)-》GetStreamUri(media)
    GetProfiles可以获得设备的所有配置信息,这是比较全面的数据。GetProfile或者是GetProfiles成功后会获得一个Profile的profileToken,并且如果里面的
    VideoEncoderConfiguration不为空,那么就可以使用该ProfileToken作为getStreamURI的参数,
    GetStreamUri的请求指针中必须填写profile的ProfileToken字段,就是要指明哪一个通道的流媒体地址。
    获取媒体参数
    GetVideoEncoderConfigurations:可以获得单独的媒体配置信息,返回的应答中包括主通道和子通道的数据,如:宽高,帧率,位率等。

    问题:

    Critical error: #import: Cannot open file "stlvector.h" forreading.
        那是因为我们的头文件使用了STL(wsdl2h 没用-s选项 ),这时要使用-I选项指定gSOAP的import文件路径,这个路径是"$gsoap\gsoap\import ",$gsoap为解压目录:
    如:soapcpp2 hello.h -I xx\gsoap\import

    mecevp.obj : error LNK2019: 无法解析的外部符号 _EVP_PKEY_encrypt_old,该符号在函数 _soap_mec_init 中被引用

    可能是在openssl库里找不到函数的定义,正确编译的方法如下:
    下载并安装per(网站见:http://www.activestate.com/activeperl),安装后目录自动加入系统变量。
    下载openssl(网址见:http://www.openssl.org/source/),运行"Visual Studio 2008 命令提示",以下步骤为编译release版本。
    1 打开命令行,进入openssl的目录,执行“perl Configure VC-WIN32 --prefix=c:/openssl”;
    2 执行“ms\do_ms”;
    3 执行“nmake -f ms\ntdll.mak”;
    4 执行 “nmake -f ms\ntdll.mak install”,到此编译完成,在c:/openssl目录下已经生成所需文件。
    如果要编译debug版,修改ms\do_ms.bat文件,在perl util\mk1mf.pl ,perl util\mkdef.pl后面加32。

    展开全文
  • Onvif开发

    2015-04-28 17:44:16
    一、 利用gsoap2.8.14生成Onvif相关源代码 1. 生成onvif.h头文件的方法 产生头文件有两种方法:链接网络生成和本地生成。 1) wsdl2h相关命令参数  -c 产生c语言的代码,否则产生C++  -s 不使用...

    转自 zsl461975543  收藏学习了,谢谢分享

    一、  利用gsoap2.8.14生成Onvif相关源代码

    1.        生成onvif.h头文件的方法

    产生头文件有两种方法:链接网络生成和本地生成。

    1)        wsdl2h相关命令参数

           -c   产生c语言的代码,否则产生C++

           -s   不使用STL代码

           -t   指定typemap.dat文件

           -o   指定生成的头文件名

    2)        链接网络生成

    l  将wsdl2.exe和typemap.dat文件放入同一个文件夹

    l  利用cmd或批处理执行以下dos命令:

    wsdl2h.exe  -c  -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.wsdlhttp://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdlhttp://www.onvif.org/onvif/ver10/analyticsdevice.wsdlhttp://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl http://www.onvif.org/onvif/ver10/deviceio.wsdlhttp://www.onvif.org/onvif/ver10/display.wsdlhttp://www.onvif.org/onvif/ver10/event/wsdl/event.wsdlhttp://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdlhttp://www.onvif.org/onvif/ver10/recording.wsdl http://www.onvif.org/onvif/ver10/replay.wsdlhttp://www.onvif.org/onvif/ver10/search.wsdlhttp://www.onvif.org/onvif/ver10/receiver.wsdlhttp://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl

    3)        下载到本地生成

    l  从ONVIF官网上把相关的WSDL文档下载到本地,下载地址(详细参见备注说明),此外还需下载样式表,下载地址见WSDL文档中的schemaLocation。

    l  将wsdl2.exe、typemap.dath、WSDL文档和样式表放入同一文件夹中。

    l  将相关WSDL文档中的样式表引入路径(schemaLocation)修改为本地实际地址,如:event.wsdl中schemaLocation="http://www.w3.org/2005/08/addressing/ws-addr.xsd修改为schemaLocation = ws-addr.xsd

    l  利用cmd或批处理执行以下命令

    wsdl2h.exe  -c  -s  -t  typemap.dat  -o  onvif.hremotediscovery.wsdldevicemgmt.wsdl analytics.wsdl analyticsdevice.wsdl media.wsdl deviceio.wsdldisplay.wsdl event.wsdl imaging.wsdl ecording.wsdl replay.wsdl search.wsdlreceiver.wsdl ptz.wsdl

    4)        备注说明

    l  wsdl2.exe位于gsoap_2.8.14\gsoap-2.8\gsoap\bin

    l  typemap.dat位于gsoap_2.8.14\gsoap-2.8\gsoap

    l  wsdl下载地址:http://www.onvif.org/Documents/Specifications.aspx

    l  各url之间用空格隔开

    l  typemap.dat不需要修改

    l  链接网络生成方法的优点是不用考虑以上文件对其它文件的依赖关系,不用修改引入路径。该方法的缺点跟网速有关,因此中途可能会中断,如果超过5分钟未生成,可重新执行命令, 通过代理上网则无法生成,不推荐用此方法。

    l  下载本地生成方法的优缺点和链接网络方法生成相反,代理网推荐使用此方法。

    2.        生成onvif源代码

    1)        整理相关的文件

    把刚生成的onvif.h与soapcpp2.exe、import和custom放入同一文件夹,其中:

    soapcpp2.exe位于gsoap_2.8.14\gsoap-2.8\gsoap\bin

    import位于gsoap_2.8.14\gsoap-2.8\gsoap

     custom位于gsoap_2.8.14\gsoap-2.8\gsoap    

    2)        通过以下命令生成相关源文件

    soapcpp2.exe-2 –c  onvif.h  -I import

    3)        Soapcpp2相关命令参数

       -2   采用SOAP1.2,

       -x   不产生xml文件(不推荐使用此命令,因为xml文档很有用)

       -I   为引入路径

       -C   只产生客户端代码(注意:C是大写)

    4)        备注说明

    l  需要在onvif.h中加入#import"wsse.h,用来做安全验证

    l  需要将import目录下的wsa5.h以下部分注释掉,否则编译时会报soap_xxxx_SOAP_ENV__Fault()函数重复定义。

    int SOAP_ENV__Fault

    ( _QName           faultcode,     // SOAP 1.1

                   char         *faultstring,       //SOAP 1.1

                   char         *faultactor,        //SOAP 1.1

                   struct SOAP_ENV__Detail  *detail,        // SOAP 1.1

                   struct SOAP_ENV__Code    *SOAP_ENV__Code,    // SOAP1.2

                  struct SOAP_ENV__Reason  *SOAP_ENV__Reason,  // SOAP 1.2

                  char         *SOAP_ENV__Node,    // SOAP 1.2

                  char         *SOAP_ENV__Role,    // SOAP 1.2

                  struct SOAP_ENV__Detail  *SOAP_ENV__Detail,  // SOAP 1.2

                 void);

     

     

     

     

     

    3.        利用gsoap2.8.8生成源代码和gsoap2.8.14生成的差异

    利用gsoap2.8.8生成源代码方法跟gsoap2.8.14基本一致,但需注意以下区别:

    1)        typemap.dat文件中需要添加相关信息

    tds    ="http://www.onvif.org/ver10/device/wsdl"

    tev    ="http://www.onvif.org/ver10/events/wsdl"

    tls    ="http://www.onvif.org/ver10/display/wsdl"

    tmd    ="http://www.onvif.org/ver10/deviceIO/wsdl"

    timg   ="http://www.onvif.org/ver20/imaging/wsdl"

    trt    ="http://www.onvif.org/ver10/media/wsdl"

    tptz   ="http://www.onvif.org/ver20/ptz/wsdl"

    trv    ="http://www.onvif.org/ver10/receiver/wsdl"

    trc    ="http://www.onvif.org/ver10/recording/wsdl"

    tse    ="http://www.onvif.org/ver10/search/wsdl"

    trp    ="http://www.onvif.org/ver10/replay/wsdl"

    tan    ="http://www.onvif.org/ver20/analytics/wsdl"

    tad    ="http://www.onvif.org/ver10/analyticsdevice/wsdl"

    tdn    ="http://www.onvif.org/ver10/network/wsdl"

    tt ="http://www.onvif.org/ver10/schema"

     

    #  OASISrecommended prefixes

    wsnt   ="http://docs.oasis-open.org/wsn/b-2"

    wsntw  ="http://docs.oasis-open.org/wsn/bw-2"

    wsrfbf ="http://docs.oasis-open.org/wsrf/bf-2"

    wsrfr  ="http://docs.oasis-open.org/wsrf/r-2"

    wsrfrw = "http://docs.oasis-open.org/wsrf/rw-2"

    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 

    2)        wsa5.h中无SOAP_ENV__Fault函数

    由于wsa5.h中没有SOAP_ENV__Fault因此不会产生代码重复,因此不用注释。

     

    二、新建工程,调试代码

    1.        新建一个项目

    将上面生成的soapH.h、soapStub.h、 wsdd.nsmap、soapC.c、soapClient.c,还有位于gsoap-2.8\gsoap 的:stdsoap2.c、stdsoap2.h和位于\custom中的:duration.c放入工程中,然后编写main函数,调试代码。

    2.        文件主要功能说明

    wsdd.nsmap     名空间定义,服务器端与客户端都要包含它,里面有很多,都是

           相同的,只需导入一个进入工程就行

    stdsoap2.h       Header _le of stdsoap2.cppruntime library

    stdsoap2.c       RuntimeC library with XML parser and run-time support routines soapStub.h       soapH.h        //Main header file to be included by all client and servicesources

    soapC.c        //Serializers and deserializers for the specfied datastructures

    soapClient.c    //Clientstub routines for remote operations  

    soapStub.h       Amodi_ed and annotated header file produced from the input header file

     

    三、设备发现main函数说明

    #include <iostream>

    #include "wsdd.nsmap"

    #include "soapH.h"

    using namespace std;

    int main()

    {

       /*****声明变量***********/

         structsoap *soap;              //soap环境变量

         structwsdd__ProbeType req;      //客户端发送的Probe

         struct__wsdd__ProbeMatches resp; //服务端回的Probematchs

         structwsdd__ScopesType sScope;   //Probe里面的范围

         structSOAP_ENV__Header header;   //SOAP的头

         intresult = 0;                    //返回值        

         int count = 0;                   //获得的设信息备个数

        

         /**获取guid(windows下叫guid,linux下叫uuid),格式为urn:uuid:8-4-4-4-12,由系统随机产生**/

         staticchar buf[64] = {0};   //用来保存guid号

       

         GUID guid;     /*声明guid为GUID结构体变量,包含4个变量,分别是

                         unsigned longData1;

                     unsigned short Data2;

                     unsigned short Data3;

                     unsigned char  Data4[ 8 ];

                            */

    if (S_OK== CoCreateGuid(&guid))    //如果guid生成成功,则将其转为字符串,保存在buf中

    {

           _snprintf(buf,sizeof(buf)

          ,"urn:uuid:%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X"

          , guid.Data1

          , guid.Data2

          , guid.Data3

          , guid.Data4[0], guid.Data4[1]

          , guid.Data4[2], guid.Data4[3], guid.Data4[4],guid.Data4[5]

          , guid.Data4[6], guid.Data4[7]

          );

         }

    soap = soap_new(); //初始化soap

        if(soap==NULL)

         {

            return -1;

         }   

         soap_set_namespaces(soap,namespaces);    //设置命名空间    

    soap->recv_timeout = 5;      //设置接收Probematchs时间,超过5秒钟没有数据就退出

    soap_default_SOAP_ENV__Header(soap,&header);   //将header设置为soap消息的头属性

    /*****给头赋值******/

         header.wsa__MessageID =buf;                     

         header.wsa__To="urn:schemas-xmlsoap-org:ws:2005:04:discovery";

         header.wsa__Action="http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";

         soap->header = &header;

         /*设置所需寻找设备的类型和范围,二者至少设定一个,否则可能收到非ONVIF设备,出现异常*/

         soap_default_wsdd__ScopesType(soap,&sScope);

         sScope.__item ="onvif://www.onvif.org";     //设置所需设备的sScope

         soap_default_wsdd__ProbeType(soap,&req);     

         req.Scopes = &sScope;

         req.Types ="tdn:NetworkVideoTransmitter";

         /*设置所需设备的类型,tdn为命名空间前缀,为wsdd.nsmap文件中{"tdn","http://www.onvif.org/ver10/network/wsdl"}的tdn,如过不是tdn,而是其它,如ns1这里也要随之改为ns1*/

     

         //通过组播发送Probe探针,发送成功返回0,否则-1

    result = soap_send___wsdd__Probe(soap,"soap.udp://239.255.255.250:3702", NULL, &req);

         if(result==-1)

         {

       cout<<"soap error:"<<soap->error<<soap_faultcode(soap)

    <<"---"<<soap_faultstring(soap)<<endl; 

         }else                  

         {

             do{    

                 result = soap_recv___wsdd__ProbeMatches(soap,&resp);

    //接收ProbeMatches,成功返回0,否则-1 

                  if (result==-1)   

                   {

                   cout<<"共发现"<<count<<"个设备"<<endl;

    cout<<"soap error:"<<soap->error<<soap_faultcode(soap)

    <<"---"<<soap_faultstring(soap)<<endl;

                    break;

                    }else  

                   {

                        count++;

                        cout<<"========================================="<<endl;              

                        cout<<"UUID:"<<""<<resp.wsdd__ProbeMatches->ProbeMatch->

    wsa__EndpointReference.Address<<endl;             

    cout<<"Type:"<<""<<resp.wsdd__ProbeMatches->ProbeMatch->Types<<endl;

                        cout<<"Scopes:"<<""<< resp.wsdd__ProbeMatches->

    ProbeMatch->Scopes->__item<<endl;                       

                        cout<<"DeviceService Address:"<<""<<resp.wsdd__ProbeMatches->

    ProbeMatch->XAddrs<<endl;                      

                        cout<<"MetadataVersion:"<<""<<resp.wsdd__ProbeMatches->

    ProbeMatch->MetadataVersion<<endl;

                    }

              }while(1);

         }                       

    /********清除变量************/

         soap_destroy(soap); // removedeserialized class instances (C++ only)

         soap_end(soap);         //clean up and remove deserialized data

         soap_done(soap);

         returnresult;

    }

    四、调试过程遇到的问题和注意事项

    1.        出现如下语法错误:

    error C2143:语法错误 : 缺少“{”(在“:”的前面)

    error C2059:语法错误 : “:”

    error C2143:语法错误 : 缺少“{”(在“:”的前面)

    需要将工程中的.c文件改成.cpp文件即可。

    2.   无法解析的外部命令错误soap_check_faultsubcode

    在stdsoap2.h中声明的soap_check_faultsubcode(structsoap *soap)函数在soapC.cpp中未实现, 可在soapC.cpp中添加如下实现:

    SOAP_FMAC3 const char * SOAP_FMAC4soap_check_faultsubcode(struct soap *soap)

    {

        soap_fault(soap);

        if(soap->version == 2)

        {  

    if(soap->fault->SOAP_ENV__Code &&soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode &&soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode)

    returnsoap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode->SOAP_ENV__Value;

            return NULL;

        }

        returnsoap->fault->faultcode;

    }

    3.        无法解析的外部命令错误soap_check_faultdetail

    在stdsoap2.h中声明的soap_check_faultdetail(struct soap *soap)函数在soapC.cpp中未实现, 可在soapC.cpp中添加如下实现:

    SOAP_FMAC3 const char * SOAP_FMAC4soap_check_faultdetail(struct soap *soap)

    {

        soap_fault(soap);

        if(soap->version == 2 && soap->fault->SOAP_ENV__Detail)

            returnsoap->fault->SOAP_ENV__Detail->__any;

        if(soap->fault->detail)

            return soap->fault->detail->__any;

        returnNULL;

    }

    4.        出现无法解析的外部符号_soap_in_xsd__duration

    无法解析的外部符号_soap_in_xsd__duration,该符号在函数_soap_getelement中被引用soapC.obj : error LNK2019: 无法解析的外部符号_soap_out_xsd__duration,该符号在函数_soap_putelement中被引用

    soapC.obj: error LNK2019: 无法解析的外部符号_soap_default_xsd__duration,该符号在函数_soap_default__tse__FindMetadata中被引用

    需要将\custom文件夹下面的duration.h和duration.c导入工程中。

    5.  在VS中出现fatal error C1128: 节数超过对象文件格式限制:请使用/bigobj 进行编译的错误

    这是由于源代码文件太大的原因,需添加选项/bigobj,在项目属性-> C/C++ ->命令行的附加选项中添加/bigobj。

    6.  如果是调用soap_call_XXXX_Probe()来实现设备发现时不能发现所有onvif设备

    该函数实现过程中只有一次接收过程,所以无法发现所有的设备的问题。如果使用该函数,还需要对函数的实现做以下更改:

    函数的接收部分,将原来的XXXX:Response该为YYYY:ProbeMatches,

    其中XXXX是.nsmap文件中http://www.onvif.org/ver10/network/wsdl"所对应的命名空间前缀,YYYY与后面YYYY:ProbeMatchesType中的前缀相同,都是http://schemas.xmlsoap.org/ws/2005/04/discovery所对应的命名空间前缀名。

    7.  抓包实验问题

    利用gsoap生成的wsdd.namsp如下:

    #include "soapH.h"

    SOAP_NMAC struct Namespace namespaces[] =

    {

             {"SOAP-ENV","http://schemas.xmlsoap.org/soap/envelope/","http://www.w3.org/*/soap-envelope", NULL},

             {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/","http://www.w3.org/*/soap-encoding", NULL},

             {"xsi","http://www.w3.org/2001/XMLSchema-instance","http://www.w3.org/*/XMLSchema-instance", NULL},

             {"xsd","http://www.w3.org/2001/XMLSchema","http://www.w3.org/*/XMLSchema", NULL},

             {"wsa","http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL, NULL},

             {"wsdd","http://schemas.xmlsoap.org/ws/2005/04/discovery", NULL, NULL},

             {"chan","http://schemas.microsoft.com/ws/2005/02/duplex", NULL, NULL},

             {"wsa5","http://www.w3.org/2005/08/addressing","http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL},

             {"xmime","http://tempuri.org/xmime.xsd", NULL, NULL},

             {"xop","http://www.w3.org/2004/08/xop/include", NULL, NULL},

             {"tt","http://www.onvif.org/ver10/schema", NULL, NULL},

             {"wsrfbf","http://docs.oasis-open.org/wsrf/bf-2", NULL, NULL},

             {"wstop","http://docs.oasis-open.org/wsn/t-1", NULL, NULL},

             {"wsrfr","http://docs.oasis-open.org/wsrf/r-2", NULL, NULL},

             {"tad","http://www.onvif.org/ver10/analyticsdevice/wsdl", NULL, NULL},

             {"tan","http://www.onvif.org/ver20/analytics/wsdl", NULL, NULL},

             {"tdn","http://www.onvif.org/ver10/network/wsdl", NULL, NULL},

             {"tds","http://www.onvif.org/ver10/device/wsdl", NULL, NULL},

             {"tev","http://www.onvif.org/ver10/events/wsdl", NULL, NULL},

             {"wsnt","http://docs.oasis-open.org/wsn/b-2", NULL, NULL},

             {"timg","http://www.onvif.org/ver20/imaging/wsdl", NULL, NULL},

             {"tls","http://www.onvif.org/ver10/display/wsdl", NULL, NULL},

             {"tmd","http://www.onvif.org/ver10/deviceIO/wsdl", NULL, NULL},

             {"tptz","http://www.onvif.org/ver20/ptz/wsdl", NULL, NULL},

             {"trc","http://www.onvif.org/ver10/recording/wsdl", NULL, NULL},

             {"trp","http://www.onvif.org/ver10/replay/wsdl", NULL, NULL},

             {"trt","http://www.onvif.org/ver10/media/wsdl", NULL, NULL},

             {"trv","http://www.onvif.org/ver10/receiver/wsdl", NULL, NULL},

             {"tse","http://www.onvif.org/ver10/search/wsdl", NULL, NULL},

             {NULL,NULL, NULL, NULL}

    };

     

     

     

     

    1)通过编写面函数之后,调试运行结果如下:

     

    其中http://192.168.106.112:80/onvif/device_service为本地模拟的设备

     

    通过抓包工具获得信息如下:

     

    2).保留以下命名空间,删除其它信息:

    #include "soapH.h"

    SOAP_NMAC struct Namespace namespaces[] =

    {

             {"SOAP-ENV","http://schemas.xmlsoap.org/soap/envelope/","http://www.w3.org/*/soap-envelope", NULL},

             {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/","http://www.w3.org/*/soap-encoding", NULL},

             {"xsi","http://www.w3.org/2001/XMLSchema-instance","http://www.w3.org/*/XMLSchema-instance", NULL},

             {"xsd","http://www.w3.org/2001/XMLSchema","http://www.w3.org/*/XMLSchema", NULL},

             {"wsa","http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL, NULL},

             {"wsdd","http://schemas.xmlsoap.org/ws/2005/04/discovery", NULL, NULL},

    {"wsa5","http://www.w3.org/2005/08/addressing","http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL},

             {"xmime","http://tempuri.org/xmime.xsd", NULL, NULL},

             {"xop","http://www.w3.org/2004/08/xop/include", NULL, NULL},

             {"tt","http://www.onvif.org/ver10/schema", NULL, NULL},

             {NULL,NULL, NULL, NULL}

    };

    调试运行结果如下:

     

    抓包工具抓到信息如下:

     

     

    3)测试工具信息如下

    抓包信息如下:

     

    4)多次实验显示:

    wsdd.namsp文件太大时,将会被拆包,192.168.106.164将始终不会回消息,减小命名空间大小,保证只发送一个UDP包,192.168.106.164将始终能回消息

     

    5) 通过抓包发现,做设备管理功能时客户端已能构与设备端通信,只是涉及到安全,设备端没有返回信息

     

    6)在程序运行时,可能会出现一下信息

    这是由于Type和Scopes都没有赋值,接收了非ONVIF的设备

    它的body中没有我们需要的值,所以在输出时会引起中断

     

     

     

     

     

     

    五、经验总结

    1.        对于利用gsoap工具实现基于ONVIF标准的功能,尽量按照如下顺序:

    Ø  了解所需实现的功能原理,参考<<ONVIF_Core_Specification,_version_2.0.pdf>>

    Ø  了解gsoap工具的使用方法和编程方法,还有文件结构,参考<<gSOAP 2.8.14 User Guide>>,位于gsoap_2.8.14\gsoap-2.8\gsoap\doc\soapdoc2.pdf里面,里面内容很多,可根据需要查找相关内容,如The wsdl2h WSDL and Schema Importer(84), Using thesoapcpp2 Compiler and Code Generator(89)SOAP Header Processing(178页),SOAP/XML Over UDP(208页)

    Ø  根据所需实现的功能查看对应的xml文档(生成源代码时产生的,)因为生成的xml文档是客户端和服务端通信时所发送的模板结构,通过它可以了解编码时所需要填充的信息

    Ø  了解工程中.h和.cpp的功能

    Ø  查看别人写的例子,理解原理,要学会从原理上去分析碰到的问题并解决问题

    Ø  自己写代码验证,事实求是,替自己负责,替用户负责。

    2.        善于利用抓包工具

    从原理上分析问题,能大大提高效率,如果利用测试工具跟客户端通信,然后进行抓包,能构很好的分析出客户端需发送的消息,服务端回的消息,非常利于编码。

    展开全文
  • onvif 开发

    2015-07-24 10:57:21
    ONVIF Profile S Specification文档描述了Device或者说DVT和Client可以使用的一种Profile,Profile这个词在计算机领域非常常见,我们可以理解成一种方案、配置、框架等。 文档里描述了如果实现VideoStream,...


    ONVIF Profile S Specification文档描述了Device或者说DVT和Client可以使用的一种Profile,Profile这个词在计算机领域非常常见,我们可以理解成一种方案、配置、框架等。

    文档里描述了如果实现VideoStream,device和client应该具备的条件,当然如果实现文档的所有条件,就可以说该设备符合Profile S

    如果单纯实现VideoStream,只需完成下列命令。

    [plain]  view plain copy
    1. 1、GetProfiles  
    2. 2、GetStreamUri   
    3. 填充rtsp路径,例如:rtsp://192.168.1.201/petrov.m4e  
    4. 3、Media Streaming using RTSP  
    5. 这里使用开源的live555,完成rtsp功能  
    6. 4、GetVideoEncoderConfiguration  
    7. 5、GetVideoEncoderConfigurationOptions  
    8. 6、GetCapabilities  
    9. NVC为了获取DVT所支持的功能的命令  

    参考文档:

    [plain]  view plain copy
    1. 1、ONVIF Profile S Specification  
    2. 描述ProfileS是什么样的一个东西,如何实现  
    3. 2、Reference_of_ONVIF_Development_v1.01.02  
    4. Onvif DVT设计参考,指明了一条道路,但没有具体内容  
    5. 3、ONVIF-Media-Service-Spec-v220  
    6. Onvif Media的说明介绍  
    7. 4、http://www.onvif.org/onvif/ver20/util/operationIndex.html  
    8. onvif几乎全部命令的详细说明,非常重要。该文档告诉我们结构体成员的意义和如何填充。Onvif开发其实就是各种结构体的填充。  

    一、产生onvif源码框架

    1、从wsdl生成C头文件

    [cpp]  view plain copy
    1. wsdl2h -o onvif.h -c -s -t .\typemap.dat http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl http://www.onvif.org/onvif/ver10/display.wsdl http://www.onvif.org/onvif/ver10/deviceio.wsdl http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl  http://www.onvif.org/onvif/ver10/receiver.wsdl http://www.onvif.org/onvif/ver10/recording.wsdl  http://www.onvif.org/onvif/ver10/search.wsdl http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl http://www.onvif.org/onvif/ver10/replay.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/schema/onvif.xsd  http://www.onvif.org/ver10/actionengine.wsdl  
    跟前一篇discovery唯一不同的是,这里多了很多wsdl文件,这次创建完整的onvif代码框架

    2、从头文件生成源码框架

    [cpp]  view plain copy
    1. soapcpp2 -c onvif.h -x -I /root/onvif/gsoap-2.8/gsoap/import -I /root/onvif/gsoap-2.8/gsoap/  
    产生的C文件比较庞大,最大的有十几兆,大部分的内容没有复用导致。

    二、创建soap运行环境

    [cpp]  view plain copy
    1. int main(int argc, char **argv)    
    2. {    
    3.     int m, s;    
    4.     struct soap add_soap;    
    5.     int server_udp;  
    6.   
    7.     server_udp = create_server_socket_udp();  
    8.     //bind_server_udp1(server_udp);  
    9.     pthread_t thrHello;  
    10.     pthread_t thrProbe;  
    11.     //pthread_create(&thrHello,NULL,main_Hello,server_udp);  
    12.     //sleep(2);  
    13.     pthread_create(&thrProbe,NULL,main_Probe,server_udp);  
    14.   
    15.     soap_init(&add_soap);    
    16.     soap_set_namespaces(&add_soap, namespaces);    
    17.   
    18.   
    19.     if (argc < 0) {    
    20.         printf("usage: %s <server_port> \n", argv[0]);    
    21.         exit(1);    
    22.     } else {    
    23.         m = soap_bind(&add_soap, NULL, 80, 100);    
    24.         if (m < 0) {    
    25.             soap_print_fault(&add_soap, stderr);    
    26.             exit(-1);    
    27.         }    
    28.         fprintf(stderr, "Socket connection successful: master socket = %d\n", m);    
    29.         for (;;) {    
    30.             s = soap_accept(&add_soap);    
    31.             if (s < 0) {    
    32.                 soap_print_fault(&add_soap, stderr);    
    33.                 exit(-1);    
    34.             }    
    35.             fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);    
    36.             soap_serve(&add_soap);    
    37.             soap_end(&add_soap);    
    38.         }    
    39.     }    
    40.     return 0;    
    41. }   
    注意,这里绑定了80端口,onvif使用的是http请求,然后附带xml,其实正常的是将onvif集成到web服务器中,普通的http请求有web服务器处理,onvif的http请求则有soap处理。我们这里的做法也可行,只不过onvif的访问web服务器的功能是无法使用的。

    三、RTSP视频对接

    1、实现GetCapabilities命令

    客户端发送GetCapabilities命令来得到设备端的能力,然后依据GetCapabilities返回的结果再来进行下一步操作

    在__tds__GetCapabilities函数中我们只需要填充Media部分和一些必要的即可

    [cpp]  view plain copy
    1. //想要对接RTSP视频,必须设置Media  
    2. tds__GetCapabilitiesResponse->Capabilities->Media = (struct tt__MediaCapabilities*)soap_malloc(soap, sizeof(struct tt__MediaCapabilities));  
    3. tds__GetCapabilitiesResponse->Capabilities->Media->XAddr = (char *) soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);  
    4. strcpy(tds__GetCapabilitiesResponse->Capabilities->Media->XAddr, _IPv4Address);  
    5. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities = (struct tt__RealTimeStreamingCapabilities*)soap_malloc(soap, sizeof(struct tt__RealTimeStreamingCapabilities));  
    6. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = (int *)soap_malloc(soap, sizeof(int));   
    7. *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = _false;     
    8. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = (int *)soap_malloc(soap, sizeof(int));  
    9. *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = _true;     
    10. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = (int *)soap_malloc(soap, sizeof(int));  
    11. *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = _true;      
    12. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->Extension = NULL;  
    13. tds__GetCapabilitiesResponse->Capabilities->Media->Extension = NULL;  
    14. tds__GetCapabilitiesResponse->Capabilities->Media->__size = 0;  
    15. tds__GetCapabilitiesResponse->Capabilities->Media->__any = 0;  
    另外必要填充的还有

    [cpp]  view plain copy
    1. //下面的重要,这里只实现视频流,需要设置VideoSources  
    2. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->VideoSources = TRUE;  
    3. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->VideoOutputs = FALSE;  
    4. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->AudioSources = FALSE;  
    5. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->AudioOutputs = FALSE;  
    6. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->RelayOutputs = FALSE;  
    7. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->__size = 0;  
    8. tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->__any = NULL;  
    9.   
    10. tds__GetCapabilitiesResponse->Capabilities->Extension->Display = NULL;  
    11. tds__GetCapabilitiesResponse->Capabilities->Extension->Recording = NULL;  
    12. tds__GetCapabilitiesResponse->Capabilities->Extension->Search = NULL;  
    13. tds__GetCapabilitiesResponse->Capabilities->Extension->Replay = NULL;  
    14. tds__GetCapabilitiesResponse->Capabilities->Extension->Receiver = NULL;  
    15. tds__GetCapabilitiesResponse->Capabilities->Extension->AnalyticsDevice = NULL;  
    16. tds__GetCapabilitiesResponse->Capabilities->Extension->Extensions = NULL;  
    17. tds__GetCapabilitiesResponse->Capabilities->Extension->__size = 0;  
    18. tds__GetCapabilitiesResponse->Capabilities->Extension->__any = NULL;  

    2、实现GetServices命令

    [cpp]  view plain copy
    1. int  __tds__GetServices(struct soap* soap, struct _tds__GetServices *tds__GetServices, struct _tds__GetServicesResponse *tds__GetServicesResponse)  
    2. {  
    3.     DBG("__tds__GetServices\n");  
    4.     /*该函数很必要*/  
    5.     char _IPAddr[INFO_LENGTH];  
    6.     int i = 0;  
    7.     sprintf(_IPAddr, "http://%03d.%03d.%03d.%03d/onvif/services", 192, 168, 1, 233);  
    8.     tds__GetServicesResponse->__sizeService = 1;  
    9.   
    10.     tds__GetServicesResponse->Service = (struct tds__Service *)soap_malloc(soap, sizeof(struct tds__Service));  
    11.     tds__GetServicesResponse->Service[0].XAddr = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);  
    12.     tds__GetServicesResponse->Service[0].Namespace = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);  
    13.     strcpy(tds__GetServicesResponse->Service[0].Namespace, "http://www.onvif.org/ver10/events/wsdl");  
    14.     strcpy(tds__GetServicesResponse[0].Service->XAddr, _IPAddr);  
    15.     tds__GetServicesResponse->Service[0].Capabilities = NULL;  
    16.     tds__GetServicesResponse->Service[0].Version = (struct tt__OnvifVersion *)soap_malloc(soap, sizeof(struct tt__OnvifVersion));  
    17.     tds__GetServicesResponse->Service[0].Version->Major = 0;  
    18.     tds__GetServicesResponse->Service[0].Version->Minor = 3;  
    19.     tds__GetServicesResponse->Service[0].__any = (char **)soap_malloc(soap, sizeof(char *));  
    20.     tds__GetServicesResponse->Service[0].__any[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);  
    21.     strcpy(tds__GetServicesResponse->Service[0].__any[0],"why1");  
    22.     tds__GetServicesResponse->Service[0].__any[1] = (char *)soap_malloc(soap,sizeof(char) * INFO_LENGTH);  
    23.     strcpy(tds__GetServicesResponse->Service[0].__any[1],"why2");  
    24.     tds__GetServicesResponse->Service[0].__size = NULL;  
    25.     tds__GetServicesResponse->Service[0].__anyAttribute = NULL;  
    26.     return SOAP_OK;  
    27. }  

    3、实现GetVideoSources命令

    [html]  view plain copy
    1. int  __tmd__GetVideoSources(struct soap* soap, struct _trt__GetVideoSources *trt__GetVideoSources, struct _trt__GetVideoSourcesResponse *trt__GetVideoSourcesResponse)  
    2. {  
    3.     DBG("__tmd__GetVideoSources\n");  
    4.   
    5.     int size1;  
    6.     size1 = 1;  
    7.     trt__GetVideoSourcesResponse->__sizeVideoSources = size1;  
    8.     trt__GetVideoSourcesResponse->VideoSources = (struct tt__VideoSource *)soap_malloc(soap, sizeof(struct tt__VideoSource) * size1);  
    9.     trt__GetVideoSourcesResponse->VideoSources[0].Framerate = 30;  
    10.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));  
    11.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Height = 720;  
    12.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Width = 1280;  
    13.     trt__GetVideoSourcesResponse->VideoSources[0].token = (char *)soap_malloc(soap, sizeof(char)*INFO_LENGTH);  
    14.     strcpy(trt__GetVideoSourcesResponse->VideoSources[0].token,"GhostyuSource_token"); //注意这里需要和GetProfile中的sourcetoken相同  
    15.   
    16.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging =(struct tt__ImagingSettings*)soap_malloc(soap, sizeof(struct tt__ImagingSettings));  
    17.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness = (float*)soap_malloc(soap,sizeof(float));  
    18.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness[0] = 128;  
    19.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation = (float*)soap_malloc(soap,sizeof(float));  
    20.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation[0] = 128;  
    21.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast = (float*)soap_malloc(soap,sizeof(float));  
    22.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast[0] = 128;  
    23.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = (int *)soap_malloc(soap,sizeof(int));  
    24.     *trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = 0;   
    25.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness = (float*)soap_malloc(soap,sizeof(float));  
    26.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness[0] = 128;  
    27.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation = (struct tt__BacklightCompensation*)soap_malloc(soap, sizeof(struct tt__BacklightCompensation));  
    28.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Mode = 0;  
    29.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Level = 20;  
    30.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Exposure = NULL;  
    31.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Focus = NULL;  
    32.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange = (struct tt__WideDynamicRange*)soap_malloc(soap, sizeof(struct tt__WideDynamicRange));  
    33.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Mode = 0;     
    34.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Level = 20;  
    35.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance = (struct tt__WhiteBalance*)soap_malloc(soap, sizeof(struct tt__WhiteBalance));  
    36.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->Mode = 0;   
    37.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CrGain = 0;   
    38.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CbGain = 0;   
    39.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Extension = NULL;  
    40.     trt__GetVideoSourcesResponse->VideoSources[0].Extension = NULL;    
    41.     return SOAP_OK;  
    42. }  
    __tmd__GetVideoSources最重要的是token的填充,必须要和下面profile中的sourcetoken相同,需要匹配到这个视频源

    4、实现GetProfiles命令

    [cpp]  view plain copy
    1. size = 1;  
    2. trt__GetProfilesResponse->Profiles =(struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile) * size);  
    3. trt__GetProfilesResponse->__sizeProfiles = size;  
    4.   
    5. i=0;  
    6. trt__GetProfilesResponse->Profiles[i].Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    7. strcpy(trt__GetProfilesResponse->Profiles[i].Name,"my_profile");  
    8. trt__GetProfilesResponse->Profiles[i].token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    9. strcpy(trt__GetProfilesResponse->Profiles[i].token,"token_profile");  
    10. trt__GetProfilesResponse->Profiles[i].fixed = _false;  
    11. trt__GetProfilesResponse->Profiles[i].__anyAttribute = NULL;  
    除了上面的基本信息,还需要填充两大项:VideoSourceConfiguration和VideoEncoderConfiguration,一个用于描述视频源的信息,另外一个描述视频的编码信息

    先给VideoSourceConfiguration分配空间

    [cpp]  view plain copy
    1. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration = (struct tt__VideoSourceConfiguration *)soap_malloc(soap,sizeof(struct tt__VideoSourceConfiguration ));  
    2. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    3. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    4. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    5. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds = (struct tt__IntRectangle *)soap_malloc(soap,sizeof(struct tt__IntRectangle));  
    然后在填充它

    [cpp]  view plain copy
    1. /*注意SourceToken*/  
    2. strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name,"VS_Name");  
    3. strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token,"VS_Token");  
    4. strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken,"GhostyuSource_token"); /*必须与__tmd__GetVideoSources中的token相同*/  
    5. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->UseCount = 1;  
    6. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->x = 1;  
    7. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->y = 1;  
    8. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->height = 720;  
    9. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->width = 1280;  
    如果是指针必须先用soap_malloc分配内存,然后才能赋值

    下面是VideoEncoderConfiguration

    [cpp]  view plain copy
    1. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration = (struct tt__VideoEncoderConfiguration *)soap_malloc(soap,sizeof(struct tt__VideoEncoderConfiguration));  
    2. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    3. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    4. strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name,"VE_Name1");  
    5. strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token,"VE_token1");  
    6. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->UseCount = 1;  
    7. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Quality = 10;  
    8. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Encoding = 1;//JPEG = 0, MPEG4 = 1, H264 = 2;  
    9. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));  
    10. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Height = 720;  
    11. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Width = 1280;  
    12. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl = (struct tt__VideoRateControl *)soap_malloc(soap, sizeof(struct tt__VideoRateControl));  
    13. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->FrameRateLimit = 30;  
    14. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->EncodingInterval = 1;  
    15. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->BitrateLimit = 500;  

    5、GetVideoSourceConfiguration和GetVideoEncoderConfiguration

    [cpp]  view plain copy
    1. int  __trt__GetVideoSourceConfiguration(struct soap* soap, struct _trt__GetVideoSourceConfiguration *trt__GetVideoSourceConfiguration, struct _trt__GetVideoSourceConfigurationResponse *trt__GetVideoSourceConfigurationResponse)  
    2. {  
    3.     DBG("__trt__GetVideoSourceConfiguration\n");  
    4.     //该函数必要,live video需要  
    5.     return SOAP_OK;  
    6. }  
    7.   
    8. int  __trt__GetVideoEncoderConfiguration(struct soap* soap, struct _trt__GetVideoEncoderConfiguration *trt__GetVideoEncoderConfiguration, struct _trt__GetVideoEncoderConfigurationResponse *trt__GetVideoEncoderConfigurationResponse)  
    9. {  
    10.     DBG("__trt__GetVideoEncoderConfiguration\n");  
    11.     return SOAP_OK;  
    12. }  

    6、GetVideoEncoderConfigurationOptions

    [cpp]  view plain copy
    1. int  __trt__GetVideoEncoderConfigurationOptions(struct soap* soap, struct _trt__GetVideoEncoderConfigurationOptions *trt__GetVideoEncoderConfigurationOptions, struct _trt__GetVideoEncoderConfigurationOptionsResponse *trt__GetVideoEncoderConfigurationOptionsResponse)  
    2. {  
    3.     DBG("__trt__GetVideoEncoderConfigurationOptions\n");  
    4.     //该函数必要,video streaming需要  
    5.     return SOAP_OK;  
    6. }  
    以上5、6不分的代码直接返回SOAP_OK即可,正常来说是应该填充的,这里不影响RTSP Video Stream,暂时就不去动它

    四、运行live555MediaServer服务器

    live555官网有很多测试文件,我这里用的是MPEG4的测试文件路劲为rtsp://192.168.1.201/petrov.m4e

    五、启动Onvif Device Manager测试

    有一个问题,OnvifDeviceManager的并不能自动发现设备(OnvifTestTool可以),还好它提供了手动添加功能

    单击add,添加如下内容:http://192.168.1.233/onvif/device_service

    注意,我在程序中固定了两个IP:linux192.168.1.233,windows:192.168.1.201,这里需看情况修改

    测试截图:

    1、Live video


    2、Video streaming


    3、Profiles


    最后是运行的live555 rtsp服务器


    终端打印的DEBUG信息


    展开全文
  • Onvif开发框架

    2016-04-10 22:36:43
    Onvif开发框架(C++)
  • Onvif 开发框架

    2016-04-14 10:54:20
    Onvif 开发框架,下载可用,当然,这是无鉴权方式,鉴权方式不难,在文档中的ONVIF.H中加import"wsse.h",现将生产框架,与所需WSDL全部上传
  • Onvif开发介绍

    2014-10-13 17:11:45
    用于指导NVR解决方案中的Onvif开发,介绍Onvif、WSDL、SOAP等基本概念,讲述开发的流程及各种文件的来源,为后续的开发及维护人员提供理论支持。
  • ONVIF开发总结

    2013-05-20 17:46:26
    ONVIF开发进行了简单的总结和分析,文中包括利用gsoap2.8.14生成Onvif相关源代码、调试代码、设备发现main函数说明、调试过程遇到的问题和注意事项
  • ONVIF开发经验总结

    2014-02-18 10:35:16
    ONVIF开发经验总结 很好的资料 适合 入门开发 很好的资料
  • Onvif开发总结

    2014-11-20 11:13:02
  • ONVIF开发步骤

    热门讨论 2011-12-17 13:49:40
    这个是本人开发ONVIF的一些开发步骤,根据文档基本能明白ONVIF开发流程!
  • onvif 开发摘要

    2020-05-10 10:35:06
    对应onvif开发,步骤比较啰嗦。常规流程是: 1.下载gsoap工具 2.利用gsoap中wsdl2h在线生成头文件或者离线生成头文件。 1)在线生成头文件,但因为自带的wsdl2h.exe工具不支持https,需要自己编译一个windows版本...
  • Onvif开发框架(C++)带鉴权
  • onvif开发discovery

    热门讨论 2013-12-26 20:29:43
    onvif客户端开发之搜索功能源码!已经经过验证,可以参考我的博客来开发
  • onvif开发总结

    2017-03-15 11:26:00
    ONVIF开发经验总结     ONVIF开发经验总结....................................................................................................... 1 一、 利用gsoap2.8.14生成Onvif相关源代码...........
  • onvif开发的一些总结

    2019-02-18 00:21:26
    是帮助一些刚接触监控开发,或者想了解onvif开发的朋友。 具体如何开发,不打算在这篇文章中详细说,后面有时间会更新。 这里主要介绍一些概念,以及一些常见的问题及解决思路99。 主要是用gsoap工具生成整体的...
  • Onvif开发框架(C++)带鉴权.rar Onvif开发框架(C++)带鉴权.rar
  • onvif开发之linux下discovery功能的实现 无bug,功能完备,有很好的借鉴意义!
  • 这里写自定义目录标题ONVIF开发过程中测试IPC遇到的问题目前测试通过的设备客户端与设备处于同一网段仍无法发现设备?客户端无法发现设备,但是可以在已知IP地址和用户名密码的情况下对IPC进行操作?客户端可以发现...
  • onvif开发中文

    2014-03-17 10:45:57
    onvif规范简介及开发 中文介绍,里面主要包含了协议规范的链接,开发详解的链接。
  • onvif开发了解webservice与wsdl的关系入门的好文章
  • 2.onvif开发流程

    2018-04-23 10:19:42
    2.onvif开发流程发现设备 &gt;&gt; 获取能力 &gt;&gt; 获取媒体信息 &gt;&gt; 获取视频编码配置 &gt;&gt; 设置视频编码配置 &gt;&gt; 获取URI &gt;&gt; ONVIF完成 ...
  • onvif开发离不开gsoap工具,官网

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,040
精华内容 816
关键字:

onvif开发