(二)Onvif对接RTSP流

onvif对接RTSP数据流


probe功能继续存在,是基于上一篇文章所说的,这一章增加对接RTSP视频流。

各种wsdl文件下载回来,方便以后用!

构建全部onvif架构如下:


./wsdl2h -o onvif.h -c -s -t typemap.dat devicemgmt.wsdl event.wsdl display.wsdl deviceio.wsdl imaging.wsdl media.wsdl ptz.wsdl receiver.wsdl recording.wsdl  search.wsdl remotediscovery.wsdl replay.wsdl analytics.wsdl  analyticsdevice.wsdl onvif.sxd  actionengine.wsdl 

(二)Onvif对接RTSP流_第1张图片

我是放在同一个目录下面的,结尾个东西我会传到csdn上。


错误的解决方法;

1、命令指定了当前目录下的onvif.sxd,如果提示找不到../ver10/schema/onvif.sxd这个错误,反正是有关于can not open onvif.sxd file的错误,就修改对应的wsdl文件,如下:

schemaLocation="../ver10/schema/onvif.sxd",指定schemaLocation的onvif.sxd路径,如果是网络的就指定网络,如果不是就指定本地的(已经下载回来了)。

2、actionengine.wsdl 需要bw-2.wsdl,如果找不到,也可以下载回来。修改actionengine.wsdl指定
我这里没用到actionengine.wsdl。

3、使用TCP和UDP连接

main函数

#define TCP_PORT 80 //onvif device management是使用80端口的,http协议的端口,onvif device managet使用的是http和onvif设备通信.
#define UDP_PORT 3702 //onvif must be
int main(){
	
	pthread_t thrTcp;  
    pthread_t thrUdp;
	int udp_fd;
	udp_fd= create_server_socket_udp();
	pthread_create(&thrTcp,NULL,tcp_server,NULL);
	pthread_create(&thrTcp,NULL,udp_server,&udp_fd);
	while(1);
}
void* udp_server(void* param){
	int* udpSocket;
	int retval=0;
	struct soap *soap_udp;
	udpSocket = (int*)param;
	bind_server_udp(*udpSocket);
	while(1){
		soap_udp=soap_new();

		soap_init1(soap_udp, SOAP_IO_UDP);
		soap_udp->master = * udpSocket;
		soap_udp->socket = * udpSocket;
		printf("skfd:%d \n",* udpSocket);
		soap_udp->errmode = 0;
		soap_udp->bind_flags = 1;
		soap_udp->master = soap_bind(soap_udp, NULL, UDP_PORT, 100);
		if (!soap_valid_socket(soap_udp->master))
		{	 
			soap_print_fault(soap_udp, stderr);
		}
		
		 
	   	struct ip_mreq mreq;
	   	mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
	   	mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	
	    if(setsockopt(*udpSocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))==-1){
		   _DBG_ERROR("memberchip error\n");
	    }
		
		//PRINT_MSG("soap_serve starting..\n");
		retval = soap_serve(soap_udp); //×èÈûÔÚÕâÀï
		PRINT_MSG("retval=%d\n",retval);
		
		soap_destroy(soap_udp);
		soap_end(soap_udp);
		soap_done(soap_udp);
		free(soap_udp);
	}
}

void* tcp_server(void*param)
{ 
	struct soap* soap; 
	
	int ret;  
	int server_tcp;
	struct sockaddr_in local_addr;
	unsigned char one = 1;
	int sock_opt = 1;
	int fault_flag = 0;
	int retval=0;

	server_tcp = create_server_socket_tcp();
	bind_server_tcp(server_tcp);

	while(1)
	{
		soap=soap_new();

		soap_init1(soap, SOAP_ENC_MTOM);
		soap->master = server_tcp;
		soap->socket = server_tcp;
		soap->errmode = 0;
		soap->bind_flags = 1;
		unsigned char one = 1;
		soap->recv_timeout = 1; //设置超时1s
		soap->send_timeout = 1;//设置超时1s
		soap->master = soap_bind(soap, NULL, TCP_PORT, 100);
		if (!soap_valid_socket(soap->master))
		{	 
			soap_print_fault(soap, stderr);
		}
		
		PRINT_MSG("tcp_serve starting..\n");
		int sock = soap_accept(soap);
		if (!soap_valid_socket(sock)){ 
			if (soap->errnum)          
				soap_print_fault(soap, stderr);
			else { 
				fprintf(stderr, "Server timed out (see code how to change this)\n");
				break;        
			}      
		}      
		retval = soap_serve(soap); //×èÈûÔÚÕâÀï
		PRINT_MSG("retval=%d\n",retval);
		if(retval && !(fault_flag))
		{
			fault_flag = 1;
		}
		else if(!retval)
		{
			fault_flag = 0;
		}
		soap_destroy(soap);
		soap_end(soap);
		soap_done(soap);
		free(soap);
	}
	ret = soap->error;
	soap_destroy(soap);
	soap_end(soap);
	soap_done(soap);
	return ret;
}


提示错误:
Error 28 fault is internal [no subcode]
"Address already in use"
Detail: bind failed in soap_bind()

修改soap_bind()函数,使sokect可以重复使用!在此函数调用bind之前增加如下代码:
int sock_opt = 1;
if ((setsockopt(soap->master, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,sizeof (sock_opt))) == -1) {
printf("setsockopt\n");
}

实现以下函数的填充:
__tds__GetDeviceInformation
__tds__GetScopes
__tds__GetCapabilities 
__tds__GetServices
__trt__GetProfiles
__trt__GetProfile
__trt__GetStreamUri
__trt__GetVideoSources
__trt__GetSnapshotUri
__trt__GetVideoEncoderConfigurationOptions 

这些函数可以参考网上的代码!
__trt__GetSnapshotUri
tMediaUri.Uri  = "10.104.15.230:8554/720p.264"; //使用live555 mediaserver

注意:以上的这些函数,在使用soap_malloc为指针分配内存后,必须使用memset把这些指针的值赋值为0,否则容易出现段错误!
结果如下:

(二)Onvif对接RTSP流_第2张图片

使用manager查看,点击左下角的refresh就可以看到对应的了,如下图:

(二)Onvif对接RTSP流_第3张图片


资源下载地址:http://download.csdn.net/detail/liqinghan/9525583



你可能感兴趣的:(onvif)