(二)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 

我是放在同一个目录下面的,结尾个东西我会传到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指定<xs:import namespace="http://docs.oasis-open.org/wsn/b-2" schemaLocation="b-2.xsd"/>
我这里没用到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;
	<span style="white-space:pre">	</span>soap->recv_timeout = 1; //设置超时1s
<span style="white-space:pre">		</span>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,否则容易出现段错误!
结果如下:


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



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



  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

john_liqinghan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值