onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接

2022年01月15日 阅读数:4
这篇文章主要向大家介绍onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。


onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接.有了前几篇的基础,如今能够正式开始onvif的实现工做,其中一项很是重要的部分就是 视频流的对接,即可以在符合onvif标准的监控客户端软件里接收到设备端NVT发来的RTSP视频流。这里php

TAG: ​ONVIF​​  html


目录(?)[-]linux


  1. 一产生onvif源码框架

    1. 从wsdl生成C头文件
    2. 从头文件生成源码框架


  2. 二建立soap运行环境
  3. 三RTSP视频对接

    1. 实现GetCapabilities命令
    2. 实现GetServices命令
    3. 实现GetVideoSources命令
    4. 实现GetProfiles命令
    5. GetVideoSourceConfiguration和GetVideoEncoderConfiguration
    6. GetVideoEncoderConfigurationOptions


  4. 四运行live555MediaServer服务器
  5. 五启动Onvif Device Manager测试

    1. Live video
    2. Video streaming
    3. Profiles
    4. 最后是运行的live555 rtsp服务器




有了前几篇的基础,如今能够正式开始onvif的实现工做,其中一项很是重要的部分就是 视频流的对接,即可以在符合onvif标准的监控客户端软件里接收到设备端NVT发来的RTSP视频流。这里,我所用的客户端软件是Onvif Device Manager v2.2。web

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

文档里描述了若是实现VideoStream,device和client应该具有的条件,固然若是实现文档的全部条件,就能够说该设备符合Profile S服务器

若是单纯实现VideoStream,只需完成下列命令。框架

一、GetProfiles
二、GetStreamUri 
填充rtsp路径,例如:rtsp://192.168.1.201/petrov.m4e
三、Media Streaming using RTSP
这里使用开源的live555,完成rtsp功能
四、GetVideoEncoderConfiguration
五、GetVideoEncoderConfigurationOptions
六、GetCapabilities
NVC为了获取DVT所支持的功能的命令socket

参考文档:ide

一、ONVIF Profile S Specification  
描述ProfileS是什么样的一个东西,如何实现  
二、Reference_of_ONVIF_Development_v1.01.02  
Onvif DVT设计参考,指明了一条道路,但没有具体内容  
三、ONVIF-Media-Service-Spec-v220  
Onvif Media的说明介绍  
四、http://www.onvif.org/onvif/ver20/util/operationIndex.html  
onvif几乎所有命令的详细说明,很是重要。该文档告诉咱们结构体成员的意义和如何填充。Onvif开发其实就是各类结构体的填充。函数

1、产生onvif源码框架

一、从wsdl生成C头文件


  1. wsdl2h -o onvif.h -c -s -t .\typemap.dat
  2.  http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl
  3.  http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl
  4.  http://www.onvif.org/onvif/ver10/display.wsdl
  5.  http://www.onvif.org/onvif/ver10/deviceio.wsdl
  6.  http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl
  7.  http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl
  8.  http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl 
  9.  http://www.onvif.org/onvif/ver10/receiver.wsdl
  10.  http://www.onvif.org/onvif/ver10/recording.wsdl 
  11.  http://www.onvif.org/onvif/ver10/search.wsdl
  12.  http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
  13.  http://www.onvif.org/onvif/ver10/replay.wsdl
  14.  http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
  15.  http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl 
  16.  http://www.onvif.org/onvif/ver10/schema/onvif.xsd 
  17.  http://www.onvif.org/ver10/actionengine.wsdl  

跟前一篇discovery惟一不一样的是,这里多了不少wsdl文件,此次建立完整的onvif代码框架

二、从头文件生成源码框架

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

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

2、建立soap运行环境


  1. int main(int argc, char **argv) 
  2.     int m, s; 
  3.     struct soap add_soap; 
  4.     int server_udp; 
  5.     server_udp = create_server_socket_udp(); 
  6.     //bind_server_udp1(server_udp); 
  7.     pthread_t thrHello; 
  8.     pthread_t thrProbe; 
  9.     //pthread_create(&thrHello,NULL,main_Hello,server_udp); 
  10.     //sleep(2); 
  11.     pthread_create(&thrProbe,NULL,main_Probe,server_udp); 

  12.     soap_init(&add_soap); 
  13.     soap_set_namespaces(&add_soap, namespaces); 

  14.     if (argc < 0) { 
  15.         printf("usage: %s <server_port> \n", argv[0]); 
  16.         exit(1); 
  17.     } else { 
  18.         m = soap_bind(&add_soap, NULL, 80, 100); 
  19.         if (m < 0) { 
  20.             soap_print_fault(&add_soap, stderr); 
  21.             exit(-1); 
  22.         } 
  23. fprintf(stderr, "Socket connection successful: master socket = %d\n", m); 
  24.         for (;;) { 
  25.             s = soap_accept(&add_soap); 
  26.             if (s < 0) { 
  27.                 soap_print_fault(&add_soap, stderr); 
  28.                 exit(-1); 
  29.             } 
  30. fprintf(stderr, "Socket connection successful: slave socket = %d\n", s); 
  31.             soap_serve(&add_soap); 
  32.             soap_end(&add_soap); 
  33.         } 
  34.     } 
  35.     return 0; 

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

3、RTSP视频对接

一、实现GetCapabilities命令

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

在__tds__GetCapabilities函数中咱们只须要填充Media部分和一些必要的便可


  1. //想要对接RTSP视频,必须设置Media 
  2. tds__GetCapabilitiesResponse->Capabilities->Media
  3.  = (struct tt__MediaCapabilities*)soap_malloc(soap, sizeof(struct tt__MediaCapabilities)); 
  4. tds__GetCapabilitiesResponse->Capabilities->Media->XAddr
  5.  = (char *) soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH); 
  6. strcpy(tds__GetCapabilitiesResponse->Capabilities->Media->XAddr, _IPv4Address); 
  7. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities
  8.  = (struct tt__RealTimeStreamingCapabilities*)soap_malloc(soap
  9. , sizeof(struct tt__RealTimeStreamingCapabilities)); 
  10. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast
  11.  = (int *)soap_malloc(soap, sizeof(int));    
  12. *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast
  13.  = _false;    
  14. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP
  15.  = (int *)soap_malloc(soap, sizeof(int)); 
  16. *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP
  17.  = _true;    
  18. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities
  19. ->RTP_USCORERTSP_USCORETCP
  20.  = (int *)soap_malloc(soap, sizeof(int)); 
  21. *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities
  22. ->RTP_USCORERTSP_USCORETCP
  23.  = _true;    
  24. tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->Extension
  25.  = NULL; 
  26. tds__GetCapabilitiesResponse->Capabilities->Media->Extension = NULL; 
  27. tds__GetCapabilitiesResponse->Capabilities->Media->__size = 0; 
  28. 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;  

二、实现GetServices命令


  1. int  __tds__GetServices(struct soap* soap, struct _tds__GetServices *tds__GetServices
  2. , struct _tds__GetServicesResponse *tds__GetServicesResponse) 
  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
  10.  = (struct tds__Service *)soap_malloc(soap, sizeof(struct tds__Service)); 
  11.     tds__GetServicesResponse->Service[0].XAddr
  12.  = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH); 
  13.     tds__GetServicesResponse->Service[0].Namespace
  14.  = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH); 
  15.     strcpy(tds__GetServicesResponse->Service[0].Namespace
  16. , "http://www.onvif.org/ver10/events/wsdl"); 
  17.     strcpy(tds__GetServicesResponse[0].Service->XAddr, _IPAddr); 
  18.     tds__GetServicesResponse->Service[0].Capabilities = NULL; 
  19.     tds__GetServicesResponse->Service[0].Version
  20.  = (struct tt__OnvifVersion *)soap_malloc(soap, sizeof(struct tt__OnvifVersion)); 
  21.     tds__GetServicesResponse->Service[0].Version->Major = 0; 
  22.     tds__GetServicesResponse->Service[0].Version->Minor = 3; 
  23.     tds__GetServicesResponse->Service[0].__any
  24.  = (char **)soap_malloc(soap, sizeof(char *)); 
  25.     tds__GetServicesResponse->Service[0].__any[0]
  26.  = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH); 
  27.     strcpy(tds__GetServicesResponse->Service[0].__any[0],"why1"); 
  28.     tds__GetServicesResponse->Service[0].__any[1]
  29.  = (char *)soap_malloc(soap,sizeof(char) * INFO_LENGTH); 
  30.     strcpy(tds__GetServicesResponse->Service[0].__any[1],"why2"); 
  31.     tds__GetServicesResponse->Service[0].__size = NULL; 
  32.     tds__GetServicesResponse->Service[0].__anyAttribute = NULL; 
  33.     return SOAP_OK; 

三、实现GetVideoSources命令


  1. int  __tmd__GetVideoSources(struct soap* soap
  2. , struct _trt__GetVideoSources *trt__GetVideoSources
  3. , struct _trt__GetVideoSourcesResponse *trt__GetVideoSourcesResponse) 
  4.     DBG("__tmd__GetVideoSources\n"); 

  5.     int size1; 
  6.     size1 = 1; 
  7.     trt__GetVideoSourcesResponse->__sizeVideoSources = size1; 
  8.     trt__GetVideoSourcesResponse->VideoSources = (struct tt__VideoSource *)
  9. soap_malloc(soap, sizeof(struct tt__VideoSource) * size1); 
  10.     trt__GetVideoSourcesResponse->VideoSources[0].Framerate = 30; 
  11.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution = 
  12. (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution)); 
  13.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Height = 720; 
  14.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Width = 1280; 
  15.     trt__GetVideoSourcesResponse->VideoSources[0].token 
  16. = (char *)soap_malloc(soap, sizeof(char)*INFO_LENGTH); 
  17.     strcpy(trt__GetVideoSourcesResponse->VideoSources[0].token,"GhostyuSource_token");
  18.  //注意这里须要和GetProfile中的sourcetoken相同 

  19.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging 
  20. =(struct tt__ImagingSettings*)soap_malloc(soap, sizeof(struct tt__ImagingSettings)); 
  21.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness 
  22. = (float*)soap_malloc(soap,sizeof(float)); 
  23.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness[0] 
  24. = 128; 
  25.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation 
  26. = (float*)soap_malloc(soap,sizeof(float)); 
  27.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation[0] = 128; 
  28.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast 
  29. = (float*)soap_malloc(soap,sizeof(float)); 
  30.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast[0] = 128; 
  31.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter 
  32. = (int *)soap_malloc(soap,sizeof(int)); 
  33.     *trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = 0;  
  34.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness 
  35. = (float*)soap_malloc(soap,sizeof(float)); 
  36.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness[0] = 128; 
  37.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation 
  38. = (struct tt__BacklightCompensation*)soap_malloc(soap
  39. , sizeof(struct tt__BacklightCompensation)); 
  40.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Mode = 0; 
  41.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Level = 20; 
  42.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Exposure = NULL; 
  43.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Focus = NULL; 
  44.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange 
  45. = (struct tt__WideDynamicRange*)soap_malloc(soap, sizeof(struct tt__WideDynamicRange)); 
  46.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Mode = 0;    
  47.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Level = 20; 
  48.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance 
  49. = (struct tt__WhiteBalance*)soap_malloc(soap, sizeof(struct tt__WhiteBalance)); 
  50.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->Mode = 0;   
  51.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CrGain = 0;  
  52.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CbGain = 0;  
  53.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Extension = NULL; 
  54.     trt__GetVideoSourcesResponse->VideoSources[0].Extension = NULL;  
  55.     return SOAP_OK; 

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

四、实现GetProfiles命令


  1. size = 1; 
  2. trt__GetProfilesResponse->Profiles 
  3. =(struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile) * size); 
  4. trt__GetProfilesResponse->__sizeProfiles = size; 

  5. i=0; 
  6. trt__GetProfilesResponse->Profiles[i].Name 
  7. = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  8. strcpy(trt__GetProfilesResponse->Profiles[i].Name,"my_profile"); 
  9. trt__GetProfilesResponse->Profiles[i].token
  10. = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  11. strcpy(trt__GetProfilesResponse->Profiles[i].token,"token_profile"); 
  12. trt__GetProfilesResponse->Profiles[i].fixed = _false; 
  13. trt__GetProfilesResponse->Profiles[i].__anyAttribute = NULL; 

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

先给VideoSourceConfiguration分配空间


  1. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration 
  2. = (struct tt__VideoSourceConfiguration *)soap_malloc(soap
  3. ,sizeof(struct tt__VideoSourceConfiguration )); 
  4. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name 
  5. = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  6. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token 
  7. = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  8. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken 
  9. = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  10. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds 
  11. = (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
  5. ,"GhostyuSource_token"); /*必须与__tmd__GetVideoSources中的token相同*/ 
  6. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->UseCount = 1; 
  7. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->x = 1; 
  8. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->y = 1; 
  9. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->height = 720; 
  10. trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->width = 1280; 

若是是指针必须先用soap_malloc分配内存,而后才能赋值

下面是VideoEncoderConfiguration


  1. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration 
  2. = (struct tt__VideoEncoderConfiguration *)soap_malloc(soap
  3. ,sizeof(struct tt__VideoEncoderConfiguration)); 
  4. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name
  5.  = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  6. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token
  7. = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN); 
  8. strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name,"VE_Name1"); 
  9. strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token,"VE_token1"); 
  10. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->UseCount = 1; 
  11. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Quality = 10; 
  12. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Encoding
  13.  = 1;//JPEG = 0, MPEG4 = 1, H264 = 2; 
  14. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution
  15.  = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution)); 
  16. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Height = 720; 
  17. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Width = 1280; 
  18. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl
  19.  = (struct tt__VideoRateControl *)soap_malloc(soap, sizeof(struct tt__VideoRateControl)); 
  20. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl
  21. ->FrameRateLimit = 30; 
  22. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl
  23. ->EncodingInterval = 1; 
  24. trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl
  25. ->BitrateLimit = 500; 

五、GetVideoSourceConfiguration和GetVideoEncoderConfiguration


  1. int  __trt__GetVideoSourceConfiguration(struct soap* soap
  2. , struct _trt__GetVideoSourceConfiguration *trt__GetVideoSourceConfiguration
  3. , struct _trt__GetVideoSourceConfigurationResponse
  4.  *trt__GetVideoSourceConfigurationResponse) 
  5.     DBG("__trt__GetVideoSourceConfiguration\n"); 
  6.     //该函数必要,live video须要 
  7.     return SOAP_OK; 

  8. int  __trt__GetVideoEncoderConfiguration(struct soap* soap
  9. , struct _trt__GetVideoEncoderConfiguration *trt__GetVideoEncoderConfiguration
  10. , struct _trt__GetVideoEncoderConfigurationResponse
  11.  *trt__GetVideoEncoderConfigurationResponse) 
  12.     DBG("__trt__GetVideoEncoderConfiguration\n"); 
  13.     return SOAP_OK; 

六、GetVideoEncoderConfigurationOptions


  1. int  __trt__GetVideoEncoderConfigurationOptions(struct soap* soap
  2. , struct _trt__GetVideoEncoderConfigurationOptions *trt__GetVideoEncoderConfigurationOptions
  3. , struct _trt__GetVideoEncoderConfigurationOptionsResponse
  4.  *trt__GetVideoEncoderConfigurationOptionsResponse) 
  5.     DBG("__trt__GetVideoEncoderConfigurationOptions\n"); 
  6.     //该函数必要,video streaming须要 
  7.     return SOAP_OK; 

以上五、6不分的代码直接返回SOAP_OK便可,正常来讲是应该填充的,这里不影响RTSP Video Stream,暂时就不去动它

4、运行live555MediaServer服务器

live555官网有不少测试文件,我这里用的是MPEG4的测试文件路劲为rtsp://192.168.1.201/petrov.m4e

5、启动Onvif Device Manager测试

有一个问题,OnvifDeviceManager的并不能自动发现设备(OnvifTestTool能够),还好它提供了手动添加功能

单击add,添加以下内容:http://192.168.1.233/onvif/device_service

注意,我在程序中固定了两个IP:linux192.168.1.233,windows:192.168.1.201,这里需看状况修改

测试截图:

一、Live video

onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接_视频流

二、Video streaming

onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接_视频流_02

三、Profiles

onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接_视频流_03

最后是运行的live555 rtsp服务器

onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接_服务器_04

终端打印的DEBUG信息

onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接_服务器_05



root


上一篇: kissthank
下一篇: c网络编程-多播