Get ONVIF Stream URI (RTSP/RTP)

Retrieve the streaming address from an ONVIF device using the Happytimesoft Client Library in C. Examples for default and custom protocols.

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:

C Code: getDevInfo1 (from onviftest)
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.

C Code: Media 1 GetStreamUri
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:

C Code: Media 2 GetStreamUri (from onviftest)
// 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) requires GetProfiles to have been called first; it then fills every profile's stream_uri.
  • The ProfileToken identifies a media profile (e.g., main or sub stream) — use the same token that GetProfiles returned.
  • Media 2 uses string protocol names ("RtspUnicast", "UdpUnicast", "TCPUnicast", "RtspOverHttp"); Media 1 uses the TransportProtocol_* enum.
  • Always check the return value of API calls and inspect errCode / fault on failure.
  • The resulting URI can be used in media players (VLC) or libraries (FFmpeg) to decode the stream.