有了前几篇的基础,现在可以正式开始onvif的实现工作,其中一项非常重要的部分就是视频流的对接,即能够在符合onvif标准的监控客户端软件里接收到设备端NVT发来的RTSP视频流。这里,我所用的客户端软件是Onvif Device Manager v2.2。【来自http://blog.csdn.net/ghostyu】

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

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

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

  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所支持的功能的命令
1、GetProfiles
2、GetStreamUri
填充rtsp路径,例如:rtsp://192.168.1.201/petrov.m4e
3、Media Streaming using RTSP
这里使用开源的live555,完成rtsp功能
4、GetVideoEncoderConfiguration
5、GetVideoEncoderConfigurationOptions
6、GetCapabilities
NVC为了获取DVT所支持的功能的命令

参考文档:

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

一、产生onvif源码框架

1、从wsdl生成C头文件

  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
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、从头文件生成源码框架

  1. soapcpp2 -c onvif.h -x -I /root/onvif/gsoap-2.8/gsoap/import -I /root/onvif/gsoap-2.8/gsoap/
soapcpp2 -c onvif.h -x -I /root/onvif/gsoap-2.8/gsoap/import -I /root/onvif/gsoap-2.8/gsoap/

产生的C文件比较庞大,最大的有十几兆,大部分的内容没有复用导致。

二、创建soap运行环境

  1. int main(int argc, char **argv)
  2. {
  3. int m, s;
  4. struct soap add_soap;
  5. int server_udp;
  6. server_udp = create_server_socket_udp();
  7. //bind_server_udp1(server_udp);
  8. pthread_t thrHello;
  9. pthread_t thrProbe;
  10. //pthread_create(&thrHello,NULL,main_Hello,server_udp);
  11. //sleep(2);
  12. pthread_create(&thrProbe,NULL,main_Probe,server_udp);
  13. soap_init(&add_soap);
  14. soap_set_namespaces(&add_soap, namespaces);
  15. if (argc < 0) {
  16. printf("usage: %s <server_port> \n", argv[0]);
  17. exit(1);
  18. } else {
  19. m = soap_bind(&add_soap, NULL, 80, 100);
  20. if (m < 0) {
  21. soap_print_fault(&add_soap, stderr);
  22. exit(-1);
  23. }
  24. fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
  25. for (;;) {
  26. s = soap_accept(&add_soap);
  27. if (s < 0) {
  28. soap_print_fault(&add_soap, stderr);
  29. exit(-1);
  30. }
  31. fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
  32. soap_serve(&add_soap);
  33. soap_end(&add_soap);
  34. }
  35. }
  36. return 0;
  37. }
int main(int argc, char **argv)
{
int m, s;
struct soap add_soap;
int server_udp; server_udp = create_server_socket_udp();
//bind_server_udp1(server_udp);
pthread_t thrHello;
pthread_t thrProbe;
//pthread_create(&thrHello,NULL,main_Hello,server_udp);
//sleep(2);
pthread_create(&thrProbe,NULL,main_Probe,server_udp); soap_init(&add_soap);
soap_set_namespaces(&add_soap, namespaces); if (argc < 0) {
printf("usage: %s <server_port> \n", argv[0]);
exit(1);
} else {
m = soap_bind(&add_soap, NULL, 80, 100);
if (m < 0) {
soap_print_fault(&add_soap, stderr);
exit(-1);
}
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
for (;;) {
s = soap_accept(&add_soap);
if (s < 0) {
soap_print_fault(&add_soap, stderr);
exit(-1);
}
fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
soap_serve(&add_soap);
soap_end(&add_soap);
}
}
return 0;
}

注意,这里绑定了80端口,onvif使用的是http请求,然后附带xml,其实正常的是将onvif集成到web服务器中,普通的http请求有web服务器处理,onvif的http请求则有soap处理。我们这里的做法也可行,只不过onvif的访问web服务器的功能是无法使用的。

三、RTSP视频对接

1、实现GetCapabilities命令

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

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

  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;
	//想要对接RTSP视频,必须设置Media
tds__GetCapabilitiesResponse->Capabilities->Media = (struct tt__MediaCapabilities*)soap_malloc(soap, sizeof(struct tt__MediaCapabilities));
tds__GetCapabilitiesResponse->Capabilities->Media->XAddr = (char *) soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
strcpy(tds__GetCapabilitiesResponse->Capabilities->Media->XAddr, _IPv4Address);
tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities = (struct tt__RealTimeStreamingCapabilities*)soap_malloc(soap, sizeof(struct tt__RealTimeStreamingCapabilities));
tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = (int *)soap_malloc(soap, sizeof(int));
*tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = _false;
tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = (int *)soap_malloc(soap, sizeof(int));
*tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = _true;
tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = (int *)soap_malloc(soap, sizeof(int));
*tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = _true;
tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->Extension = NULL;
tds__GetCapabilitiesResponse->Capabilities->Media->Extension = NULL;
tds__GetCapabilitiesResponse->Capabilities->Media->__size = 0;
tds__GetCapabilitiesResponse->Capabilities->Media->__any = 0;

另外必要填充的还有

  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. tds__GetCapabilitiesResponse->Capabilities->Extension->Display = NULL;
  10. tds__GetCapabilitiesResponse->Capabilities->Extension->Recording = NULL;
  11. tds__GetCapabilitiesResponse->Capabilities->Extension->Search = NULL;
  12. tds__GetCapabilitiesResponse->Capabilities->Extension->Replay = NULL;
  13. tds__GetCapabilitiesResponse->Capabilities->Extension->Receiver = NULL;
  14. tds__GetCapabilitiesResponse->Capabilities->Extension->AnalyticsDevice = NULL;
  15. tds__GetCapabilitiesResponse->Capabilities->Extension->Extensions = NULL;
  16. tds__GetCapabilitiesResponse->Capabilities->Extension->__size = 0;
  17. tds__GetCapabilitiesResponse->Capabilities->Extension->__any = NULL;
	//下面的重要,这里只实现视频流,需要设置VideoSources
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->VideoSources = TRUE;
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->VideoOutputs = FALSE;
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->AudioSources = FALSE;
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->AudioOutputs = FALSE;
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->RelayOutputs = FALSE;
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->__size = 0;
tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->__any = NULL; tds__GetCapabilitiesResponse->Capabilities->Extension->Display = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->Recording = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->Search = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->Replay = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->Receiver = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->AnalyticsDevice = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->Extensions = NULL;
tds__GetCapabilitiesResponse->Capabilities->Extension->__size = 0;
tds__GetCapabilitiesResponse->Capabilities->Extension->__any = NULL;

2、实现GetServices命令

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

3、实现GetVideoSources命令

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

__tmd__GetVideoSources最重要的是token的填充,必须要和下面profile中的sourcetoken相同,需要匹配到这个视频源

4、实现GetProfiles命令

  1. size = 1;
  2. trt__GetProfilesResponse->Profiles =(struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile) * size);
  3. trt__GetProfilesResponse->__sizeProfiles = size;
  4. i=0;
  5. trt__GetProfilesResponse->Profiles[i].Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
  6. strcpy(trt__GetProfilesResponse->Profiles[i].Name,"my_profile");
  7. trt__GetProfilesResponse->Profiles[i].token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
  8. strcpy(trt__GetProfilesResponse->Profiles[i].token,"token_profile");
  9. trt__GetProfilesResponse->Profiles[i].fixed = _false;
  10. trt__GetProfilesResponse->Profiles[i].__anyAttribute = NULL;
	size = 1;
trt__GetProfilesResponse->Profiles =(struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile) * size);
trt__GetProfilesResponse->__sizeProfiles = size; i=0;
trt__GetProfilesResponse->Profiles[i].Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
strcpy(trt__GetProfilesResponse->Profiles[i].Name,"my_profile");
trt__GetProfilesResponse->Profiles[i].token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
strcpy(trt__GetProfilesResponse->Profiles[i].token,"token_profile");
trt__GetProfilesResponse->Profiles[i].fixed = _false;
trt__GetProfilesResponse->Profiles[i].__anyAttribute = NULL;

除了上面的基本信息,还需要填充两大项:VideoSourceConfiguration和VideoEncoderConfiguration,一个用于描述视频源的信息,另外一个描述视频的编码信息

先给VideoSourceConfiguration分配空间

  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));
	trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration = (struct tt__VideoSourceConfiguration *)soap_malloc(soap,sizeof(struct tt__VideoSourceConfiguration ));
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds = (struct tt__IntRectangle *)soap_malloc(soap,sizeof(struct tt__IntRectangle));

然后在填充它

  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;
	/*注意SourceToken*/
strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name,"VS_Name");
strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token,"VS_Token");
strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken,"GhostyuSource_token"); /*必须与__tmd__GetVideoSources中的token相同*/
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->UseCount = 1;
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->x = 1;
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->y = 1;
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->height = 720;
trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->width = 1280;

如果是指针必须先用soap_malloc分配内存,然后才能赋值

下面是VideoEncoderConfiguration

  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;
	trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration = (struct tt__VideoEncoderConfiguration *)soap_malloc(soap,sizeof(struct tt__VideoEncoderConfiguration));
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name,"VE_Name1");
strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token,"VE_token1");
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->UseCount = 1;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Quality = 10;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Encoding = 1;//JPEG = 0, MPEG4 = 1, H264 = 2;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Height = 720;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Width = 1280;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl = (struct tt__VideoRateControl *)soap_malloc(soap, sizeof(struct tt__VideoRateControl));
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->FrameRateLimit = 30;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->EncodingInterval = 1;
trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->BitrateLimit = 500;

5、GetVideoSourceConfiguration和GetVideoEncoderConfiguration

  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. int  __trt__GetVideoEncoderConfiguration(struct soap* soap, struct _trt__GetVideoEncoderConfiguration *trt__GetVideoEncoderConfiguration, struct _trt__GetVideoEncoderConfigurationResponse *trt__GetVideoEncoderConfigurationResponse)
  8. {
  9. DBG("__trt__GetVideoEncoderConfiguration\n");
  10. return SOAP_OK;
  11. }
int  __trt__GetVideoSourceConfiguration(struct soap* soap, struct _trt__GetVideoSourceConfiguration *trt__GetVideoSourceConfiguration, struct _trt__GetVideoSourceConfigurationResponse *trt__GetVideoSourceConfigurationResponse)
{
DBG("__trt__GetVideoSourceConfiguration\n");
//该函数必要,live video需要
return SOAP_OK;
} int __trt__GetVideoEncoderConfiguration(struct soap* soap, struct _trt__GetVideoEncoderConfiguration *trt__GetVideoEncoderConfiguration, struct _trt__GetVideoEncoderConfigurationResponse *trt__GetVideoEncoderConfigurationResponse)
{
DBG("__trt__GetVideoEncoderConfiguration\n");
return SOAP_OK;
}

6、GetVideoEncoderConfigurationOptions

  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. }
int  __trt__GetVideoEncoderConfigurationOptions(struct soap* soap, struct _trt__GetVideoEncoderConfigurationOptions *trt__GetVideoEncoderConfigurationOptions, struct _trt__GetVideoEncoderConfigurationOptionsResponse *trt__GetVideoEncoderConfigurationOptionsResponse)
{
DBG("__trt__GetVideoEncoderConfigurationOptions\n");
//该函数必要,video streaming需要
return SOAP_OK;
}

以上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信息

源代码下载地址:http://download.csdn.net/detail/ghostyu/4796093

onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接的更多相关文章

  1. onvif规范的实现:使用gSOAP创建SOAP调用实例

    预备知识 ONVIF规范中设备管理和控制部分所定义的接口均以Web Services的形式提供.ONVIF规范涵盖了完全的XML及WSDL的定义.每一个支持ONVIF规范的终端设备均须提供与功能相应的 ...

  2. onvif规范 中文介绍

    什么是ONVIF ? ONVIF规范描述了网络视频的模型.接口.数据类型以及数据交互的模式.并复用了一些现有的标准,如WS系列标准等. ONVIF规范的目标是实现一个网络视频框架协议,使不同厂商所生产 ...

  3. onvif规范的实现:onvif开发常用调试方法 和常见的segmentation fault错误

    在前几篇中,虽然已经实现了rtsp视频流的对接,但是还要做的工作还非常多,onvif本来就是一个覆盖面非常广的一个协议,每一个功能都要填充大量的函数.而且稍不注意就会出现segmentation fa ...

  4. onvif规范的实现:server端Discovery实现,通过OnvifTestTool12.06测试

    说明:网上关于ONVIF开发的文章并不多,也更找不到具体的实例来入门学习.只能靠翻阅各种Specification摸索中前进,下面是最近几天的成果.调通了服务端(或者说设备端)的Discovery,使 ...

  5. HTTP协议/RTSP协议/RTMP协议的区别

    RTSP. RTMP.HTTP的共同点.区别 共同点: 1:RTSP RTMP HTTP都是在应用应用层. 2: 理论上RTSP RTMPHTTP都可以做直播和点播,但一般做直播用RTSP RTMP, ...

  6. onvif 协议

    1.ONVIF 协议解读 https://www.onvif.org 一.什么是ONVIF? 1.1形成 2008年5月,由安讯士(AXIS)联合博世(BOSCH)及索尼(SONY)公司三方宣布携手共 ...

  7. onvif杂项

    onvif规范 中文介绍 什么是ONVIF ? ONVIF规范描述了网络视频的模型.接口.数据类型以及数据交互的模式.并复用了一些现有的标准,如WS系列标准等.ONVIF规范的目标是实现一个网络视频框 ...

  8. 接入监控视频,为啥还需要对接厂商的SDK呢,不是有onvif这样的标准协议吗?

    不少人问过我这个问题,这真是一个好问题. 我举两个例子,让您仔细品: ① 快速打开视频和极致操控的问题. onvif协议很科班,但厂商的sdk可能会给你一些独特的方法,譬如先make一个I帧,这样第一 ...

  9. onvif 开发之video streamer---onvif实现功能和经验

    目录(?)[-] 一产生onvif源码框架 从wsdl生成C头文件 从头文件生成源码框架 二创建soap运行环境 三RTSP视频对接 实现GetCapabilities命令 实现GetServices ...

随机推荐

  1. 【SQL语句】 - Ctrl+3 查询表属性的存储过程 [sp_select_talberowName]

    /**-- ============================================= Author: xftCteateDate: 2013-10-11Description:查看表 ...

  2. 原来真的不会用指针[*p++]

    Describe: 有2字节字符数据,需要转换成2字节的短整型,字符数据低字节在前. Analyse: 其实就是取一下数据,移位再或一下就好了,大伙都这样想的. Ex1: 假设tmp1就是短整型,p指 ...

  3. C++重难点知识

    1.顶层const和底层const const int a=10; int b=5; const int *p1=&a; int (*const)p2=&b; p1是顶层const,表 ...

  4. vs2010中socket链接错误LINK2019

    解决方法参考下面链接: http://blog.163.com/strive_only/blog/static/893801682009225112354746/

  5. django第二个项目--使用模板

    第一步: 创建新项目secondproject cd /tmp/django-admin startproject secondeproject 第二步: 创建一个用于放置模板文件夹 cd /tmp/ ...

  6. Git工作中用法(Gitlab)

    感觉又有了新的认识.  一共有3个仓库,本地自己的,远程自己的,远程主仓库. 为了方便能及时从主仓库获取更新的内容要将远程主仓库也clone下来 git clone upstream url    / ...

  7. tomcat 项目部署问题

    我本地Tomcat版本:Apache Tomcat/8.0.3.0 服务器端:Apache Tomcat/6.0.37 JVM都是:1.7.0_40-b43 之前项目运行正常,在我更新了一些模块后,重 ...

  8. Code First 创建数据库

    最近在对以前学的知识做一个总结,EF 这块,Code First 是很重要的一部分,方便快捷创建模型.   Code First有两种配置方式: DataAnnatation: [Table(&quo ...

  9. CentOS安装错误:no default or ui configuration

    靠,以后再也不用浏览器自带的下载工具下载镜像文件了,原来是下载的不完整,但是显示完全下载完毕了,真特么误导人.文件的checksum不对. references: https://www.centos ...

  10. Asp.Net的核心对象

    原文地址:http://www.cnblogs.com/fish-li/archive/2011/08/21/2148640.html 1.HttpRuntime 对象在处理Http请求的asp.ne ...