26417
- 收藏
- 点赞
- 分享
- 举报
ONVIF协议实现2:码流地址的获取并在ONVIF Device Manager测试成功
本帖最后由 goodman 于 2015-1-5 21:26 编辑
工作平台及工具:
Ubuntu:12.04 + gcc + OnvifTestTool12.12
gsoap下载:[url]http://www.cs.fsu.edu/~engelen/soap.html[/url]
PC:live555.exe + test.264
目前的最新版本为:gsoap2.8.21
通过设备发现的实现,对ONVIF有了很多的了解,也对其开发步骤有了很好地认识,现在实现码流的获取也不难按如下步骤即可:
1.相关概念和前置知识
Profile:参见[url]http://www.onvif.org/Portals/0/documents/op/ONVIF_Profile_Policy_v2-0.pdf[/url]
1.1、GetCapabilities #获取设备能力表
1.2、GetProfiles # 获取设备的Profile
1.3、GetStreamUri #填充rtsp路径如:[url]rtsp://192.168.1.101/test.264[/url]
1.4、RTSP服务器 #因为我们的设备端不是摄像机所以要借助live555来模拟
1.5、GetVideoSourceConfiguration #获取视频源配置信息
1.6、GetVideoEncoderConfigurationOptions #获取编码配置选项
下面我们的框架和具体实现围绕这几个函数开实现。
2.生成框架代码
执行如下代码(我的工程里面有个gen.sh也可以生成代码):
./wsdl2h -o onvif.h -c -s -t ./typemap.dat [url]http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl[/url]
./soapcpp2 -c onvif.h -x -d ./ -I ${HOME}/workspace/source/gsoap-2.8/gsoap/import -I ${HOME}/workspace/source/gsoap-2.8/gsoap/
这里我们最小化实现,只包含这个2个其他的都排除在外,这样生成的代码才最小,将生成的代码从tools目录移动到src目录里面(目录结构请下载对用的工程文件)

我们看到完整的工程包含这么多的WSDL如果全部实现,光是定义相应的函数就够你受得了。
3.启动一个gsoap服务
main函数里面启动了一个soap_server,这里使用8080端口sevice的的端口可以改成你自己的
[code]
int gsoapInit(struct OnvifApp* app)
{
if (!app->bindPort)
app->bindPort = 8080;
strcpy(app->hostAddress, "192.168.1.104");
snprintf(app->xAddr, sizeof(app->xAddr), "http://%s:%d/onvif/device_service",
app->hostAddress, app->bindPort);
fprintf(stderr, "xAddr:%s\n", app->xAddr);
snprintf(app->xAddrRoot, sizeof(app->xAddrRoot), "http://%s:%d/onvif",
app->hostAddress, app->bindPort);
soap_init2(&app->soap, SOAP_ENC_MTOM | SOAP_ENC_MIME, 0 );
soap_set_namespaces(&app->soap, namespaces);
soap_set_recv_logfile(&app->soap, "./log/recv.xml");
soap_set_sent_logfile(&app->soap, "./log/send.xml");
soap_set_test_logfile(&app->soap, "./log/test.log");
app->soap.bind_flags = SO_REUSEADDR;
app->soap.accept_timeout = 10;
app->soap.recv_timeout = 10;
app->soap.send_timeout = 10;
app->soap.max_keep_alive = 30;
app->masterSocket = soap_bind(&app->soap, "0.0.0.0", app->bindPort, 100);
if (app->masterSocket < 0) {
soap_print_fault(&app->soap, stderr);
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
gApp = (struct OnvifApp*)calloc(1, sizeof(*gApp));
if(!gApp) {
fprintf(stderr, "calloc wsapp failed\n");
return -1;
}
for(;;) {
if(gsoapInit(gApp)!=0) //具体的函数定义请参考工程文件
break;
if (WsAppRun(gApp, 1) < 0)
break;
getchar();
gsoapFini(gApp);
free(gApp);
return 0;
}
free(gApp);
return -1;
}
[/code]
4.整理需要实现的函数
上面的框架代码实现好后,一编译就会报一大推的链接错误,我们需要将这些函数实现,我们按命名空间来讲这些函数分类到2个单独的文件离去,分别为
tds_ssom.c 和 trt_ssom.c具体的内容就不贴了比较多,可以参看我工程里的代码。然后再Makefile里面把这2个文件添加上,就能找到这些引用了,这样
做的好处是,每次需要添加第三个WSDL的时候可以保证前面整理的函数都是可用的,这样可以避免很多重复的劳动。
5.实现关键代码
5.1 __tds__GetCapabilities函数
[code]
SOAP_FMAC5 int SOAP_FMAC6 __tds__GetCapabilities(struct soap* soap, struct _tds__GetCapabilities *tds__GetCapabilities, struct _tds__GetCapabilitiesResponse *tds__GetCapabilitiesResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
enum tt__CapabilityCategory CapabilityCategory;
if (!tds__GetCapabilities->Category) {
CapabilityCategory = tt__CapabilityCategory__All;
} else {
CapabilityCategory = *(tds__GetCapabilities->Category);
}
if (CapabilityCategory != tt__CapabilityCategory__All &&
CapabilityCategory != tt__CapabilityCategory__Analytics &&
CapabilityCategory != tt__CapabilityCategory__Device &&
CapabilityCategory != tt__CapabilityCategory__Events &&
CapabilityCategory != tt__CapabilityCategory__Imaging &&
CapabilityCategory != tt__CapabilityCategory__Media &&
CapabilityCategory != tt__CapabilityCategory__PTZ) {
fprintf(stderr, "The requested WSDL service category is not supported by the NVT");
//return soap_sender_fault_subcode(soap, "env:Receiver/ter:ActionNotSupported/ter:NoSuchService", "The requested WSDL service category is not supported by the NVT", NULL); ;
return SOAP_FAULT;
}
static struct tt__Capabilities tCapabilities;
soap_default_tt__Capabilities(soap, &tCapabilities);
tds__GetCapabilitiesResponse->Capabilities = &tCapabilities;
/* tt:AnalyticsCapabilities */
if ((CapabilityCategory == tt__CapabilityCategory__All) || (CapabilityCategory == tt__CapabilityCategory__Analytics)) {
static struct tt__AnalyticsCapabilities tAnalytics;
soap_default_tt__AnalyticsCapabilities(soap, &tAnalytics);
tCapabilities.Analytics = &tAnalytics;
static char Analytics_Addr[256];
sprintf(Analytics_Addr, "%sanalytics", gApp->xAddrRoot);
tAnalytics.XAddr = Analytics_Addr;
tAnalytics.RuleSupport = xsd__boolean__false_;
tAnalytics.AnalyticsModuleSupport = xsd__boolean__false_;
}
/* tt:DeviceCapabilities */
if ((CapabilityCategory == tt__CapabilityCategory__All) || (CapabilityCategory == tt__CapabilityCategory__Device)) {
static struct tt__DeviceCapabilities tDevice;
soap_default_tt__DeviceCapabilities(soap, &tDevice);
tCapabilities.Device = &tDevice;
static char Device_Addr[64];
sprintf(Device_Addr, "%sdevice_service", gApp->xAddrRoot);
tDevice.XAddr = Device_Addr;
/* tt:NetworkCapabilities */
static struct tt__NetworkCapabilities tNetwork;
soap_default_tt__NetworkCapabilities(soap, &tNetwork);
tDevice.Network = &tNetwork;
static enum xsd__boolean enIPFilter = xsd__boolean__true_;
static enum xsd__boolean enZeroConfiguration = xsd__boolean__false_;
static enum xsd__boolean enIPVersion6 = xsd__boolean__false_;
static enum xsd__boolean enDynDNS = xsd__boolean__true_;
tNetwork.IPFilter = &enIPFilter;
tNetwork.ZeroConfiguration = &enZeroConfiguration;
tNetwork.IPVersion6 = &enIPVersion6;
tNetwork.DynDNS = &enDynDNS;
static struct tt__NetworkCapabilitiesExtension tNetworkCapabilitiesExtension;
soap_default_tt__NetworkCapabilitiesExtension(soap, &tNetworkCapabilitiesExtension);
tNetwork.Extension = &tNetworkCapabilitiesExtension;
static enum xsd__boolean enDot11Configuration;
tNetworkCapabilitiesExtension.Dot11Configuration = &enDot11Configuration;
/* tt:SystemCapabilities */
static struct tt__SystemCapabilities tSystemCapabilities;
soap_default_tt__SystemCapabilities(soap, &tSystemCapabilities);
tDevice.System = &tSystemCapabilities;
tSystemCapabilities.DiscoveryResolve = xsd__boolean__false_;
tSystemCapabilities.DiscoveryBye = xsd__boolean__true_;
tSystemCapabilities.RemoteDiscovery = xsd__boolean__true_;
tSystemCapabilities.SystemBackup = xsd__boolean__false_;
tSystemCapabilities.SystemLogging = xsd__boolean__false_;
tSystemCapabilities.FirmwareUpgrade = xsd__boolean__true_;
tSystemCapabilities.__sizeSupportedVersions = 3;
static struct tt__OnvifVersion tSupportedVersions[3];
tSupportedVersions[0].Major = 2;
tSupportedVersions[0].Minor = 2;
tSupportedVersions[1].Major = 2;
tSupportedVersions[1].Minor = 1;
tSupportedVersions[2].Major = 2;
tSupportedVersions[2].Minor = 0;
tSystemCapabilities.SupportedVersions = tSupportedVersions;
static struct tt__SystemCapabilitiesExtension tSystemCapabilitiesExtension;
soap_default_tt__SystemCapabilitiesExtension(soap, &tSystemCapabilitiesExtension);
tSystemCapabilities.Extension = &tSystemCapabilitiesExtension;
static enum xsd__boolean enHttpFirmwareUpgrade = xsd__boolean__true_;
static enum xsd__boolean enHttpSystemBackup = xsd__boolean__false_;
static enum xsd__boolean enHttpSystemLogging = xsd__boolean__false_;
static enum xsd__boolean enHttpSupportInformation = xsd__boolean__false_;
tSystemCapabilitiesExtension.HttpFirmwareUpgrade = &enHttpFirmwareUpgrade;
tSystemCapabilitiesExtension.HttpSystemBackup = &enHttpSystemBackup;
tSystemCapabilitiesExtension.HttpSystemLogging = &enHttpSystemLogging;
tSystemCapabilitiesExtension.HttpSupportInformation = &enHttpSupportInformation;
/* tt:IOCapabilities */
static struct tt__IOCapabilities tIO;
soap_default_tt__IOCapabilities(soap, &tIO);
tDevice.IO = &tIO;
static int iInputConnectors = 1;
tIO.InputConnectors = &iInputConnectors;
static int iRelayOutputs = 1;
tIO.RelayOutputs = &iRelayOutputs;
static struct tt__IOCapabilitiesExtension tIOCapabilitiesExtension;
soap_default_tt__IOCapabilitiesExtension(soap, &tIOCapabilitiesExtension);
tIO.Extension = &tIOCapabilitiesExtension;
static enum xsd__boolean enAuxiliary = xsd__boolean__false_;
tIOCapabilitiesExtension.Auxiliary = &enAuxiliary;
tIOCapabilitiesExtension.__sizeAuxiliaryCommands = 1;
static char chAuxiliaryCommands[] = "nothing";
static char* p = chAuxiliaryCommands;
tIOCapabilitiesExtension.AuxiliaryCommands = &p;//&chAuxiliaryCommands;
static struct tt__IOCapabilitiesExtension2 tIOCapabilitiesExtension2;
soap_default_tt__IOCapabilitiesExtension2(soap, &tIOCapabilitiesExtension2);
tIOCapabilitiesExtension.Extension = &tIOCapabilitiesExtension2;
tDevice.Security = NULL;
}
tCapabilities.Events = NULL;
/* tt:ImagingCapabilities */
tCapabilities.Imaging = NULL;
if ((CapabilityCategory == tt__CapabilityCategory__All) || (CapabilityCategory == tt__CapabilityCategory__Media)) {
static struct tt__MediaCapabilities tMedia;
soap_default_tt__MediaCapabilities(soap, &tMedia);
tCapabilities.Media = &tMedia;
static char Media_Addr[64];
sprintf(Media_Addr, "%sMedia", gApp->xAddrRoot);
tMedia.XAddr = Media_Addr;
static struct tt__RealTimeStreamingCapabilities tRealTimeStreamingCapabilities;
soap_default_tt__RealTimeStreamingCapabilities(soap, &tRealTimeStreamingCapabilities);
tMedia.StreamingCapabilities = &tRealTimeStreamingCapabilities;
static enum xsd__boolean enRTPMulticast = xsd__boolean__false_;
static enum xsd__boolean enRTP_USCORETCP = xsd__boolean__true_;
static enum xsd__boolean enRTP_USCORERTSP_USCORETCP = xsd__boolean__true_;
tRealTimeStreamingCapabilities.RTPMulticast = &enRTPMulticast;
tRealTimeStreamingCapabilities.RTP_USCORETCP = &enRTP_USCORETCP;
tRealTimeStreamingCapabilities.RTP_USCORERTSP_USCORETCP = &enRTP_USCORERTSP_USCORETCP;
static struct tt__MediaCapabilitiesExtension tMediaCapabilitiesExtension;
soap_default_tt__MediaCapabilitiesExtension(soap, &tMediaCapabilitiesExtension);
tMedia.Extension = &tMediaCapabilitiesExtension;
static struct tt__ProfileCapabilities tProfileCapabilities;
soap_default_tt__ProfileCapabilities(soap, &tProfileCapabilities);
tMediaCapabilitiesExtension.ProfileCapabilities = &tProfileCapabilities;
tProfileCapabilities.MaximumNumberOfProfiles = 3;
}
tCapabilities.PTZ = NULL;
tCapabilities.Extension = NULL;
fprintf(stderr, "GetCapabilities ok....\n");
return SOAP_OK;
}
[/code]
5.2__trt__GetProfile函数
[code]
int __trt__GetProfile(struct soap* soap, struct _trt__GetProfile *trt__GetProfile, struct _trt__GetProfileResponse *trt__GetProfileResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
return GetProfile(soap, trt__GetProfile->ProfileToken, trt__GetProfileResponse);
}
int __trt__GetProfiles(struct soap* soap, struct _trt__GetProfiles *trt__GetProfiles, struct _trt__GetProfilesResponse *trt__GetProfilesResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
return GetProfile(soap, NULL, trt__GetProfilesResponse);
}
5.3__trt__GetStreamUri函数
int __trt__GetStreamUri(struct soap* soap, struct _trt__GetStreamUri *trt__GetStreamUri, struct _trt__GetStreamUriResponse *trt__GetStreamUriResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
if (trt__GetStreamUri->StreamSetup) {
if (trt__GetStreamUri->StreamSetup->Stream == 1) {
return soap_sender_fault_subcode(soap, "ter:InvalidArgVal/ter:InvalidStreamSetup", "Specification of StreamType or Transport part in StreamSetup is not supported.", NULL);
}
if (trt__GetStreamUri->StreamSetup->Transport->Protocol== 3) {
return soap_sender_fault_subcode(soap, "ter:InvalidArgVal/ter:InvalidStreamSetup", "The HTTP is not supported.", NULL);
}
} else {
return soap_sender_fault_subcode(soap, "ter:InvalidArgVal/ter:GetStreamUri", "Invalid GetStreamUri.", NULL);
}
static struct tt__MediaUri tMediaUri;
static char Dev_Addr[64];
const char* v4_address = "192.168.1.101"; // 修改成你自己的流媒体服务器ip
if (strcmp(trt__GetStreamUri->ProfileToken, "media_profile1") == 0) {
sprintf(Dev_Addr, "rtsp://%s/test.264", v4_address);
} else if (strcmp(trt__GetStreamUri->ProfileToken, "media_profile2") == 0) {
sprintf(Dev_Addr, "rtsp://%s/live1", v4_address);
} else {
return SOAP_ERR;
}
tMediaUri.Uri = Dev_Addr;
tMediaUri.InvalidAfterConnect = xsd__boolean__false_;
tMediaUri.InvalidAfterReboot = xsd__boolean__false_;
static LONG64 SmTimeout;
soap_s2xsd__duration(soap,"PT100S",&SmTimeout);
tMediaUri.Timeout = SmTimeout;//"PT100S";
trt__GetStreamUriResponse->MediaUri = &tMediaUri;
return SOAP_OK;
}
[/code]
5.4.其他函数__trt__GetVideoEncoderConfigurationOptions和__trt__GetVideoSourceConfiguration
这2个函数也很重要,你也可以不实现,现实的话视频的信息无法获取,当然我这里是随便填的,详细参见工程文件,代码比较多
6.运行测试机
由于本次我们没有实现设备发现功能,并且我们的测试机器没有流媒体服务器,将live555.exe和test.264解码出来放在同一个目录
运行live555就得到了流媒体地址(这个地址就是__trt__GetStreamUri里面填的地址):

我们需要手工的将ONVIF地址添加进来.

点开我们的测试设备,就可以开到视频流了。


7.总结
这样基于ONVIF的流媒体地址搜索就实现了,当然过程也耗费了一点时间调试,里面我基本全部使用了静态变量,
应该使用soap_malloc来动态申请,我没有完全搞明白soap的内存管理机制,所以使用保守的做法,至少不会出现内存泄露。
框架生成好再开发ONVIF协议的就是填充结构体,每个命令就要填一大推的结构体。所有的命令在下面可以看到
[url]http://www.onvif.org/onvif/ver20/util/operationIndex.html[/url]
点开每一个都有详细的说明,只要按这个说明填好结构体,ONVIF协议的开发就没有什么难度。tds_ssom.c里面包含了一些基本信息网络等函数,
实现他们就可以在Device Manager的信息栏显示了:

完整的工程下载:[url]http://pan.baidu.com/s/1bnpQnJh[/url] 附件包含测试视频,超过20M了丢个外链吧!
工作平台及工具:
Ubuntu:12.04 + gcc + OnvifTestTool12.12
gsoap下载:[url]http://www.cs.fsu.edu/~engelen/soap.html[/url]
PC:live555.exe + test.264
目前的最新版本为:gsoap2.8.21
通过设备发现的实现,对ONVIF有了很多的了解,也对其开发步骤有了很好地认识,现在实现码流的获取也不难按如下步骤即可:
1.相关概念和前置知识
Profile:参见[url]http://www.onvif.org/Portals/0/documents/op/ONVIF_Profile_Policy_v2-0.pdf[/url]
1.1、GetCapabilities #获取设备能力表
1.2、GetProfiles # 获取设备的Profile
1.3、GetStreamUri #填充rtsp路径如:[url]rtsp://192.168.1.101/test.264[/url]
1.4、RTSP服务器 #因为我们的设备端不是摄像机所以要借助live555来模拟
1.5、GetVideoSourceConfiguration #获取视频源配置信息
1.6、GetVideoEncoderConfigurationOptions #获取编码配置选项
下面我们的框架和具体实现围绕这几个函数开实现。
2.生成框架代码
执行如下代码(我的工程里面有个gen.sh也可以生成代码):
./wsdl2h -o onvif.h -c -s -t ./typemap.dat [url]http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl[/url]
./soapcpp2 -c onvif.h -x -d ./ -I ${HOME}/workspace/source/gsoap-2.8/gsoap/import -I ${HOME}/workspace/source/gsoap-2.8/gsoap/
这里我们最小化实现,只包含这个2个其他的都排除在外,这样生成的代码才最小,将生成的代码从tools目录移动到src目录里面(目录结构请下载对用的工程文件)

我们看到完整的工程包含这么多的WSDL如果全部实现,光是定义相应的函数就够你受得了。
3.启动一个gsoap服务
main函数里面启动了一个soap_server,这里使用8080端口sevice的的端口可以改成你自己的
[code]
int gsoapInit(struct OnvifApp* app)
{
if (!app->bindPort)
app->bindPort = 8080;
strcpy(app->hostAddress, "192.168.1.104");
snprintf(app->xAddr, sizeof(app->xAddr), "http://%s:%d/onvif/device_service",
app->hostAddress, app->bindPort);
fprintf(stderr, "xAddr:%s\n", app->xAddr);
snprintf(app->xAddrRoot, sizeof(app->xAddrRoot), "http://%s:%d/onvif",
app->hostAddress, app->bindPort);
soap_init2(&app->soap, SOAP_ENC_MTOM | SOAP_ENC_MIME, 0 );
soap_set_namespaces(&app->soap, namespaces);
soap_set_recv_logfile(&app->soap, "./log/recv.xml");
soap_set_sent_logfile(&app->soap, "./log/send.xml");
soap_set_test_logfile(&app->soap, "./log/test.log");
app->soap.bind_flags = SO_REUSEADDR;
app->soap.accept_timeout = 10;
app->soap.recv_timeout = 10;
app->soap.send_timeout = 10;
app->soap.max_keep_alive = 30;
app->masterSocket = soap_bind(&app->soap, "0.0.0.0", app->bindPort, 100);
if (app->masterSocket < 0) {
soap_print_fault(&app->soap, stderr);
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
gApp = (struct OnvifApp*)calloc(1, sizeof(*gApp));
if(!gApp) {
fprintf(stderr, "calloc wsapp failed\n");
return -1;
}
for(;;) {
if(gsoapInit(gApp)!=0) //具体的函数定义请参考工程文件
break;
if (WsAppRun(gApp, 1) < 0)
break;
getchar();
gsoapFini(gApp);
free(gApp);
return 0;
}
free(gApp);
return -1;
}
[/code]
4.整理需要实现的函数
上面的框架代码实现好后,一编译就会报一大推的链接错误,我们需要将这些函数实现,我们按命名空间来讲这些函数分类到2个单独的文件离去,分别为
tds_ssom.c 和 trt_ssom.c具体的内容就不贴了比较多,可以参看我工程里的代码。然后再Makefile里面把这2个文件添加上,就能找到这些引用了,这样
做的好处是,每次需要添加第三个WSDL的时候可以保证前面整理的函数都是可用的,这样可以避免很多重复的劳动。
5.实现关键代码
5.1 __tds__GetCapabilities函数
[code]
SOAP_FMAC5 int SOAP_FMAC6 __tds__GetCapabilities(struct soap* soap, struct _tds__GetCapabilities *tds__GetCapabilities, struct _tds__GetCapabilitiesResponse *tds__GetCapabilitiesResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
enum tt__CapabilityCategory CapabilityCategory;
if (!tds__GetCapabilities->Category) {
CapabilityCategory = tt__CapabilityCategory__All;
} else {
CapabilityCategory = *(tds__GetCapabilities->Category);
}
if (CapabilityCategory != tt__CapabilityCategory__All &&
CapabilityCategory != tt__CapabilityCategory__Analytics &&
CapabilityCategory != tt__CapabilityCategory__Device &&
CapabilityCategory != tt__CapabilityCategory__Events &&
CapabilityCategory != tt__CapabilityCategory__Imaging &&
CapabilityCategory != tt__CapabilityCategory__Media &&
CapabilityCategory != tt__CapabilityCategory__PTZ) {
fprintf(stderr, "The requested WSDL service category is not supported by the NVT");
//return soap_sender_fault_subcode(soap, "env:Receiver/ter:ActionNotSupported/ter:NoSuchService", "The requested WSDL service category is not supported by the NVT", NULL); ;
return SOAP_FAULT;
}
static struct tt__Capabilities tCapabilities;
soap_default_tt__Capabilities(soap, &tCapabilities);
tds__GetCapabilitiesResponse->Capabilities = &tCapabilities;
/* tt:AnalyticsCapabilities */
if ((CapabilityCategory == tt__CapabilityCategory__All) || (CapabilityCategory == tt__CapabilityCategory__Analytics)) {
static struct tt__AnalyticsCapabilities tAnalytics;
soap_default_tt__AnalyticsCapabilities(soap, &tAnalytics);
tCapabilities.Analytics = &tAnalytics;
static char Analytics_Addr[256];
sprintf(Analytics_Addr, "%sanalytics", gApp->xAddrRoot);
tAnalytics.XAddr = Analytics_Addr;
tAnalytics.RuleSupport = xsd__boolean__false_;
tAnalytics.AnalyticsModuleSupport = xsd__boolean__false_;
}
/* tt:DeviceCapabilities */
if ((CapabilityCategory == tt__CapabilityCategory__All) || (CapabilityCategory == tt__CapabilityCategory__Device)) {
static struct tt__DeviceCapabilities tDevice;
soap_default_tt__DeviceCapabilities(soap, &tDevice);
tCapabilities.Device = &tDevice;
static char Device_Addr[64];
sprintf(Device_Addr, "%sdevice_service", gApp->xAddrRoot);
tDevice.XAddr = Device_Addr;
/* tt:NetworkCapabilities */
static struct tt__NetworkCapabilities tNetwork;
soap_default_tt__NetworkCapabilities(soap, &tNetwork);
tDevice.Network = &tNetwork;
static enum xsd__boolean enIPFilter = xsd__boolean__true_;
static enum xsd__boolean enZeroConfiguration = xsd__boolean__false_;
static enum xsd__boolean enIPVersion6 = xsd__boolean__false_;
static enum xsd__boolean enDynDNS = xsd__boolean__true_;
tNetwork.IPFilter = &enIPFilter;
tNetwork.ZeroConfiguration = &enZeroConfiguration;
tNetwork.IPVersion6 = &enIPVersion6;
tNetwork.DynDNS = &enDynDNS;
static struct tt__NetworkCapabilitiesExtension tNetworkCapabilitiesExtension;
soap_default_tt__NetworkCapabilitiesExtension(soap, &tNetworkCapabilitiesExtension);
tNetwork.Extension = &tNetworkCapabilitiesExtension;
static enum xsd__boolean enDot11Configuration;
tNetworkCapabilitiesExtension.Dot11Configuration = &enDot11Configuration;
/* tt:SystemCapabilities */
static struct tt__SystemCapabilities tSystemCapabilities;
soap_default_tt__SystemCapabilities(soap, &tSystemCapabilities);
tDevice.System = &tSystemCapabilities;
tSystemCapabilities.DiscoveryResolve = xsd__boolean__false_;
tSystemCapabilities.DiscoveryBye = xsd__boolean__true_;
tSystemCapabilities.RemoteDiscovery = xsd__boolean__true_;
tSystemCapabilities.SystemBackup = xsd__boolean__false_;
tSystemCapabilities.SystemLogging = xsd__boolean__false_;
tSystemCapabilities.FirmwareUpgrade = xsd__boolean__true_;
tSystemCapabilities.__sizeSupportedVersions = 3;
static struct tt__OnvifVersion tSupportedVersions[3];
tSupportedVersions[0].Major = 2;
tSupportedVersions[0].Minor = 2;
tSupportedVersions[1].Major = 2;
tSupportedVersions[1].Minor = 1;
tSupportedVersions[2].Major = 2;
tSupportedVersions[2].Minor = 0;
tSystemCapabilities.SupportedVersions = tSupportedVersions;
static struct tt__SystemCapabilitiesExtension tSystemCapabilitiesExtension;
soap_default_tt__SystemCapabilitiesExtension(soap, &tSystemCapabilitiesExtension);
tSystemCapabilities.Extension = &tSystemCapabilitiesExtension;
static enum xsd__boolean enHttpFirmwareUpgrade = xsd__boolean__true_;
static enum xsd__boolean enHttpSystemBackup = xsd__boolean__false_;
static enum xsd__boolean enHttpSystemLogging = xsd__boolean__false_;
static enum xsd__boolean enHttpSupportInformation = xsd__boolean__false_;
tSystemCapabilitiesExtension.HttpFirmwareUpgrade = &enHttpFirmwareUpgrade;
tSystemCapabilitiesExtension.HttpSystemBackup = &enHttpSystemBackup;
tSystemCapabilitiesExtension.HttpSystemLogging = &enHttpSystemLogging;
tSystemCapabilitiesExtension.HttpSupportInformation = &enHttpSupportInformation;
/* tt:IOCapabilities */
static struct tt__IOCapabilities tIO;
soap_default_tt__IOCapabilities(soap, &tIO);
tDevice.IO = &tIO;
static int iInputConnectors = 1;
tIO.InputConnectors = &iInputConnectors;
static int iRelayOutputs = 1;
tIO.RelayOutputs = &iRelayOutputs;
static struct tt__IOCapabilitiesExtension tIOCapabilitiesExtension;
soap_default_tt__IOCapabilitiesExtension(soap, &tIOCapabilitiesExtension);
tIO.Extension = &tIOCapabilitiesExtension;
static enum xsd__boolean enAuxiliary = xsd__boolean__false_;
tIOCapabilitiesExtension.Auxiliary = &enAuxiliary;
tIOCapabilitiesExtension.__sizeAuxiliaryCommands = 1;
static char chAuxiliaryCommands[] = "nothing";
static char* p = chAuxiliaryCommands;
tIOCapabilitiesExtension.AuxiliaryCommands = &p;//&chAuxiliaryCommands;
static struct tt__IOCapabilitiesExtension2 tIOCapabilitiesExtension2;
soap_default_tt__IOCapabilitiesExtension2(soap, &tIOCapabilitiesExtension2);
tIOCapabilitiesExtension.Extension = &tIOCapabilitiesExtension2;
tDevice.Security = NULL;
}
tCapabilities.Events = NULL;
/* tt:ImagingCapabilities */
tCapabilities.Imaging = NULL;
if ((CapabilityCategory == tt__CapabilityCategory__All) || (CapabilityCategory == tt__CapabilityCategory__Media)) {
static struct tt__MediaCapabilities tMedia;
soap_default_tt__MediaCapabilities(soap, &tMedia);
tCapabilities.Media = &tMedia;
static char Media_Addr[64];
sprintf(Media_Addr, "%sMedia", gApp->xAddrRoot);
tMedia.XAddr = Media_Addr;
static struct tt__RealTimeStreamingCapabilities tRealTimeStreamingCapabilities;
soap_default_tt__RealTimeStreamingCapabilities(soap, &tRealTimeStreamingCapabilities);
tMedia.StreamingCapabilities = &tRealTimeStreamingCapabilities;
static enum xsd__boolean enRTPMulticast = xsd__boolean__false_;
static enum xsd__boolean enRTP_USCORETCP = xsd__boolean__true_;
static enum xsd__boolean enRTP_USCORERTSP_USCORETCP = xsd__boolean__true_;
tRealTimeStreamingCapabilities.RTPMulticast = &enRTPMulticast;
tRealTimeStreamingCapabilities.RTP_USCORETCP = &enRTP_USCORETCP;
tRealTimeStreamingCapabilities.RTP_USCORERTSP_USCORETCP = &enRTP_USCORERTSP_USCORETCP;
static struct tt__MediaCapabilitiesExtension tMediaCapabilitiesExtension;
soap_default_tt__MediaCapabilitiesExtension(soap, &tMediaCapabilitiesExtension);
tMedia.Extension = &tMediaCapabilitiesExtension;
static struct tt__ProfileCapabilities tProfileCapabilities;
soap_default_tt__ProfileCapabilities(soap, &tProfileCapabilities);
tMediaCapabilitiesExtension.ProfileCapabilities = &tProfileCapabilities;
tProfileCapabilities.MaximumNumberOfProfiles = 3;
}
tCapabilities.PTZ = NULL;
tCapabilities.Extension = NULL;
fprintf(stderr, "GetCapabilities ok....\n");
return SOAP_OK;
}
[/code]
5.2__trt__GetProfile函数
[code]
int __trt__GetProfile(struct soap* soap, struct _trt__GetProfile *trt__GetProfile, struct _trt__GetProfileResponse *trt__GetProfileResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
return GetProfile(soap, trt__GetProfile->ProfileToken, trt__GetProfileResponse);
}
int __trt__GetProfiles(struct soap* soap, struct _trt__GetProfiles *trt__GetProfiles, struct _trt__GetProfilesResponse *trt__GetProfilesResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
return GetProfile(soap, NULL, trt__GetProfilesResponse);
}
5.3__trt__GetStreamUri函数
int __trt__GetStreamUri(struct soap* soap, struct _trt__GetStreamUri *trt__GetStreamUri, struct _trt__GetStreamUriResponse *trt__GetStreamUriResponse)
{
printf("%s:%d\n",__FUNCTION__,__LINE__);
if (trt__GetStreamUri->StreamSetup) {
if (trt__GetStreamUri->StreamSetup->Stream == 1) {
return soap_sender_fault_subcode(soap, "ter:InvalidArgVal/ter:InvalidStreamSetup", "Specification of StreamType or Transport part in StreamSetup is not supported.", NULL);
}
if (trt__GetStreamUri->StreamSetup->Transport->Protocol== 3) {
return soap_sender_fault_subcode(soap, "ter:InvalidArgVal/ter:InvalidStreamSetup", "The HTTP is not supported.", NULL);
}
} else {
return soap_sender_fault_subcode(soap, "ter:InvalidArgVal/ter:GetStreamUri", "Invalid GetStreamUri.", NULL);
}
static struct tt__MediaUri tMediaUri;
static char Dev_Addr[64];
const char* v4_address = "192.168.1.101"; // 修改成你自己的流媒体服务器ip
if (strcmp(trt__GetStreamUri->ProfileToken, "media_profile1") == 0) {
sprintf(Dev_Addr, "rtsp://%s/test.264", v4_address);
} else if (strcmp(trt__GetStreamUri->ProfileToken, "media_profile2") == 0) {
sprintf(Dev_Addr, "rtsp://%s/live1", v4_address);
} else {
return SOAP_ERR;
}
tMediaUri.Uri = Dev_Addr;
tMediaUri.InvalidAfterConnect = xsd__boolean__false_;
tMediaUri.InvalidAfterReboot = xsd__boolean__false_;
static LONG64 SmTimeout;
soap_s2xsd__duration(soap,"PT100S",&SmTimeout);
tMediaUri.Timeout = SmTimeout;//"PT100S";
trt__GetStreamUriResponse->MediaUri = &tMediaUri;
return SOAP_OK;
}
[/code]
5.4.其他函数__trt__GetVideoEncoderConfigurationOptions和__trt__GetVideoSourceConfiguration
这2个函数也很重要,你也可以不实现,现实的话视频的信息无法获取,当然我这里是随便填的,详细参见工程文件,代码比较多
6.运行测试机
由于本次我们没有实现设备发现功能,并且我们的测试机器没有流媒体服务器,将live555.exe和test.264解码出来放在同一个目录
运行live555就得到了流媒体地址(这个地址就是__trt__GetStreamUri里面填的地址):

我们需要手工的将ONVIF地址添加进来.

点开我们的测试设备,就可以开到视频流了。


7.总结
这样基于ONVIF的流媒体地址搜索就实现了,当然过程也耗费了一点时间调试,里面我基本全部使用了静态变量,
应该使用soap_malloc来动态申请,我没有完全搞明白soap的内存管理机制,所以使用保守的做法,至少不会出现内存泄露。
框架生成好再开发ONVIF协议的就是填充结构体,每个命令就要填一大推的结构体。所有的命令在下面可以看到
[url]http://www.onvif.org/onvif/ver20/util/operationIndex.html[/url]
点开每一个都有详细的说明,只要按这个说明填好结构体,ONVIF协议的开发就没有什么难度。tds_ssom.c里面包含了一些基本信息网络等函数,
实现他们就可以在Device Manager的信息栏显示了:

完整的工程下载:[url]http://pan.baidu.com/s/1bnpQnJh[/url] 附件包含测试视频,超过20M了丢个外链吧!
我来回答
回答49个
时间排序
认可量排序
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
加载中···
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片
相关问答
-
2015-01-09 21:52:35
-
2017-10-26 10:15:31
-
2017-09-05 11:49:45
-
2016-04-08 19:03:38
-
2017-11-01 10:48:13
-
2019-09-30 18:56:47
-
2014-12-31 21:32:49
-
2013-06-28 22:35:45
-
2015-12-18 15:45:27
-
2019-01-22 11:49:16
-
2018-08-28 13:24:28
-
2013-07-11 12:48:42
-
2015-03-19 15:19:23
-
2016-01-07 10:53:12
-
2018-09-18 10:48:36
-
2018-12-11 10:20:04
-
12013-07-11 12:08:27
-
02015-03-20 10:16:35
-
22017-10-12 19:25:44
无更多相似问答 去提问

点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认