天天看点

Onvif协议初步探究

在之前很长时间对于GB28181协议的研究过后,发现很多国际品牌摄像头在对接过程中不支持GB28181协议,对于这些品牌大多数还是支持一个国际化的设备发现协议--------Onvif协议。那么今天就过来谈一谈自己对Onvif协议的初见解。

    首先,我们来看一下什么是web service:

    Web Services初学者,gSOAP可能是他们入手的最开始的工具,这样就不用我们重复的实现别人已经造好的轮子。对于众多的概念,我们先放在一边,从总体上面了解一下:
           

1、Web Services是一种网络服务,它对外提供了一系列远程调用接口(RPC),你可以像本地调用一样去调用这些远程调用接口。

2、Web Services常用的框架有多种,ONVIF标准中的Web Service采用的是SOAP方式。

3、WSDL文档是采用SOAP方式实现的Web Services的接口描述文档,就像动态库的.h文件一样。同时也展示了WSDL语言转化为C语言的对比效果。

其次,我们要知道我们通过Onvif协议可以干什么:

     在很多工程中,我感觉最实用的应该是设备发现、鉴权、获取rtspUri这么三个功能,因为对于监控项目中,最关心的环节莫过于如何取流,以及如何进行在网络环境中发现设备。
     那我们首先看一下设备发现是如何做到的:
     开启线程:
     void probeCallback(DEVICE_BINFO * p_res, void * p_data)
           

{

ONVIF_DEVICE_EX * p_dev = NULL;

ONVIF_DEVICE_EX device;

memset(&device, 0, sizeof(ONVIF_DEVICE_EX));

memcpy(&device.onvif_device.binfo, p_res, sizeof(DEVICE_BINFO));
device.state = 1;

p_dev = findDevice(&device);
if (p_dev == NULL)
{
    printf("Found device. ip : %s, port : %d\n", p_res->XAddr.host, p_res->XAddr.port);

    p_dev = addDevice(&device);
    if (p_dev)
    {
        p_dev->thread_handler = sys_os_create_thread((void *)getDevInfoThread, p_dev);
    }
}
else 
{
    if (p_dev->no_res_nums >= 2 && 0 == p_dev->thread_handler)
    {
        p_dev->thread_handler = sys_os_create_thread((void *)getDevInfoThread, p_dev);
    }

    p_dev->no_res_nums = 0; 
    p_dev->state = 1;
}
           

}

处理信令交互的内容:

void * getDevInfoThread(void * argv)

{

char profileToken[ONVIF_TOKEN_LEN];

ONVIF_Profile * p_profile = NULL;

ONVIF_DEVICE_EX * p_device = (ONVIF_DEVICE_EX *) argv;

GetCapabilities(&p_device->onvif_device);

GetServices(&p_device->onvif_device);

GetDeviceInformation(&p_device->onvif_device);

GetVideoSources(&p_device->onvif_device);

GetImagingSettings(&p_device->onvif_device);

GetVideoSourceConfigurations(&p_device->onvif_device);

GetVideoEncoderConfigurations(&p_device->onvif_device);

if (GetAudioSources(&p_device->onvif_device))
{
    GetAudioSourceConfigurations(&p_device->onvif_device);  

    GetAudioEncoderConfigurations(&p_device->onvif_device);
}

/* save currrent profile token */

if (p_device->onvif_device.curProfile)
{
    strcpy(profileToken, p_device->onvif_device.curProfile->token);
}
else
{
    memset(profileToken, 0, sizeof(profileToken));
}

GetProfiles(&p_device->onvif_device);

GetStreamUris(&p_device->onvif_device);
ONVIF_Profile *temp = p_device->onvif_device.profiles;
//获取到他所有码流
//while (temp) {
    printf("name:%s-----stream_uri:%s\n", temp->name, temp->stream_uri);
//  temp = temp->next;
//}
/* resume current profile */
    printf("Token is----------->:%s\n",profileToken);
if (profileToken[0] != '\0')
{
    p_profile = onvif_find_Profile(&p_device->onvif_device, profileToken);
}

if (NULL == p_profile)
{
    p_profile = p_device->onvif_device.profiles;
}

p_device->onvif_device.curProfile = p_profile;

if (p_device->onvif_device.Capabilities.ptz.support)
{
    GetNodes(&p_device->onvif_device);

    GetConfigurations(&p_device->onvif_device);
}

if (p_device->onvif_device.Capabilities.media.SnapshotUri == 1 && p_profile)
{
    int len;
    unsigned char * p_buff;

    if (GetSnapshot(&p_device->onvif_device, p_profile->token, &p_buff, &len))
    {
        if (p_device->p_snapshot)
        {
            FreeSnapshotBuff(p_device->p_snapshot);
            p_device->p_snapshot = NULL;
            p_device->snapshot_len = 0;
        }

        p_device->p_snapshot = p_buff;
        p_device->snapshot_len = len;
    }
}

if (p_device->onvif_device.Capabilities.events.support == 1 && 
    p_device->onvif_device.events.subscribe == FALSE)
{
    // the caller should call Unsubscribe when free this device
    Subscribe(&p_device->onvif_device, pps_get_index(m_dev_ul, p_device));
}

onvifUserTest(p_device);

if (p_device->onvif_device.Capabilities.image.support)
{
    onvifImageTest(p_device);
}

if (p_device->onvif_device.Capabilities.media2.support)
{
    onvifMedia2Test(p_device);
}

if (p_device->onvif_device.Capabilities.accesscontrol.support)
{
    onvifAccessControlTest(p_device);
}

if (p_device->onvif_device.Capabilities.doorcontrol.support)
{
    onvifDoorControlTest(p_device);
}

if (p_device->onvif_device.Capabilities.recording.support)
{
    onvifRecordingTest(p_device);
}

p_device->thread_handler = 0;

return NULL;
           

}

然后里面就可以发现到设备,并且鉴权通过,并且最终获取到每个设备中的主码流、子码流的rtsp地址了。

配合程序测试连接:http://download.csdn.net/download/qq_24798461/9984271

最后:

如果有想联系我做技术交流的,可以联系我qq: 1015787417

继续阅读