Table of Contents

VAST.ONVIF Library

The VAST.ONVIF library provides a client implementation for communicating with ONVIF-compliant IP cameras and video encoders. It supports device discovery, media profile retrieval, streaming URI extraction, PTZ camera control, snapshot capture, and event subscriptions.

Overview

Feature Description
Device Discovery Find ONVIF devices on the network using WS-Discovery
Device Information Retrieve manufacturer, model, firmware, serial, and MAC address
Media Profiles Enumerate available media profiles with video/audio configuration
Streaming URIs Get RTSP URIs for all supported transport modes
PTZ Control Pan, tilt, zoom control for PTZ-capable cameras
Snapshots Capture still images from cameras
Event Subscription Subscribe to pullpoint notifications for motion detection, I/O events

Requirements

Device Discovery

The OnvifDiscovery class discovers ONVIF devices on the network using the WS-Discovery protocol.

Basic Discovery

// Discover devices with 5-second timeout
var devices = await VAST.ONVIF.OnvifDiscovery.SearchAsync(5000);

foreach (var device in devices)
{
    Console.WriteLine($"Found: {device.IPAddress}");
    Console.WriteLine($"  MAC: {device.MacAddress}");
    Console.WriteLine($"  ONVIF Address: {device.OnvifAddress}");
}

Network Interface Selection

By default, discovery runs on all active network interfaces. To specify interfaces manually:

// Clear auto-detected interfaces
VAST.ONVIF.OnvifDiscovery.Nics.Clear();

// Add specific interface
VAST.ONVIF.OnvifDiscovery.Nics.Add(new VAST.ONVIF.NetworkInterface
{
    IPAddress = "192.168.1.100"
});

var devices = await VAST.ONVIF.OnvifDiscovery.SearchAsync(5000);

Vendor Filtering

Filter discovery results by MAC address prefix to find devices from specific manufacturers:

// Filter for Axis cameras (MAC prefix)
VAST.ONVIF.OnvifDiscovery.VendorMacFilter = "00:40:8C";

var devices = await VAST.ONVIF.OnvifDiscovery.SearchAsync(5000);

Discovered Device Information

The DiscoveredDevice class contains:

Property Description
IPAddress Device IP address
MacAddress Device MAC address
OnvifAddress ONVIF service endpoint URL
UpnpServiceAddress UPnP service URL (if available)
Model Device model name
FirmwareVersion Device firmware version

ONVIF Client

The library provides two client implementations for different ONVIF profiles:

Client ONVIF Profile Description
OnvifClient1 Profile S (Media) Standard streaming profile for live video
OnvifClient2 Profile T (Media2) Advanced profile with H.265 support and recording playback

Both clients share the same base interface (IOnvifClient) and provide identical functionality for device information, streaming URIs, PTZ control, and snapshots. Use OnvifClient2 for newer cameras that support ONVIF Profile T, or when you need access to recording search and replay features.

Connecting to a Device

VAST.ONVIF.IOnvifClient client = null;
try
{
    // First let's try OnvifClient2 (Profile T / Media2)
    client = new VAST.ONVIF.OnvifClient2(
        "http://192.168.1.100:80/onvif/device_service",
        "admin",
        "password"
    );

    await client.OpenAsync();
}
catch (Exception)
{
    // OnvifClient2 failed, fall back to OnvifClient1 (Profile S)
    try
    {
        client = new VAST.ONVIF.OnvifClient1(
            "http://192.168.1.100:80/onvif/device_service",
            "admin",
            "password"
        );

        await client.OpenAsync();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Connection failed: {ex.Message}");
        client = null;
    }
}

if (client != null)
{
    Console.WriteLine($"Manufacturer: {client.Manufacturer}");
    Console.WriteLine($"Model: {client.Model}");
    Console.WriteLine($"Firmware: {client.Firmware}");
    Console.WriteLine($"Serial: {client.Serial}");
    Console.WriteLine($"MAC: {client.MACAddress}");
}

Device Properties

After calling OpenAsync(), the following properties are available:

Property Description
IP Device IP address
Port Device port number
Manufacturer Device manufacturer name
Model Device model name
Firmware Firmware version
Serial Serial number
HwID Hardware identifier
MACAddress MAC address
StreamingUris List of available streaming URIs
CameraControl PTZ camera control interface

Media Profiles and Streaming URIs

After connecting, the client retrieves all available media profiles and their streaming URIs.

Accessing Streaming URIs

await client.OpenAsync();

foreach (var uri in client.StreamingUris)
{
    Console.WriteLine($"Profile: {uri.Profile.Name}");
    Console.WriteLine($"  URI: {uri.Uri}");
    Console.WriteLine($"  Transport: {uri.RtpTransportType} ({uri.RtpTransportCast})");

    // Access media type information
    foreach (var stream in uri.Profile.Streams)
    {
        if (stream.ContentType == VAST.Common.ContentType.Video)
        {
            Console.WriteLine($"  Video: {stream}");
        }
        else if (stream.ContentType == VAST.Common.ContentType.Audio)
        {
            Console.WriteLine($"  Audio: {stream}");
        }
    }
}

Transport Types

Each media profile may provide multiple streaming URIs with different transport configurations:

Transport Cast Description
UDP Unicast Standard RTP over UDP (default)
UDP Multicast RTP multicast streaming
TCP Interleaved Unicast RTP interleaved over RTSP TCP connection
HTTP Tunnel Unicast RTP tunneled over HTTP for firewall traversal

Using Streaming URIs with RTSP Source

await client.OpenAsync();

// Get the first available streaming URI
var streamUri = client.StreamingUris.FirstOrDefault();
if (streamUri != null)
{
    var rtspSource = new VAST.RTSP.RtspClientSource();
    rtspSource.Uri = streamUri.Uri;

    rtspSource.StateChanged += (sender, state) =>
    {
        if (state == MediaState.Opened)
        {
            rtspSource.Start();
        }
    };

    rtspSource.Open();
}

PTZ Camera Control

For PTZ-capable cameras, the CameraControl property provides access to pan, tilt, and zoom functionality through the ICameraControl interface.

Checking PTZ Support

await client.OpenAsync();

if (client.CameraControl != null)
{
    Console.WriteLine("PTZ is supported");

    if (client.CameraControl.IsPanTiltSupported)
    {
        Console.WriteLine("  Pan/Tilt supported");
    }

    if (client.CameraControl.IsZoomSupported)
    {
        Console.WriteLine("  Zoom supported");
    }
}

Continuous Movement

var ptz = client.CameraControl;

// Start continuous pan/tilt movement
// Speed values range from -1.0 to +1.0
ptz.SetPanTiltSpeed(0.5f, 0.0f);  // Pan right at half speed

// Stop movement
ptz.StopPanTilt();

// Continuous zoom
ptz.SetZoomSpeed(0.3f);  // Zoom in slowly

// Stop zoom
ptz.StopSmoothZoom();

Absolute Positioning

var ptz = client.CameraControl;

// Move to absolute position
// Pan/tilt values typically range from -1.0 to +1.0
ptz.SetPanTilt(0.5f, -0.2f);

// Set absolute zoom level (ptz.MinZoom to ptz.MaxZoom)
ptz.CurrentZoom = 0.5f;

Presets

var ptz = client.CameraControl;

// Store current position as preset
// Preset number -1 means home position
ptz.StorePreset(1);

// Recall preset with movement speed
ptz.RecallPreset(1, 0.5f);

Snapshot Capture

Capture still images from cameras that support the ONVIF snapshot feature.

await client.OpenAsync();

try
{
    using (var stream = await client.TakeSnapshot())
    {
        // Save to file
        using (var fileStream = File.Create("snapshot.jpg"))
        {
            await stream.CopyToAsync(fileStream);
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Snapshot failed: {ex.Message}");
}

Resource Cleanup

Always dispose of the client when finished to release event subscriptions and network resources:

var client = new VAST.ONVIF.OnvifClient1(uri, username, password);

try
{
    await client.OpenAsync();
    // Use client...
}
finally
{
    client.Dispose();
}

Or use the using pattern:

using (var client = new VAST.ONVIF.OnvifClient1(uri, username, password))
{
    await client.OpenAsync();
    // Use client...
}

Troubleshooting

Common Issues

Issue Cause Solution
Discovery finds no devices Firewall blocking WS-Discovery Allow UDP port 3702
Authentication failure Wrong credentials or time sync Verify credentials; check device time
No streaming URIs Incorrect credentials Profiles require authentication
PTZ not available Camera not PTZ-capable Check CameraControl is not null
Connection timeout Wrong port or IP Verify device address and port

Time Synchronization

ONVIF authentication uses WS-Security with timestamp validation. If the client and device clocks differ significantly, authentication may fail. The library automatically detects and compensates for time differences, but large discrepancies (>5 seconds) may cause issues.

HTTPS Support

The client supports both HTTP and HTTPS connections:

// HTTP connection (default port 80)
var client = new VAST.ONVIF.OnvifClient1(
    "http://192.168.1.100/onvif/device_service",
    "admin", "password");

// HTTPS connection (default port 443)
var client = new VAST.ONVIF.OnvifClient1(
    "https://192.168.1.100/onvif/device_service",
    "admin", "password");

See Also