1.概述
在我们使用onvif对接监控,使用onvif获取到的rtsp地址取流时,会出现这样的一种应用场景,只取流一路rtsp流,分发给多个客户端进行显示,客户端取流的时间点不相同,此时如果摄像头的关键帧间隔设置的很大,那么其余后续的客户端就需要等待摄像头编码出下一个关键帧才能进行显示,这样需要等待很长的时间,体验很差。我们可以通过onvif向摄像头发送插入关键帧的请求来优化这种情况。
2.整个流程使用到的接口
3.demo
//OnvifTool.h
#include "stdsoap2.h"
#include "soapH.h"
#include "soapStub.h"
#include "wsseapi.h"
#include <string>
using namespace std;
class OnvifTool
{
public:
OnvifTool();
~OnvifTool();
bool GetCapabilities(const string& ip, uint16_t port, const string& userName,
const string& password, string& xAddr);
bool GetProfiles(const string& userName, const string& password, const string& xAddr,
string& profileToken);
bool SetSynchronizationPoint(const string& userName, const string& password,
const string& xAddr, const string& profileToken);
private:
void InitSoap(soap *pSoap);
void FreeSoap(soap *pSoap);
soap* m_pSoap;
};
// OnvifTool.cxx
// 只获取第一个profile文件来做测试
#include "OnvifTool.h"
#include <iostream>
OnvifTool::OnvifTool()
{
m_pSoap = soap_new();
}
OnvifTool::~OnvifTool()
{
if (m_pSoap) {
FreeSoap(m_pSoap);
soap_free(m_pSoap);
}
}
bool OnvifTool::GetCapabilities(const string& ip, uint16_t port, const string& userName,
const string& password, string& xAddr)
{
InitSoap(m_pSoap);
char endp[128] = {0};
if (port != 0)
snprintf(endp, sizeof(endp), "http://%s:%d/onvif/device_service", ip, port);
else
snprintf(endp, sizeof(endp), "http://%s/onvif/device_service", ip);
struct _tds__GetCapabilities req;
struct _tds__GetCapabilitiesResponse resp;
req.Category.push_back(tt__CapabilityCategory__All); //获取所有能力
soap_wsse_add_UsernameTokenDigest(m_pSoap, NULL, userName.c_str(),
password.c_str());
int ret = soap_call___tds__GetCapabilities(m_pSoap, endp, NULL,
&req, resp);
if (ret != SOAP_OK) {
cout << "GetCapabilities failed!!!!" << endl;
FreeSoap(m_pSoap);
return false;
}
if (resp.Capabilities && resp.Capabilities->Media
&& resp.Capabilities->Media->XAddr) {
xAddr = resp.Capabilities->Media->XAddr;
cout << "GetCapabilities success, xAddr=" << xAddr << endl;
FreeSoap(m_pSoap);
return true;
}
cout << "GetCapabilities failed!!!!" << endl;
FreeSoap(m_pSoap);
return false;
}
bool OnvifTool::GetProfiles(const string& userName,const string& password,
string& xAddr, const string& profileToken)
{
InitSoap(m_pSoap);
struct _trt__GetProfiles req;
struct _trt__GetProfilesResponse resp;
soap_wsse_add_UsernameTokenDigest(m_pSoap, NULL, userName.c_str(),
password.c_str());
int ret = soap_call___trt__GetProfiles(m_pSoap, xAddr.c_str(), NULL, &req, resp);
if (ret != SOAP_OK) {
cout << "GetProfiles failed!!!!" << endl;
FreeSoap(m_pSoap);
return false;
}
if (resp.Profiles.size() > 0) {
// 只取第一个profile做测试
profileToken = resp.Profiles[0]->token;
cout << "GetProfiles success, profileToken=" << profileToken << endl;
FreeSoap(m_pSoap);
return true;
}
cout << "GetProfiles failed!!!!" << endl;
FreeSoap(m_pSoap);
return false;
}
bool OnvifTool::SetSynchronizationPoint(const string& userName, const string& password,
const string& xAddr, const string& profileToken)
{
InitSoap(m_pSoap);
struct _trt__SetSynchronizationPoint req;
struct _trt__SetSynchronizationPointResponse resp;
req.ProfileToken = profileToken;
soap_wsse_add_UsernameTokenDigest(m_pSoap, NULL, userName.c_str(), password.c_str());
int ret = soap_call___trt__SetSynchronizationPoint(m_pSoap, xAddr.c_str(), NULL,
&req, resp);
if (ret != SOAP_OK) {
cout << "SetSynchronizationPoint failed!!!!" << endl;
FreeSoap(m_pSoap);
return false;
}
cout << "SetSynchronizationPoint success" << endl;
FreeSoap(m_pSoap);
return true;
}
void OnvifTool::InitSoap(soap *pSoap)
{
soap_init(pSoap);
pSoap->recv_timeout = 1;
pSoap->send_timeout = 1;
pSoap->connect_timeout = 1;
soap_set_namespaces(pSoap, namespaces);
}
void OnvifTool::FreeSoap(soap *pSoap)
{
soap_destroy(pSoap);
soap_end(pSoap);
soap_done(pSoap);
}
// main.cxx
#include "OnvifTool.h"
int main()
{
string ip = "192.168.1.2";
string userName = "admin";
string password = "admin";
uint16_t port = 80;
string xAddr, profileToken;
OnvifTool tool;
bool ret = tool.GetCapabilities(ip, port, userName, password, xAddr);
if (!ret)
return -1;
ret = tool.GetProfiles(userName, password, xAddr, profileToken);
if (!ret)
return -1;
ret = tool.SetSynchronizationPoint(userName, password, xAddr, profileToken);
if (!ret)
return -1;
return 0;
}