8-Onvif协议:IPC客户端之获取实时预览的url地址

参考文章

https://blog.csdn.net/zhizhengguan/article/details/109387400

https://blog.csdn.net/benkaoya/article/details/72486624

一、简介

​ ONVIF规范中设备管理和控制部分所定义的接口均以Web Services的形式提供,而音视频流则通过RTP/RTSP进行。简单粗暴的理解:IPC的各种参数获取/配置都是通过ONVIF协议接口实现,而音视频流多媒体传输采用的是RTP/RTSP协议实现。要读取IPC的音视频流,概况起来是,先通过ONVIF接口获取IPC主/辅码流的RTSP地址,再利用FFmpeg接口(或其他开源方案)读取音视频流数据。
ONVIF协议接口在media.wsdl,文件地址为https://www.onvif.org/ver10/media/wsdl/media.wsdl
在这里插入图片描述

​ Onvif协议对前端摄像头的取流是通过标准RTSP协议,因此我们就需要通过Onvif协议获取到需要预览摄像头的RTSP的地址,将拿到的RTSP通过VLC或者其他的RTSP客户端取流预览前端摄像头。实现的功能如下图所示:

在这里插入图片描述

形如rtsp://192.168.1.137:554/stream1

二、获取实时预览url地址的流程

  1. 通过「设备发现」,得到 「设备服务地址」。
  2. 使用「设备服务地址」调用ONVIF_GetMediaCapabilities接口,得到「媒体服务地址」。
  3. 使用「媒体服务地址」调用ONVIF_GetMediaProfilesToken接口,得到主次码流的「媒体配置信息」,其中包含ProfileToken。
  4. 根据获取到的token调用对应的接口获取到RTSP地址。
  5. 获取到RTSP地址之后我们就可以用opencv或者ffmeg之类的看实时视频了。

注:获取的token包含了主码流、辅码流的token已经各种配置的token,可以根据自己需要自取;根据主、辅码流的toekn获取到的是对应主、辅码流的RTSP地址。主、辅码流的RTSP地址不同,但是差异可能不大。


VLC播放RTSP视频
RTSP是很成熟的多媒体传输协议,用于传输音视频流数据。我们不需要自己写代码来实现RTSP协议,有很多现成的开源方案可供我们使用,比如强大的FFmpeg。为了让大家对RTSP有个更好的认识,下面使用VLC media player播放RTSP视频流。

打开VLC media player播放器(我的版本是VLC media player 2.1.3)。

选择菜单【媒体】>【打开网络串流】,输入RTSP地址,点击【播放】,即可实时播放视频流媒体,如下图所示。

在这里插入图片描述
在这里插入图片描述

如果提示认证失败,那么URL就要加上用户名、密码,格式如:rtsp://username:password@100.100.100.5:554/av0_0


三、数据结构和函数

生成gSOAP框架的代码,项目文件结构和解决编译报错可以参考佬的这篇文章:

https://blog.csdn.net/zhizhengguan/article/details/109387400

1.数据结构

# 数据类型定义在client\application\soapStub.h

tt__StreamSetup              ttStreamSetup;
tt__Transport                ttTransport;
_trt__GetStreamUri           req;
_trt__GetStreamUriResponse   rep;
/* ../onvif_head/onvif.h:996 */
#ifndef SOAP_TYPE_tt__StreamSetup
#define SOAP_TYPE_tt__StreamSetup (734)
/* complex XML schema type 'tt:StreamSetup': */
class SOAP_CMAC tt__StreamSetup : public soap_dom_element {
      public:
        /// Required element 'tt:Stream' of XML schema type 'tt:StreamType'
        enum tt__StreamType Stream;
        /// Required element 'tt:Transport' of XML schema type 'tt:Transport'
        tt__Transport *Transport;
      public:
        /// Return unique type id SOAP_TYPE_tt__StreamSetup
        virtual long soap_type(void) const { return SOAP_TYPE_tt__StreamSetup; }
        /// (Re)set members to default values
        virtual void soap_default(struct soap*);
        /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures
        virtual void soap_serialize(struct soap*) const;
        /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK
        virtual int soap_put(struct soap*, const char *tag, const char *type) const;
        /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK
        virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;
        /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error
        virtual void *soap_get(struct soap*, const char *tag, const char *type);
        /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error
        virtual void *soap_in(struct soap*, const char *tag, const char *type);
        /// Return a new object of type tt__StreamSetup, default initialized and not managed by a soap context
        virtual tt__StreamSetup *soap_alloc(void) const { return SOAP_NEW_UNMANAGED(tt__StreamSetup); }
      public:
        /// Constructor with default initializations
        tt__StreamSetup() : Stream(), Transport() { }
        /// Destructor
        virtual ~tt__StreamSetup() { }
        /// Friend allocator used by soap_new_tt__StreamSetup(struct soap*, int)
        friend SOAP_FMAC1 tt__StreamSetup * SOAP_FMAC2 soap_instantiate_tt__StreamSetup(struct soap*, int, const char*, const char*, size_t*);
};
#endif

/* ../onvif_head/onvif.h:998 */
#ifndef SOAP_TYPE_tt__Transport
#define SOAP_TYPE_tt__Transport (735)
/* Type tt__Transport is a recursive data type, (in)directly referencing itself through its (base or derived class) members */
/* complex XML schema type 'tt:Transport': */
class SOAP_CMAC tt__Transport : public soap_dom_element {
      public:
        /// Required element 'tt:Protocol' of XML schema type 'tt:TransportProtocol'
        enum tt__TransportProtocol Protocol;
        /// Optional element 'tt:Tunnel' of XML schema type 'tt:Transport'
        tt__Transport *Tunnel;
      public:
        /// Return unique type id SOAP_TYPE_tt__Transport
        virtual long soap_type(void) const { return SOAP_TYPE_tt__Transport; }
        /// (Re)set members to default values
        virtual void soap_default(struct soap*);
        /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures
        virtual void soap_serialize(struct soap*) const;
        /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK
        virtual int soap_put(struct soap*, const char *tag, const char *type) const;
        /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK
        virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;
        /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error
        virtual void *soap_get(struct soap*, const char *tag, const char *type);
        /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error
        virtual void *soap_in(struct soap*, const char *tag, const char *type);
        /// Return a new object of type tt__Transport, default initialized and not managed by a soap context
        virtual tt__Transport *soap_alloc(void) const { return SOAP_NEW_UNMANAGED(tt__Transport); }
      public:
        /// Constructor with default initializations
        tt__Transport() : Protocol(), Tunnel() { }
        /// Destructor
        virtual ~tt__Transport() { }
        /// Friend allocator used by soap_new_tt__Transport(struct soap*, int)
        friend SOAP_FMAC1 tt__Transport * SOAP_FMAC2 soap_instantiate_tt__Transport(struct soap*, int, const char*, const char*, size_t*);
};
#endif

/* ../onvif_head/onvif.h:2146 */
#ifndef SOAP_TYPE__trt__GetStreamUri
#define SOAP_TYPE__trt__GetStreamUri (1309)
/* complex XML schema type 'trt:GetStreamUri': */
class SOAP_CMAC _trt__GetStreamUri {
      public:
        /// Required element 'trt:StreamSetup' of XML schema type 'tt:StreamSetup'
        tt__StreamSetup *StreamSetup;
        /// Required element 'trt:ProfileToken' of XML schema type 'tt:ReferenceToken'
        char *ProfileToken;
        /// Context that manages this object
        struct soap *soap;
      public:
        /// Return unique type id SOAP_TYPE__trt__GetStreamUri
        virtual long soap_type(void) const { return SOAP_TYPE__trt__GetStreamUri; }
        /// (Re)set members to default values
        virtual void soap_default(struct soap*);
        /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures
        virtual void soap_serialize(struct soap*) const;
        /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK
        virtual int soap_put(struct soap*, const char *tag, const char *type) const;
        /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK
        virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;
        /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error
        virtual void *soap_get(struct soap*, const char *tag, const char *type);
        /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error
        virtual void *soap_in(struct soap*, const char *tag, const char *type);
        /// Return a new object of type _trt__GetStreamUri, default initialized and not managed by a soap context
        virtual _trt__GetStreamUri *soap_alloc(void) const { return SOAP_NEW_UNMANAGED(_trt__GetStreamUri); }
      public:
        /// Constructor with default initializations
        _trt__GetStreamUri() : StreamSetup(), ProfileToken(), soap() { }
        /// Destructor
        virtual ~_trt__GetStreamUri() { }
        /// Friend allocator used by soap_new__trt__GetStreamUri(struct soap*, int)
        friend SOAP_FMAC1 _trt__GetStreamUri * SOAP_FMAC2 soap_instantiate__trt__GetStreamUri(struct soap*, int, const char*, const char*, size_t*);
};
#endif

/* ../onvif_head/onvif.h:2148 */
#ifndef SOAP_TYPE__trt__GetStreamUriResponse
#define SOAP_TYPE__trt__GetStreamUriResponse (1310)
/* complex XML schema type 'trt:GetStreamUriResponse': */
class SOAP_CMAC _trt__GetStreamUriResponse {
      public:
        /// Required element 'trt:MediaUri' of XML schema type 'tt:MediaUri'
        tt__MediaUri *MediaUri;
        /// Context that manages this object
        struct soap *soap;
      public:
        /// Return unique type id SOAP_TYPE__trt__GetStreamUriResponse
        virtual long soap_type(void) const { return SOAP_TYPE__trt__GetStreamUriResponse; }
        /// (Re)set members to default values
        virtual void soap_default(struct soap*);
        /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures
        virtual void soap_serialize(struct soap*) const;
        /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK
        virtual int soap_put(struct soap*, const char *tag, const char *type) const;
        /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK
        virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;
        /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error
        virtual void *soap_get(struct soap*, const char *tag, const char *type);
        /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error
        virtual void *soap_in(struct soap*, const char *tag, const char *type);
        /// Return a new object of type _trt__GetStreamUriResponse, default initialized and not managed by a soap context
        virtual _trt__GetStreamUriResponse *soap_alloc(void) const { return SOAP_NEW_UNMANAGED(_trt__GetStreamUriResponse); }
      public:
        /// Constructor with default initializations
        _trt__GetStreamUriResponse() : MediaUri(), soap() { }
        /// Destructor
        virtual ~_trt__GetStreamUriResponse() { }
        /// Friend allocator used by soap_new__trt__GetStreamUriResponse(struct soap*, int)
        friend SOAP_FMAC1 _trt__GetStreamUriResponse * SOAP_FMAC2 soap_instantiate__trt__GetStreamUriResponse(struct soap*, int, const char*, const char*, size_t*);
};
#endif

2.函数

函数声明:client\application\soapStub.h

/** Web service synchronous operation 'soap_call___trt__GetStreamUri' to the specified endpoint and SOAP Action header, returns SOAP_OK or error code */
SOAP_FMAC5 int SOAP_FMAC6 soap_call___trt__GetStreamUri(struct soap *soap, const char *soap_endpoint, const char *soap_action, _trt__GetStreamUri *trt__GetStreamUri, _trt__GetStreamUriResponse &trt__GetStreamUriResponse);

函数定义:client\application\soapClient.cpp

SOAP_FMAC5 int SOAP_FMAC6 soap_call___trt__GetStreamUri(struct soap *soap, const char *soap_endpoint, const char *soap_action, _trt__GetStreamUri *trt__GetStreamUri, _trt__GetStreamUriResponse &trt__GetStreamUriResponse)
{	if (soap_send___trt__GetStreamUri(soap, soap_endpoint, soap_action, trt__GetStreamUri) || soap_recv___trt__GetStreamUri(soap, trt__GetStreamUriResponse))
		return soap->error;
	return SOAP_OK;
}

四、功能实现(c++)

int ONVIF_GetMediaCapabilities(const std::string& deviceXAddr, std::string *mediaXAddr)
{
    int result = 0;
    struct soap *soap = nullptr;
    _tds__GetCapabilities            devinfo_req;
    _tds__GetCapabilitiesResponse    devinfo_resp;


            SOAP_ASSERT(!deviceXAddr.empty());
            SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    result = soap_call___tds__GetCapabilities(soap, deviceXAddr.c_str(), NULL, &devinfo_req, devinfo_resp);
    SOAP_CHECK_ERROR(result, soap, "GetCapabilities");
    

    if(devinfo_resp.Capabilities->Media != nullptr)
    {
        *mediaXAddr=devinfo_resp.Capabilities->Media->XAddr;
    }
    else
    {
        *mediaXAddr="null";
    }
       

#if DEBUG
    std::cout << "---------------------ONVIF_GetPTZCapabilities------------------" << "\n";
    std::cout << "Media:" << *mediaXAddr << "\n";
    std::cout << "-------------------------------------------------------------" << "\n";
#endif

    EXIT:

    if (nullptr != soap) {
        ONVIF_soap_delete(soap);
    }
    return result;
}

bool ONVIF_GetMediaProfilesToken(const std::string& mediaXAddr, std::string *mediaprofilesToken)
{
    int result = 0;
    struct soap *soap = nullptr;
    _trt__GetProfiles           devinfo_req;
    _trt__GetProfilesResponse   devinfo_resp;

            SOAP_ASSERT(!mediaXAddr.empty());
            SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    result = soap_call___trt__GetProfiles(soap, mediaXAddr.c_str(), nullptr, &devinfo_req, devinfo_resp);
    SOAP_CHECK_ERROR(result, soap, "ONVIF_GetProfiles");

            SOAP_ASSERT(devinfo_resp.__sizeProfiles > 0);

    *mediaprofilesToken = (*devinfo_resp.Profiles)->token;
#if DEBUG
    std::cout << "-----------------ONVIF_GetMediaProfilesToken-----------------" << "\n";
    std::cout << *mediaprofilesToken << "\n";
    std::cout << "-------------------------------------------------------------" << "\n";
#endif 
    EXIT:
    if (nullptr != soap) {
        ONVIF_soap_delete(soap);
    }

    return result;
}

/************************************************************************
**函数:ONVIF_GetStreamUri
**功能:获取设备码流地址(RTSP)
**参数:
       [in]  MediaXAddr    - 媒体服务地址
       [in]  ProfileToken  - the media profile token
**返回:
       0表明成功,非0表明失败
**备注:
************************************************************************/
int ONVIF_GetStreamUri(const std::string&MediaXAddr, const std::string&ProfileToken, std::string *streamUri)
{
    int result = 0;
    struct soap *soap = nullptr;
    tt__StreamSetup              ttStreamSetup;
    tt__Transport                ttTransport;
    _trt__GetStreamUri           req;
    _trt__GetStreamUriResponse   rep;

     SOAP_ASSERT(!MediaXAddr.empty());
     SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));


    ttStreamSetup.Stream                = tt__StreamType__RTP_Unicast;
    ttStreamSetup.Transport             = &ttTransport;
    ttStreamSetup.Transport->Protocol   = tt__TransportProtocol__RTSP;
    ttStreamSetup.Transport->Tunnel     = nullptr;
    req.StreamSetup                     = &ttStreamSetup;
    req.ProfileToken                    = const_cast<char *>(ProfileToken.c_str());

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    result = soap_call___trt__GetStreamUri(soap, MediaXAddr.c_str(), nullptr, &req, rep);
    SOAP_CHECK_ERROR(result, soap, "GetServices");



    if (nullptr != rep.MediaUri) {
        if (nullptr != rep.MediaUri->Uri) {
            *streamUri = rep.MediaUri->Uri;
#if DEBUG
            std::cout << "----------------------ONVIF_GetStreamUri---------------------" << "\n";
            std::cout << "RTSP URI:\t"<< *streamUri << "\n";
            std::cout << "-------------------------------------------------------------" << "\n";
#endif
        }
    }

    EXIT:

    if (nullptr != soap) {
        ONVIF_soap_delete(soap);
    }

    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值