onvif学习笔记10:获取RTSP流地址

有网友购买了我的ONVIF视频课程 (注:CSDN已经把课程下架了,说不符合要求),问了我几个问题,其中一个是实现ONVIF服务器的获取RTSP地址功能,本文整理出一个思路,愿帮到在学习ONVIF路上的诸君。
我录制的视频是很早之前的,一直没抽时间再录一个实战视频,所以凡是购买的网友,均会进行指导。当然,限于能力,也不是所有的问题都解答。

官方WSDL说明

ONVIF协议通过GetStreamUri获取流地址,在官方wsdl页面搜索GetStreamUri可看到该命令的详细信息。
详细字段如图1所示:
图1 GetStreamUri
GetStreamUri是客户端发起的请求,共2大字段:
第1个是ProfileToken,亦即要获取的媒体profile名称——因为不同的profile,可以有不同的媒体参数。最简单的例子,摄像头有2路视频输出,720P和1080P,则会有2个媒体profile(使用不同的token来表示),因此,需要指定获取的是哪一个profile的流地址。
第2个是流参数设置StreamSetup。说明如下:

  • Stream:一个枚举类型,指定单播还是多播。
  • Transport:指定传输的协议。
    GetStreamUriResponse是响应包,其字段由服务端填充,客户端只要组装好GetStreamUri发送出来,等待响应包即可。
  • Uri:即流地址。
  • InvalidAfterConnect:指示只有连接后uri是否有效,设置为false。
  • InvalidAfterReboot:指示重启后uri是否有效,设置为false。
  • Timeout:超时时间,设置为0表示永久有效,——即使profile发生改变。

笔者存疑:InvalidAfterConnect、InvalidAfterReboot在字面上和解释上似乎不通,但对比官方说明中的ValidUntilConnectt ValidUntilReboot似乎又说得通,笔者怀疑是wsdl文档更新过程表述不一致导致的。在代码中,务必让这2个字段设置为false。

代码实现思路

下面分别从客户端、服务器讲讲代码实现思路。

客户端获取代码

首先,设置_trt__GetStreamUri结构体为指定的profile名称。——profile名称由其它函数获取。
其次,设置tt__StreamSetup结构体为单播,枚举值为tt__StreamType__RTP_Unicast。
再次,设置tt__Transport结构体字段,协议为tt__TransportProtocol__UDP。
最后,调用soap_call___trt__GetStreamUri函数。在_trt__GetStreamUriResponse中的MediaUri带有Uri,此亦本文开头提到的流地址

服务端返回代码

在响应GetStreamUri的函数中,判断_trt__GetStreamUri带的字段,如指针有效性、profile有效性,传输协议的判断。
然后设置trt__GetStreamUriResponse的MediaUri,包括Uri、InvalidAfterConnect、InvalidAfterReboot和Timeout。其中,Uri就是RTSP媒体器地址。
关于RTSP地址的设置,可以固定一种格式,在流服务器中固定,再在ONVIF服务器中固定,但这样不方便。也可以在流服务器中生成,然后通过进程通信的方式通知ONVIF服务器,这样方便维护。

代码结构体

文中涉及的结构体较多,较复杂,有删改。

class _trt__GetStreamUri
{ public:
/// <PRE><BLOCKQUOTE>
///   Stream Setup that should be used with the uri
/// </BLOCKQUOTE></PRE>
/// Element "StreamSetup" of XSD type "http://www.onvif.org/ver10/schema":StreamSetup.
    tt__StreamSetup*                     StreamSetup                    1;    ///< Required element.
/// <PRE><BLOCKQUOTE>
///   The ProfileToken element indicates the media profile to use and will define the configuration of the content of the stream.
/// </BLOCKQUOTE></PRE>
/// Element "ProfileToken" of XSD type "http://www.onvif.org/ver10/schema":ReferenceToken.
    tt__ReferenceToken                   ProfileToken                   1;    ///< Required element.
/// A handle to the soap struct context that manages this instance when instantiated by a context or NULL otherwise (automatically set).
    struct soap                         *soap                          ;
};

class tt__StreamSetup
{ public:
/// <PRE><BLOCKQUOTE>
///   Defines if a multicast or unicast stream is requested
/// </BLOCKQUOTE></PRE>
/// Element "Stream" of XSD type "http://www.onvif.org/ver10/schema":StreamType.
    enum tt__StreamType                  Stream                         1;    ///< Required element.
/// Element "Transport" of XSD type "http://www.onvif.org/ver10/schema":Transport.
    tt__Transport*                       Transport                      1;    ///< Required element.
/// @todo <any namespace="##any" minOccurs="0" maxOccurs="unbounded">
/// @todo Schema extensibility is user-definable.
///       Consult the protocol documentation to change or insert declarations.
///       Use wsdl2h option -x to remove this element.
///       Use wsdl2h option -d for xsd__anyType DOM (soap_dom_element).
/// Size of the array of XML or DOM nodes is 0..unbounded.
    std::vector<xsd__anyType           > __any                         0;    ///< Catch any element content in DOM.
/// @todo <anyAttribute namespace="##any">.
/// @todo Schema extensibility is user-definable.
///       Consult the protocol documentation to change or insert declarations.
///       Use wsdl2h option -x to remove this attribute.
///       Use wsdl2h option -d for xsd__anyAttribute DOM (soap_dom_attribute).
   @xsd__anyAttribute                    __anyAttribute                ;    ///< Store anyAttribute content in DOM soap_dom_attribute linked node structure.
/// A handle to the soap struct context that manages this instance when instantiated by a context or NULL otherwise (automatically set).
    struct soap                         *soap                          ;
};

enum tt__StreamType
{
    tt__StreamType__RTP_Unicast,    ///< xs:string value="RTP-Unicast"
    tt__StreamType__RTP_Multicast,    ///< xs:string value="RTP-Multicast"
};

class tt__Transport
{ public:
/// <PRE><BLOCKQUOTE>
///   Defines the network protocol for streaming, either UDP=RTP/UDP, RTSP=RTP/RTSP/TCP or HTTP=RTP/RTSP/HTTP/TCP
/// </BLOCKQUOTE></PRE>
/// Element "Protocol" of XSD type "http://www.onvif.org/ver10/schema":TransportProtocol.
    enum tt__TransportProtocol           Protocol                       1;    ///< Required element.
/// <PRE><BLOCKQUOTE>
///   Optional element to describe further tunnel options. This element is normally not needed
/// </BLOCKQUOTE></PRE>
/// Element "Tunnel" of XSD type "http://www.onvif.org/ver10/schema":Transport.
    tt__Transport*                       Tunnel                         0;    ///< Optional element.
/// A handle to the soap struct context that manages this instance when instantiated by a context or NULL otherwise (automatically set).
    struct soap                         *soap                          ;
};

enum tt__TransportProtocol
{
    tt__TransportProtocol__UDP,    ///< xs:string value="UDP"
    tt__TransportProtocol__TCP,    ///< xs:string value="TCP"
    tt__TransportProtocol__RTSP,    ///< xs:string value="RTSP"
    tt__TransportProtocol__HTTP,    ///< xs:string value="HTTP"
};

响应包结构体:

class _trt__GetStreamUriResponse
{ public:

/// </BLOCKQUOTE></PRE>
/// Element "MediaUri" of XSD type "http://www.onvif.org/ver10/schema":MediaUri.
    tt__MediaUri*                        MediaUri                       1;    ///< Required element.
/// A handle to the soap struct context that manages this instance when instantiated by a context or NULL otherwise (automatically set).
    struct soap                         *soap                          ;
};

class tt__MediaUri
{ public:
/// <PRE><BLOCKQUOTE>
///   Stable Uri to be used for requesting the media stream
/// </BLOCKQUOTE></PRE>
/// Element "Uri" of XSD type xs:anyURI.
    xsd__anyURI                          Uri                            1;    ///< Required element.
/// <PRE><BLOCKQUOTE>
///   Indicates if the Uri is only valid until the connection is established. The value shall be set to "false".
/// </BLOCKQUOTE></PRE>
/// Element "InvalidAfterConnect" of XSD type xs:boolean.
    bool                                 InvalidAfterConnect            1;    ///< Required element.
/// <PRE><BLOCKQUOTE>
///   Indicates if the Uri is invalid after a reboot of the device. The value shall be set to "false".
/// </BLOCKQUOTE></PRE>
/// Element "InvalidAfterReboot" of XSD type xs:boolean.
    bool                                 InvalidAfterReboot             1;    ///< Required element.
/// <PRE><BLOCKQUOTE>
///   Duration how long the Uri is valid. This parameter shall be set to PT0S to indicate that this stream URI is indefinitely valid even if the profile changes
/// </BLOCKQUOTE></PRE>
/// Element "Timeout" of XSD type xs:duration.
    xsd__duration                        Timeout                        1;    ///< Required element.
/// @todo <any namespace="##any" minOccurs="0" maxOccurs="unbounded">
/// @todo Schema extensibility is user-definable.
///       Consult the protocol documentation to change or insert declarations.
///       Use wsdl2h option -x to remove this element.
///       Use wsdl2h option -d for xsd__anyType DOM (soap_dom_element).
/// Size of the array of XML or DOM nodes is 0..unbounded.
    std::vector<xsd__anyType           > __any                         0;    ///< Catch any element content in DOM.
/// @todo <anyAttribute namespace="##any">.
/// @todo Schema extensibility is user-definable.
///       Consult the protocol documentation to change or insert declarations.
///       Use wsdl2h option -x to remove this attribute.
///       Use wsdl2h option -d for xsd__anyAttribute DOM (soap_dom_attribute).
   @xsd__anyAttribute                    __anyAttribute                ;    ///< Store anyAttribute content in DOM soap_dom_attribute linked node structure.
/// A handle to the soap struct context that manages this instance when instantiated by a context or NULL otherwise (automatically set).
    struct soap                         *soap                          ;
};

后记

文中只针对GetStreamUri字段进行说明,未提到ONVIF的连接、ONVIF鉴权等事宜。
本文出现的函数、枚举,均为很久前笔者生成的ONVIF框架代码,不表示本文发表时生成的ONVIF代码亦如是。
文中提到的profile,可搜索网上资料,也可参考笔者之前写的文章。
ONVIF不实现RTSP流服务,仅提供一个渠道让客户端获取流地址而已。实际项目中,可使用live555(笔者曾经研究过一段时间,其它服务未接触)实现。
由于ONVIF可参考资料较少,文中难免有错漏之处,欢迎指正,一起学习,共同进步。

参考资料:

onvif GetStreamUri

李迟 2019.4.15 周一 深夜

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值