Introduction
Once connected to an ONVIF device, you often need to retrieve its video/audio stream URI to consume the media (e.g., via an RTSP player or FFmpeg). The Happytimesoft ONVIF Client Library provides several ways to do this. The code examples below are taken from the official onviftest.cpp test program.
Method 1: Use the high-level GetStreamUris() helper, which retrieves the stream URI for every profile in one call.
Method 2: Issue a GetStreamUri request directly (Media 1 or Media 2) to get a URI for a specific profile with a chosen transport protocol.
Method 1: Get Stream URIs for All Profiles
The library's high-level helper GetStreamUris(ONVIF_DEVICE *, TransportProtocol) first needs the device profiles to be loaded (via GetProfiles), then fills the stream_uri field of every profile. This is how the test program initializes all stream addresses:
BOOL getDevInfo1(ONVIF_DEVICE_EX * p_device)
{
// Load the media profiles first
if (!GetProfiles(&p_device->onvif_device))
{
return FALSE;
}
// Get the RTSP stream URI for every profile (RTP over RTSP)
if (!GetStreamUris(&p_device->onvif_device, TransportProtocol_RTSP))
{
return FALSE;
}
return TRUE;
}
After this call, each profile in p_device->onvif_device.profiles has its stream_uri field populated with an address of the form rtsp://[IP]:[PORT]/[STREAM_PATH].
Method 2a: GetStreamUri via Media 1
For fine-grained control over the transport protocol, call onvif_trt_GetStreamUri (Media 1 service) with a request that specifies the stream setup and profile token.
ONVIF_DEVICE * p_dev = &p_device->onvif_device;
// Build the request
trt_GetStreamUri_REQ req;
trt_GetStreamUri_RES res;
memset(&req, 0, sizeof(req));
memset(&res, 0, sizeof(res));
// Stream type: unicast or multicast
req.StreamSetup.Stream = StreamType_RTP_Unicast;
// Transport protocol: UDP, TCP (RTSP), or HTTP
req.StreamSetup.Transport.Protocol = TransportProtocol_UDP;
// Options: TransportProtocol_UDP, TransportProtocol_TCP,
// TransportProtocol_RTSP, TransportProtocol_HTTP
// Identify the media profile
strcpy(req.ProfileToken, p_profile->token);
if (onvif_trt_GetStreamUri(p_dev, &req, &res))
{
printf("profile=%s, uri=%s\n", req.ProfileToken, res.Uri);
strcpy(p_profile->stream_uri, res.Uri);
}
Method 2b: GetStreamUri via Media 2
If the device supports the ONVIF Media 2 service, use onvif_tr2_GetStreamUri. Note that Media 2 uses a string protocol name (e.g., "RtspUnicast") instead of an enum. This is exactly how the test program retrieves the URI for each Media 2 profile:
// tr2_GetProfiles already filled res.Profiles
tr2_GetStreamUri_REQ req1;
tr2_GetStreamUri_RES res1;
memset(&req1, 0, sizeof(req1));
memset(&res1, 0, sizeof(res1));
// Media 2 uses a string protocol, e.g. "RtspUnicast"
strcpy(req1.Protocol, "RtspUnicast");
strcpy(req1.ProfileToken, res.Profiles->MediaProfile.token);
ret = onvif_tr2_GetStreamUri(&p_device->onvif_device, &req1, &res1);
if (ret)
{
printf("onvif_tr2_GetStreamUri, profile=%s, uri=%s\n", req1.ProfileToken, res1.Uri);
}
Note: The Media 2 high-level helper is tr2_GetStreamUris(ONVIF_DEVICE *, "RTSP"), which fills stream URIs for all Media 2 profiles (used in getDevInfo2 in the test program).
Protocol Comparison
| Protocol | Media 1 enum / Media 2 string | Notes |
|---|---|---|
| RTP over RTSP | TransportProtocol_RTSP / "RtspUnicast" |
Standard method; most common for live viewing. |
| RTP over UDP | TransportProtocol_UDP / "UdpUnicast" |
Lower overhead, but may be blocked by firewalls. |
| RTP over TCP | TransportProtocol_TCP / "TCPUnicast" |
Reliable through most firewalls. |
| RTP over HTTP | TransportProtocol_HTTP / "RtspOverHttp" |
HTTP tunneling for restrictive firewall environments. |
Key Notes
GetStreamUris(ONVIF_DEVICE *, TransportProtocol)requiresGetProfilesto have been called first; it then fills every profile'sstream_uri.- The
ProfileTokenidentifies a media profile (e.g., main or sub stream) — use the same token thatGetProfilesreturned. - Media 2 uses string protocol names (
"RtspUnicast","UdpUnicast","TCPUnicast","RtspOverHttp"); Media 1 uses theTransportProtocol_*enum. - Always check the return value of API calls and inspect
errCode/faulton failure. - The resulting URI can be used in media players (VLC) or libraries (FFmpeg) to decode the stream.