天天看點

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

繼續閱讀