onvif对接RTSP数据流
构建全部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指定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;
}
修改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