获取一个摄像头的RTSP地址一般有如下几个步骤:
1. GetServices 获取设备的服务
2. GetProfiles 获取媒体信息文件,识别主通道、子通道的视频编码分辨率
3. GetStreamUri 获取指定通道的流媒体地址
注:
GetCapabilities 获取设备能力文件,从中识别出媒体信息地址,但是这个接口不适用于获取H265编码相关功能。
要想获取H265的相关功能,必须将https://www.onvif.org/onvif/ver20/media/wsdl/media.wsdl 添加到wsdl2h的命令之中。 具体参考上一篇文章 Linux c++ onvif客户端开发(1): 根据wsdl生成cpp源文件-优快云博客
1. 认证
static int ONVIF_SetAuthInfo(struct soap *soap, const char *username,
const char *password) {
int result = 0;
SOAP_ASSERT(NULL != username);
SOAP_ASSERT(NULL != password);
result = soap_wsse_add_UsernameTokenDigest(soap, NULL, username, password);
SOAP_CHECK_ERROR(result, soap, "add_UsernameTokenDigest");
EXIT:
return result;
}
每个接口的soap对象,每次请求都需要单独设置认证。
2. GetServices
int ONVIF_GetServices(const char *DeviceXAddr) {
printf("ONVIF_GetServices --\n");
int result = 0;
struct soap *soap = NULL;
struct _tds__GetServices devsrv_req;
struct _tds__GetServicesResponse devsrv_resp;
SOAP_ASSERT(NULL != DeviceXAddr);
SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
devsrv_req.IncludeCapability = true;
result = soap_call___tds__GetServices(soap, DeviceXAddr, NULL, &devsrv_req,
devsrv_resp);
SOAP_CHECK_ERROR(result, soap, "ONVIF_GetServices");
for (auto &i : devsrv_resp.Service) {
printf("%s service %s, %s\n", DeviceXAddr, i->Namespace.data(),
i->XAddr.data());
if (i->Namespace == NAMESPACE_MEDIA_H265) {
ONVIF_GetProfiles2(i->XAddr.data());
} else if (i->Namespace == NAMESPACE_MEDIA_H264) {
ONVIF_GetProfiles(i->XAddr.data());
}
}
EXIT:
if (NULL != soap) {
ONVIF_soap_delete(soap);
}
return result;
}
我们可以通过判断namespace的方式来判定是否是H264还是H265所用地址。
#define NAMESPACE_MEDIA_H264 "http://www.onvif.org/ver10/media/wsdl"
#define NAMESPACE_MEDIA_H265 "http://www.onvif.org/ver20/media/wsdl"
3.GetProfiles
对于H265功能(实现http://www.onvif.org/ver20/media/wsdl)的GetProfiles如下
int ONVIF_GetProfiles2(const char *media_xaddr) {
// xmlns:trt="http://www.onvif.org/ver10/media/wsdl
// xmlns:ns1="http://www.onvif.org/ver20/media/wsdl"
printf("GetProfiles2 --\n");
int result = 0;
struct soap *soap = NULL;
SOAP_ASSERT(NULL != media_xaddr);
SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
// 支持H265
struct _ns1__GetProfiles devpro2_req;
struct _ns1__GetProfilesResponse devpro2_resp;
ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
result = soap_call___ns1__GetProfiles(soap, media_xaddr, NULL, &devpro2_req,
devpro2_resp);
SOAP_CHECK_ERROR(result, soap, "ONVIF_GetProfiles2");
for (auto &i : devpro2_resp.Profiles) {
printf("%s profile2 %s, %s\n", media_xaddr, i->Name.data(),
i->token.data());
ONVIF_GetStreamUri2(media_xaddr, i->token.data());
}
EXIT:
if (NULL != soap) {
ONVIF_soap_delete(soap);
}
return result;
}
对于传统H264(实现http://www.onvif.org/ver10/media/wsdl)的功能
int ONVIF_GetProfiles(const char *media_xaddr) {
// xmlns:trt="http://www.onvif.org/ver10/media/wsdl
// xmlns:ns1="http://www.onvif.org/ver20/media/wsdl"
printf("GetProfiles --\n");
int result = 0;
struct soap *soap = NULL;
// 不支持H265
struct _trt__GetProfiles devpro_req;
struct _trt__GetProfilesResponse devpro_resp;
SOAP_ASSERT(NULL != media_xaddr);
SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
result = soap_call___trt__GetProfiles(soap, media_xaddr, NULL, &devpro_req,
devpro_resp);
SOAP_CHECK_ERROR(result, soap, "ONVIF_GetProfiles");
for (auto &i : devpro_resp.Profiles) {
printf("%s profile %s\n", media_xaddr, i->token.data());
ONVIF_GetStreamUri(media_xaddr, i->token.data());
}
EXIT:
if (NULL != soap) {
ONVIF_soap_delete(soap);
}
return result;
}
4.GetStreamUri
H265获取方式
int ONVIF_GetStreamUri2(const char *media_xaddr, char *token) {
printf("ONVIF_GetStreamUri2 --\n");
int result = 0;
struct soap *soap = NULL;
struct _ns1__GetStreamUri devstrm_req;
struct _ns1__GetStreamUriResponse devstrm_resp;
SOAP_ASSERT(NULL != media_xaddr);
SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
devstrm_req.Protocol = "RTSP";
devstrm_req.ProfileToken = token;
result = soap_call___ns1__GetStreamUri(soap, media_xaddr, NULL,
&devstrm_req, devstrm_resp);
SOAP_CHECK_ERROR(result, soap, "ONVIF_GetStreamUri2");
printf("%s ONVIF_GetStreamUri2 %s\n", media_xaddr, devstrm_resp.Uri.data());
EXIT:
if (NULL != soap) {
ONVIF_soap_delete(soap);
}
return result;
}
H264获取方式
int ONVIF_GetStreamUri(const char *DeviceXAddr, char *token) {
printf("ONVIF_GetStreamUri --\n");
int result = 0;
struct soap *soap = NULL;
struct tt__StreamSetup ttStreamSetup;
struct tt__Transport ttTransport;
struct _trt__GetStreamUri devstrm_req;
struct _trt__GetStreamUriResponse devstrm_resp;
SOAP_ASSERT(NULL != DeviceXAddr);
SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
// enum class tt__StreamType {
// RTP_Unicast = 0,
// RTP_Multicast = 1
// };
// enum class tt__TransportProtocol {
// UDP = 0,
// TCP = 1,
// RTSP = 2,
// HTTP = 3
// };
ttStreamSetup.Stream = tt__StreamType::RTP_Unicast;
ttStreamSetup.Transport = &ttTransport;
ttStreamSetup.Transport->Protocol = tt__TransportProtocol::RTSP;
ttStreamSetup.Transport->Tunnel = NULL;
devstrm_req.StreamSetup = &ttStreamSetup;
devstrm_req.ProfileToken = token;
result = soap_call___trt__GetStreamUri(soap, DeviceXAddr, NULL,
&devstrm_req, devstrm_resp);
SOAP_CHECK_ERROR(result, soap, "ONVIF_GetStreamUri");
if (devstrm_resp.MediaUri) {
printf("%s GetStreamUri %s\n", DeviceXAddr,
devstrm_resp.MediaUri->Uri.data());
}
EXIT:
if (NULL != soap) {
ONVIF_soap_delete(soap);
}
return result;
}
5. 执行结果
http://10.10.10.105:2020/onvif/device_service, tdn:NetworkVideoTransmitter
NTP --
Manufacturer:TP-Link
Model:TL-IPC642P-A4
FirmwareVersion:1.0.1 Build 230106 Rel.64198n
SerialNumber:086e9147
HardwareId:3.0
NTP --
ntp manual :
GetCapabilities --
http://10.10.10.105:2020/onvif/device_service capabilities includes tt__AnalyticsCapabilities http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service capabilities includes tt__DeviceCapabilities http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service capabilities includes tt__EventCapabilities http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service capabilities includes tt__ImagingCapabilities http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service capabilities includes tt__MediaCapabilities http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service capabilities includes tt__PTZCapabilities http://10.10.10.105:2020/onvif/service
ONVIF_GetServices --
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver10/device/wsdl, http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver10/media/wsdl, http://10.10.10.105:2020/onvif/service
GetProfiles --
http://10.10.10.105:2020/onvif/service profile profile_1
ONVIF_GetStreamUri --
http://10.10.10.105:2020/onvif/service GetStreamUri rtsp://10.10.10.105:554/stream1
http://10.10.10.105:2020/onvif/service profile profile_2
ONVIF_GetStreamUri --
http://10.10.10.105:2020/onvif/service GetStreamUri rtsp://10.10.10.105:554/stream2
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver10/events/wsdl, http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver20/analytics/wsdl, http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver20/imaging/wsdl, http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver20/ptz/wsdl, http://10.10.10.105:2020/onvif/service
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver20/media/wsdl, http://10.10.10.105:2020/onvif/service
GetProfiles2 --
http://10.10.10.105:2020/onvif/service profile2 mainStream, profile_1
ONVIF_GetStreamUri2 --
http://10.10.10.105:2020/onvif/service ONVIF_GetStreamUri2 rtsp://10.10.10.105:554/stream1
http://10.10.10.105:2020/onvif/service profile2 minorStream, profile_2
ONVIF_GetStreamUri2 --
http://10.10.10.105:2020/onvif/service ONVIF_GetStreamUri2 rtsp://10.10.10.105:554/stream2
http://10.10.10.105:2020/onvif/device_service service http://www.onvif.org/ver10/deviceIO/wsdl, http://10.10.10.105:2020/onvif/servicehttp://10.10.10.104/onvif/device_service, tdn:NetworkVideoTransmitter tds:Device
NTP --
Manufacturer:Dahua
Model:IPC-EW5431-ASW
FirmwareVersion:2.622.0000000.18.R, Build Date 2017-11-10
SerialNumber:5E012B9PAGF4BA8
HardwareId:1.00
NTP --
GetCapabilities --
http://10.10.10.104/onvif/device_service capabilities includes tt__AnalyticsCapabilities http://10.10.10.104/onvif/analytics_service
http://10.10.10.104/onvif/device_service capabilities includes tt__DeviceCapabilities http://10.10.10.104/onvif/device_service
http://10.10.10.104/onvif/device_service capabilities includes tt__EventCapabilities http://10.10.10.104/onvif/event_service
http://10.10.10.104/onvif/device_service capabilities includes tt__ImagingCapabilities http://10.10.10.104/onvif/imaging_service
http://10.10.10.104/onvif/device_service capabilities includes tt__MediaCapabilities http://10.10.10.104/onvif/media_service
ONVIF_GetServices --
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver10/device/wsdl, http://10.10.10.104/onvif/device_service
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver20/analytics/wsdl, http://10.10.10.104/onvif/analytics_service
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver20/imaging/wsdl, http://10.10.10.104/onvif/imaging_service
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver10/media/wsdl, http://10.10.10.104/onvif/media_service
GetProfiles --
http://10.10.10.104/onvif/media_service profile MediaProfile000
ONVIF_GetStreamUri --
http://10.10.10.104/onvif/media_service GetStreamUri rtsp://10.10.10.104:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
http://10.10.10.104/onvif/media_service profile MediaProfile001
ONVIF_GetStreamUri --
http://10.10.10.104/onvif/media_service GetStreamUri rtsp://10.10.10.104:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver20/media/wsdl, http://10.10.10.104/onvif/media2_service
GetProfiles2 --
http://10.10.10.104/onvif/media2_service profile2 MediaProfile_Channel1_MainStream, MediaProfile000
ONVIF_GetStreamUri2 --
http://10.10.10.104/onvif/media2_service ONVIF_GetStreamUri2 rtsp://10.10.10.104:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
http://10.10.10.104/onvif/media2_service profile2 MediaProfile_Channel1_SubStream1, MediaProfile001
ONVIF_GetStreamUri2 --
http://10.10.10.104/onvif/media2_service ONVIF_GetStreamUri2 rtsp://10.10.10.104:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver10/events/wsdl, http://10.10.10.104/onvif/event_service
http://10.10.10.104/onvif/device_service service http://www.onvif.org/ver10/deviceIO/wsdl, http://10.10.10.104/onvif/deviceIO_servicehttp://10.10.10.103/onvif/device_service, tdn:NetworkVideoTransmitter tds:Device
NTP --
Manufacturer:Dahua
Model:DH-IPC-HDBW1230R-V5
FirmwareVersion:2.800.0000000.10.R 2023-08-31
SerialNumber:7L050ECPAG571D8
HardwareId:1.00
NTP --
[soap] ONVIF_GetNtp error: 12, SOAP-ENV:Sender, This optional method is not implemented
GetCapabilities --
http://10.10.10.103/onvif/device_service capabilities includes tt__AnalyticsCapabilities http://10.10.10.103/onvif/analytics_service
http://10.10.10.103/onvif/device_service capabilities includes tt__DeviceCapabilities http://10.10.10.103/onvif/device_service
http://10.10.10.103/onvif/device_service capabilities includes tt__EventCapabilities http://10.10.10.103/onvif/event_service
http://10.10.10.103/onvif/device_service capabilities includes tt__ImagingCapabilities http://10.10.10.103/onvif/imaging_service
http://10.10.10.103/onvif/device_service capabilities includes tt__MediaCapabilities http://10.10.10.103/onvif/media_service
ONVIF_GetServices --
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver10/device/wsdl, http://10.10.10.103/onvif/device_service
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver20/analytics/wsdl, http://10.10.10.103/onvif/Analytics_service
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver20/imaging/wsdl, http://10.10.10.103/onvif/imaging_service
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver10/media/wsdl, http://10.10.10.103/onvif/media_service
GetProfiles --
[soap] ONVIF_GetProfiles error: 4, (null), (null)
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver20/media/wsdl, http://10.10.10.103/onvif/media2_service
GetProfiles2 --
http://10.10.10.103/onvif/media2_service profile2 Profile000, Profile000
ONVIF_GetStreamUri2 --
http://10.10.10.103/onvif/media2_service ONVIF_GetStreamUri2 rtsp://10.10.10.103:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
http://10.10.10.103/onvif/media2_service profile2 Profile001, Profile001
ONVIF_GetStreamUri2 --
http://10.10.10.103/onvif/media2_service ONVIF_GetStreamUri2 rtsp://10.10.10.103:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver10/events/wsdl, http://10.10.10.103/onvif/event_service
http://10.10.10.103/onvif/device_service service http://www.onvif.org/ver10/deviceIO/wsdl, http://10.10.10.103/onvif/deviceIO_service
代码见 NoevilMe/onvif_demo: Linux c++ onvif client demo (github.com)