zoukankan      html  css  js  c++  java
  • onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接

    有了前几篇的基础,现在可以正式开始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 . ypemap.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 .	ypemap.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.   
    7.     server_udp = create_server_socket_udp();  
    8.     //bind_server_udp1(server_udp);   
    9.     pthread_t thrHello;  
    10.     pthread_t thrProbe;  
    11.     //pthread_create(&thrHello,NULL,main_Hello,server_udp);   
    12.     //sleep(2);   
    13.     pthread_create(&thrProbe,NULL,main_Probe,server_udp);  
    14.   
    15.     soap_init(&add_soap);    
    16.     soap_set_namespaces(&add_soap, namespaces);    
    17.   
    18.   
    19.     if (argc < 0) {    
    20.         printf("usage: %s <server_port>  ", argv[0]);    
    21.         exit(1);    
    22.     } else {    
    23.         m = soap_bind(&add_soap, NULL, 80, 100);    
    24.         if (m < 0) {    
    25.             soap_print_fault(&add_soap, stderr);    
    26.             exit(-1);    
    27.         }    
    28.         fprintf(stderr, "Socket connection successful: master socket = %d ", m);    
    29.         for (;;) {    
    30.             s = soap_accept(&add_soap);    
    31.             if (s < 0) {    
    32.                 soap_print_fault(&add_soap, stderr);    
    33.                 exit(-1);    
    34.             }    
    35.             fprintf(stderr, "Socket connection successful: slave socket = %d ", s);    
    36.             soap_serve(&add_soap);    
    37.             soap_end(&add_soap);    
    38.         }    
    39.     }    
    40.     return 0;    
    41. }   
    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> 
    ", 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
    ", 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
    ", 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.   
    10. tds__GetCapabilitiesResponse->Capabilities->Extension->Display = NULL;  
    11. tds__GetCapabilitiesResponse->Capabilities->Extension->Recording = NULL;  
    12. tds__GetCapabilitiesResponse->Capabilities->Extension->Search = NULL;  
    13. tds__GetCapabilitiesResponse->Capabilities->Extension->Replay = NULL;  
    14. tds__GetCapabilitiesResponse->Capabilities->Extension->Receiver = NULL;  
    15. tds__GetCapabilitiesResponse->Capabilities->Extension->AnalyticsDevice = NULL;  
    16. tds__GetCapabilitiesResponse->Capabilities->Extension->Extensions = NULL;  
    17. tds__GetCapabilitiesResponse->Capabilities->Extension->__size = 0;  
    18. 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 ");  
    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.   
    10.     tds__GetServicesResponse->Service = (struct tds__Service *)soap_malloc(soap, sizeof(struct tds__Service));  
    11.     tds__GetServicesResponse->Service[0].XAddr = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);  
    12.     tds__GetServicesResponse->Service[0].Namespace = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);  
    13.     strcpy(tds__GetServicesResponse->Service[0].Namespace, "http://www.onvif.org/ver10/events/wsdl");  
    14.     strcpy(tds__GetServicesResponse[0].Service->XAddr, _IPAddr);  
    15.     tds__GetServicesResponse->Service[0].Capabilities = NULL;  
    16.     tds__GetServicesResponse->Service[0].Version = (struct tt__OnvifVersion *)soap_malloc(soap, sizeof(struct tt__OnvifVersion));  
    17.     tds__GetServicesResponse->Service[0].Version->Major = 0;  
    18.     tds__GetServicesResponse->Service[0].Version->Minor = 3;  
    19.     tds__GetServicesResponse->Service[0].__any = (char **)soap_malloc(soap, sizeof(char *));  
    20.     tds__GetServicesResponse->Service[0].__any[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);  
    21.     strcpy(tds__GetServicesResponse->Service[0].__any[0],"why1");  
    22.     tds__GetServicesResponse->Service[0].__any[1] = (char *)soap_malloc(soap,sizeof(char) * INFO_LENGTH);  
    23.     strcpy(tds__GetServicesResponse->Service[0].__any[1],"why2");  
    24.     tds__GetServicesResponse->Service[0].__size = NULL;  
    25.     tds__GetServicesResponse->Service[0].__anyAttribute = NULL;  
    26.     return SOAP_OK;  
    27. }  
    int  __tds__GetServices(struct soap* soap, struct _tds__GetServices *tds__GetServices, struct _tds__GetServicesResponse *tds__GetServicesResponse)
    {
    	DBG("__tds__GetServices
    ");
    	/*该函数很必要*/
    	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 ");  
    4.   
    5.     int size1;  
    6.     size1 = 1;  
    7.     trt__GetVideoSourcesResponse->__sizeVideoSources = size1;  
    8.     trt__GetVideoSourcesResponse->VideoSources = (struct tt__VideoSource *)soap_malloc(soap, sizeof(struct tt__VideoSource) * size1);  
    9.     trt__GetVideoSourcesResponse->VideoSources[0].Framerate = 30;  
    10.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));  
    11.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Height = 720;  
    12.     trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Width = 1280;  
    13.     trt__GetVideoSourcesResponse->VideoSources[0].token = (char *)soap_malloc(soap, sizeof(char)*INFO_LENGTH);  
    14.     strcpy(trt__GetVideoSourcesResponse->VideoSources[0].token,"GhostyuSource_token"); //注意这里需要和GetProfile中的sourcetoken相同  
    15.   
    16.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging =(struct tt__ImagingSettings*)soap_malloc(soap, sizeof(struct tt__ImagingSettings));  
    17.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness = (float*)soap_malloc(soap,sizeof(float));  
    18.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness[0] = 128;  
    19.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation = (float*)soap_malloc(soap,sizeof(float));  
    20.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation[0] = 128;  
    21.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast = (float*)soap_malloc(soap,sizeof(float));  
    22.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast[0] = 128;  
    23.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = (int *)soap_malloc(soap,sizeof(int));  
    24.     *trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = 0;   
    25.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness = (float*)soap_malloc(soap,sizeof(float));  
    26.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness[0] = 128;  
    27.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation = (struct tt__BacklightCompensation*)soap_malloc(soap, sizeof(struct tt__BacklightCompensation));  
    28.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Mode = 0;  
    29.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Level = 20;  
    30.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Exposure = NULL;  
    31.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Focus = NULL;  
    32.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange = (struct tt__WideDynamicRange*)soap_malloc(soap, sizeof(struct tt__WideDynamicRange));  
    33.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Mode = 0;     
    34.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Level = 20;  
    35.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance = (struct tt__WhiteBalance*)soap_malloc(soap, sizeof(struct tt__WhiteBalance));  
    36.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->Mode = 0;   
    37.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CrGain = 0;   
    38.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CbGain = 0;   
    39.     trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Extension = NULL;  
    40.     trt__GetVideoSourcesResponse->VideoSources[0].Extension = NULL;    
    41.     return SOAP_OK;  
    42. }  
    int  __tmd__GetVideoSources(struct soap* soap, struct _trt__GetVideoSources *trt__GetVideoSources, struct _trt__GetVideoSourcesResponse *trt__GetVideoSourcesResponse)
    {
    	DBG("__tmd__GetVideoSources
    ");
    
    	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.   
    5. i=0;  
    6. trt__GetProfilesResponse->Profiles[i].Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    7. strcpy(trt__GetProfilesResponse->Profiles[i].Name,"my_profile");  
    8. trt__GetProfilesResponse->Profiles[i].token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);  
    9. strcpy(trt__GetProfilesResponse->Profiles[i].token,"token_profile");  
    10. trt__GetProfilesResponse->Profiles[i].fixed = _false;  
    11. 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 ");  
    4.     //该函数必要,live video需要   
    5.     return SOAP_OK;  
    6. }  
    7.   
    8. int  __trt__GetVideoEncoderConfiguration(struct soap* soap, struct _trt__GetVideoEncoderConfiguration *trt__GetVideoEncoderConfiguration, struct _trt__GetVideoEncoderConfigurationResponse *trt__GetVideoEncoderConfigurationResponse)  
    9. {  
    10.     DBG("__trt__GetVideoEncoderConfiguration ");  
    11.     return SOAP_OK;  
    12. }  
    int  __trt__GetVideoSourceConfiguration(struct soap* soap, struct _trt__GetVideoSourceConfiguration *trt__GetVideoSourceConfiguration, struct _trt__GetVideoSourceConfigurationResponse *trt__GetVideoSourceConfigurationResponse)
    {
    	DBG("__trt__GetVideoSourceConfiguration
    ");
    	//该函数必要,live video需要
    	return SOAP_OK;
    }
    
    int  __trt__GetVideoEncoderConfiguration(struct soap* soap, struct _trt__GetVideoEncoderConfiguration *trt__GetVideoEncoderConfiguration, struct _trt__GetVideoEncoderConfigurationResponse *trt__GetVideoEncoderConfigurationResponse)
    {
    	DBG("__trt__GetVideoEncoderConfiguration
    ");
    	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 ");  
    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
    ");
    	//该函数必要,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

  • 相关阅读:
    Redis(三)、Redis主从复制
    Redis(二)、Redis持久化RDB和AOF
    Redis(一)、Redis五种数据结构
    docker(部署常见应用):docker部署redis
    docker(三):Harbor 1.8.0 仓库的安装和使用
    Redis List 命令技巧
    数据库——MySQL——事务
    数据库——MySQL
    数据库——MySQL——权限管理
    数据库——MySQL——多表查询
  • 原文地址:https://www.cnblogs.com/shakin/p/3714851.html
Copyright © 2011-2022 走看看