在之前很長時間對于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