Onvif协议对前端摄像头的取流是通过标准Rtsp协议,因此我们就需要通过Onvif协议获取到需要预览摄像头的Rtsp的地址,将拿到的RTSP通过VLC或者其他的RTSP客户端取流预览前端摄像头。
通过Onvif协议获取到前端摄像头的Rtsp地址,需要两个步骤:
注:获取的token包含了主码流、辅码流的token已经各种配置的token,可以根据自己需要自取;根据主、辅码流的toekn获取到的是对应主、辅码流的RTSP地址。主、辅码流的RTSP地址不同,但是差异可能不大。
struct soap *stSoapNew = soap_new();
if (stSoapNew == nullptr)
{
return ;
}
soap_set_namespaces(stSoapNew, namespaces); // 设置soap的namespaces
stSoapNew->recv_timeout = 5; // 设置超时5秒(超过指定时间没有数据就退出)
stSoapNew->send_timeout = 5;
stSoapNew->connect_timeout = 5;
soap_set_mode(stSoapNew, SOAP_C_UTFSTRING); // 设置为UTF-8编码,否则叠加中文OSD会乱码
if (stSoapNew == nullptr)
{
printf( "Onvif New Soap error!");
return;
}
// 如果服务要求鉴权,则以下接口就需要加上用户名密码进行鉴权
soap_wsse_add_UsernameTokenDigest(stSoapNew, NULL, pUserName, pPassWord);//对用户名密码进行加密
struct _trt__GetProfiles stProfiles;
struct _trt__GetProfilesResponse stProfilesResponse;
memset(&stProfiles, 0x00, sizeof(stProfiles));
memset(&stProfilesResponse, 0x00, sizeof(stProfilesResponse));
// pProfilesAddr 是soap_call___tds__GetCapabilities接口获取到的media地址,具体实现参见:[获取设备能力](https://blog.csdn.net/u013566528/article/details/102070372)
nRet = soap_call___trt__GetProfiles(stSoapNew, pProfilesAddr, nullptr, &stProfiles, &stProfilesResponse);
if (nRet != SOAP_OK || stProfilesResponse.__sizeProfiles == 0)
{
printf("Get profiles num is %d,error code is %d,labbuf is %s", stProfilesResponse.__sizeProfiles, nRet,stSoapInfo->labbuf);
return;
}
stProfilesResponse.Profiles[i].token; // 后面获取RTSP地址的token
stProfilesResponse.Profiles[i].name; // 是对当前profiles的介绍
struct soap *stSoapNew = soap_new();
if (stSoapNew == nullptr)
{
return ;
}
soap_set_namespaces(stSoapNew, namespaces); // 设置soap的namespaces
stSoapNew->recv_timeout = 5; // 设置超时5秒(超过指定时间没有数据就退出)
stSoapNew->send_timeout = 5;
stSoapNew->connect_timeout = 5;
soap_set_mode(stSoapNew, SOAP_C_UTFSTRING); // 设置为UTF-8编码,否则叠加中文OSD会乱码
if (stSoapNew == nullptr)
{
printf( "Onvif New Soap error!");
return;
}
// 构建请求的结构体
struct tt__StreamSetup ttStreamSetup;
struct tt__Transport ttTransport;
struct _trt__GetStreamUri stStreamUri;
struct _trt__GetStreamUriResponse stStreamUriResp;
memset(&stStreamUri, 0x00, sizeof(stStreamUri));
memset(&stStreamUriResp, 0x00, sizeof(stStreamUriResp));
memset(&ttStreamSetup, 0x00, sizeof(ttStreamSetup));
memset(&ttTransport, 0x00, sizeof(ttTransport));
ttStreamSetup.Stream = tt__StreamType__RTP_Unicast;
ttStreamSetup.Transport = &ttTransport;
ttStreamSetup.Transport->Protocol = tt__TransportProtocol__RTSP;
ttStreamSetup.Transport->Tunnel = NULL;
stStreamUri.StreamSetup = &ttStreamSetup;
stStreamUri.ProfileToken = pMainStreamToken; // 上面获取到的token
// 如果服务要求鉴权,则以下接口就需要加上用户名密码进行鉴权
soap_wsse_add_UsernameTokenDigest(stSoapNew, NULL, pUserName, pPassWord);//对用户名密码进行加密
// pProfilesAddr 是soap_call___tds__GetCapabilities接口获取到的media地址,具体实现参见:[获取设备能力](https://blog.csdn.net/u013566528/article/details/102070372)
int nRet = soap_call___trt__GetStreamUri(stSoapNew , pProfilesAddr, NULL, &stStreamUri, &stStreamUriResp);
if (nRet != ONVIFSDK_NOERROR || stSoapInfo->error != SOAP_OK)
{
printf("Dev ip is %s,ChannelIndex is %d Gsoap return is %d labbuf is %s", m_pIpInfo, nChannelIndex, nRet, stSoapInfo->labbuf);
return;
}
stStreamUriResp.MediaUri->Uri; // 这个就是获取到的摄像头实时预览的RTSP地址
至此,通过Onvif协议获取到了RTSP地址,通过RTSP客户端就可以预览前端摄像头的实时视频了。