A comprehensive guide for using RtspGStreamerLib to capture RTSP video frames in .NET applications.
RtspGStreamerLib provides a simple API to capture frames from RTSP video streams using GStreamer. It uses direct P/Invoke calls to the native GStreamer libraries, eliminating the need for any NuGet dependencies.
- Direct P/Invoke - No NuGet dependencies, uses system-installed GStreamer
- Frame callbacks - Process each frame in memory as it arrives
- Hardware acceleration - Automatic HW decoding support on ARM64 devices
- H.265/HEVC support - Full codec support (H.264 also available)
- BGR format - Output ready for OpenCV and computer vision processing
- Multi-platform - Windows x64, Linux x64, Linux ARM64
sudo apt update
sudo apt install -y libgstreamer1.0-0 libgstreamer1.0-dev \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-libav \
gstreamer1.0-tools gstreamer1.0-omxsudo apt update
sudo apt install -y libgstreamer1.0-0 libgstreamer1.0-dev \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-libav- Download from: https://gstreamer.freedesktop.org/download/
- Install both Runtime + Development (MSVC x86_64)
- Add to PATH:
C:\Program Files\gstreamer\1.0\msvc_x86_64\bin - Restart your terminal/IDE
# Linux
ldconfig -p | grep gstreamer
# Should show: libgstreamer-1.0.so.0
# Windows
where gst-launch-1.0using RtspGStreamerLib;
class Program
{
static void Main(string[] args)
{
// Initialize GStreamer (call once at startup)
RtspFrameCapture.Initialize();
// Create capture instance
using var capture = new RtspFrameCapture();
// Frame received callback
capture.OnFrameReceived += (frame) =>
{
Console.WriteLine($"Frame: {frame.Width}x{frame.Height}");
Console.WriteLine($"Format: {frame.Format}");
Console.WriteLine($"Data size: {frame.Data.Length} bytes");
Console.WriteLine($"Stream timestamp: {frame.StreamTimestamp}");
// Process frame.Data here...
};
// Error callback
capture.OnError += (error) =>
{
Console.WriteLine($"Error: {error}");
};
// Start capture
string rtspUrl = "rtsp://user:password@192.168.1.100:554/stream";
bool useHardwareAccel = false; // Set true on ARM64
if (capture.Start(rtspUrl, useHardwareAccel))
{
Console.WriteLine("Capture started! Press any key to stop...");
Console.ReadKey();
capture.Stop();
}
}
}cd RtspGStreamerExample
# Software decoding (all platforms)
dotnet run "rtsp://user:password@192.168.1.100:554/stream"
# Hardware decoding (ARM64 only)
dotnet run "rtsp://user:password@192.168.1.100:554/stream" 1Frames are delivered in BGR format (3 bytes per pixel):
Memory layout: [B0, G0, R0, B1, G1, R1, B2, G2, R2, ...]
Total size: Width x Height x 3 bytes
// Access pixel at position (x, y)
int index = (y * frame.Width + x) * 3;
byte blue = frame.Data[index];
byte green = frame.Data[index + 1];
byte red = frame.Data[index + 2];// Convert BGR to RGB (if needed)
for (int i = 0; i < frame.Data.Length; i += 3)
{
byte temp = frame.Data[i]; // Blue
frame.Data[i] = frame.Data[i + 2]; // Red -> Blue position
frame.Data[i + 2] = temp; // Blue -> Red position
}The library provides two types of timestamps for each frame:
The PTS (Presentation Timestamp) from the RTSP stream. This is the timestamp assigned by the camera with nanosecond precision.
// Get precise time between frames
double deltaSeconds = (currentFrame.StreamTimestamp - previousFrame.StreamTimestamp).TotalSeconds;The DateTime when the frame was received in your C# code. This includes network latency, decoding time, and thread scheduling delays.
// Only use for logging/debugging
Console.WriteLine($"Frame received at: {frame.ReceivedAt}");See TIMESTAMPS.md for detailed information about timestamp precision.
Modify the latency parameter in RtspFrameCapture.cs:
// Lower latency (50-100ms): Faster response, potentially less stable
"rtspsrc location=\"{rtspUrl}\" protocols=tcp latency=50 ! "
// Higher latency (500ms+): More buffering, more stable
"rtspsrc location=\"{rtspUrl}\" protocols=tcp latency=500 ! "// BGR (default, 3 bytes/pixel) - OpenCV compatible
"videoconvert ! video/x-raw,format=BGR ! "
// RGBA (4 bytes/pixel)
"videoconvert ! video/x-raw,format=RGBA ! "
// Grayscale (1 byte/pixel)
"videoconvert ! video/x-raw,format=GRAY8 ! "Add a frame rate limiter to reduce CPU usage:
// Process only 10 FPS
"videoconvert ! videorate ! video/x-raw,framerate=10/1,format=BGR ! "By default, the library uses H.265. For H.264 streams:
string pipeline =
$"rtspsrc location=\"{rtspUrl}\" protocols=tcp latency=200 ! " +
"rtph264depay ! h264parse ! " +
$"{(useHardwareAccel ? "v4l2h264dec" : "avdec_h264")} ! " +
"videoconvert ! video/x-raw,format=BGR ! " +
"appsink name=sink emit-signals=false max-buffers=1 drop=true";| Resolution | FPS | CPU Usage | RAM | Latency |
|---|---|---|---|---|
| 2560x1440 | 30 | ~10-15% | ~60 MB | ~200ms |
| 1920x1080 | 30 | ~8-12% | ~40 MB | ~150ms |
| Resolution | FPS | CPU Usage | RAM | Latency |
|---|---|---|---|---|
| 2560x1440 | 30 | ~25-30% | ~100 MB | ~250ms |
| 1920x1080 | 30 | ~15-20% | ~70 MB | ~200ms |
Linux:
# Check if library is installed
ldconfig -p | grep gstreamer
# Install if missing
sudo apt install libgstreamer1.0-0Windows:
# Check if in PATH
where gst-launch-1.0
# If not found, add GStreamer bin folder to PATH- Test RTSP URL with gst-launch:
gst-launch-1.0 rtspsrc location="rtsp://your-url" ! fakesink-
Check codec - ensure it matches (H.264 vs H.265)
-
Try switching protocols:
// TCP (default, more reliable)
protocols=tcp
// UDP (lower latency, may have packet loss)
protocols=udp- Verify hardware decoder is available:
gst-inspect-1.0 v4l2h265dec- Enable hardware acceleration:
capture.Start(rtspUrl, useHardwareAccel: true);- Frame callbacks execute on a background thread (not the main thread)
- Use locks when accessing shared data from callbacks
- Frame data is copied to managed memory (safe to use after callback returns)
- Always call
Dispose()or useusingto release GStreamer resources
┌─────────────────┐
│ Your App C# │
│ (Processing) │
└────────┬────────┘
│ OnFrameReceived(VideoFrame)
│
┌────────▼────────┐
│RtspFrameCapture │
│ (C# Wrapper) │
└────────┬────────┘
│ P/Invoke
│
┌────────▼────────┐
│ GStreamer │
│ (Native C/C++) │
└────────┬────────┘
│ RTSP/RTP
│
┌────────▼────────┐
│ IP Camera │
│ (H.265 Stream) │
└─────────────────┘
-
Thread safety: Callbacks run on a background thread. Use locks for shared data.
-
Memory: Frames are copied to managed memory. Process and release quickly for high throughput.
-
BGR format: GStreamer outputs BGR (not RGB). Remember this when integrating with libraries that expect RGB.
-
Disposable: Always use
usingor callDispose()to release GStreamer resources.