Comparison of different approaches for processing RTSP H.265 streams in .NET applications, with focus on ARM64 devices.
| Feature | RtspClientSharpCore | Emgu.CV (OpenCV) | GStreamer P/Invoke |
|---|---|---|---|
| CPU (720p ARM64) | 60-80% | 40-50% | 10-15% |
| RAM Usage | 180 MB | 120 MB | 60 MB |
| HW Accel ARM64 | No | Complex setup | Automatic |
| H.265/HEVC | Limited | Yes | Yes |
| NuGet Dependencies | 3+ packages | 1 large package | None |
| Install Size | ~50 MB | ~200 MB | ~350 MB* |
| ARM64 Build | Problematic | Doesn't compile | Works |
| Frame Access | Callback | Mat object | Callback |
| Output Format | RGB24 | BGR/Gray | Configurable |
| Built-in CV Algorithms | No | Many | No |
| Typical Latency | 300-500ms | 200-400ms | 150-250ms |
| Pipeline Control | Limited | Medium | Full |
* GStreamer is shared by the system, not duplicated per application
Native Hardware Acceleration:
Without HW Accel (avdec_h265): 60% CPU
With HW Accel (v4l2h265dec): 10% CPU ← 6x better!
GStreamer automatically detects and uses the hardware decoder on ARM64 devices like Khadas VIM3 (Amlogic A311D), Raspberry Pi, and Jetson.
RtspClientSharpCore:
<PackageReference Include="RtspClientSharp" Version="1.3.5" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
<PackageReference Include="FFmpeg.AutoGen" Version="6.1.0" />
<!-- + ARM64 build issues -->Emgu.CV:
<PackageReference Include="Emgu.CV.runtime.ubuntu-x64" Version="4.8.1" />
<!-- No ARM64 runtime! -->
<!-- Requires manual OpenCV compilation -->GStreamer P/Invoke:
<!-- NO DEPENDENCIES! -->
<!-- Uses system-installed GStreamer -->On ARM64 device:
# GStreamer P/Invoke - one line
sudo apt install libgstreamer1.0-0 gstreamer1.0-plugins-good gstreamer1.0-omx
# vs Emgu.CV - compile OpenCV from scratch
git clone https://github.com/opencv/opencv
mkdir build && cd build
cmake .. -DENABLE_NEON=ON -DWITH_V4L=ON ...
make -j6 # 2+ hours of compilation!GStreamer P/Invoke:
// You control EVERYTHING
string pipeline =
"rtspsrc location=\"{url}\" protocols=tcp latency=200 ! " +
"rtph265depay ! h265parse ! " +
"v4l2h265dec ! " + // ← Choose decoder
"videoconvert ! " +
"videorate ! video/x-raw,framerate=10/1 ! " + // ← Control FPS
"videoscale ! video/x-raw,width=640,height=480 ! " + // ← Resize
"video/x-raw,format=BGR ! " + // ← Output format
"appsink";Emgu.CV:
// Limited control
var capture = new VideoCapture("rtsp://...");
// No control over decoder, latency, format, etc.CPU: 65% constant
RAM: 180 MB
FPS: 28-30 (some drops)
Temperature: 75°C
Latency: 450ms
CPU: ~45% estimated (no HW accel)
RAM: ~120 MB
FPS: 28-30
Temperature: ~70°C
Latency: ~300ms
CPU: 12% constant
RAM: 60 MB
FPS: 30 stable
Temperature: 55°C
Latency: 180ms
Ideal for:
- ARM64 devices (Raspberry Pi, Orange Pi, Khadas, Jetson)
- H.265/HEVC streams
- Multiple simultaneous cameras
- Real-time processing
- Low power consumption
- Fine-grained pipeline control
Ideal for:
- Rapid prototyping
- Complex CV algorithms (YOLO, face detection, etc.)
- Windows/Linux x64 only
- HW acceleration not needed
Not recommended for:
- ARM64 (difficult to compile)
- Performance-critical applications
- Multiple streams
Ideal for:
- Legacy projects already using it
- Simple H.264 RTSP streams
- Windows/Linux x64
Not recommended for:
- ARM64
- H.265/HEVC
- Performance-critical applications
- Hardware acceleration
using var capture = new RtspFrameCapture();
capture.OnFrameReceived += (frame) =>
{
// Frame already decoded in BGR, ready for processing
ProcessFrame(frame.Data, frame.Width, frame.Height);
};
capture.Start(rtspUrl, useHardwareAccel: true);Advantages:
- 10% CPU on Khadas VIM3
- BGR frames ready for processing
- 30 FPS stable
- Low temperature
var capture = new VideoCapture(rtspUrl);
Mat frame = new Mat();
while (capture.Read(frame))
{
// Has built-in algorithms, but...
// ...no HW accel, CPU goes to 45%
}Problems:
- Doesn't compile easily on ARM64
- No automatic HW accel
- High CPU usage
For video processing on ARM64 devices, the choice is clear:
1st GStreamer P/Invoke - BEST option
✓ 10% CPU with HW accel
✓ Zero NuGet dependencies
✓ Full control
✓ Simple installation
2nd Emgu.CV - Good, but...
⚠ Doesn't compile easily on ARM64
⚠ No automatic HW accel
⚠ Large dependency
3rd RtspClientSharpCore - Not recommended
✗ 60% CPU
✗ No HW accel
✗ Limited H.265
Use GStreamer P/Invoke and implement your processing logic:
- Background subtraction is simple (~50 lines)
- Frame analysis is straightforward
- Full control over the pipeline
If you need complex CV algorithms (YOLO, etc.), consider:
- Run inference in a separate service (Python + OpenCV)
- GStreamer P/Invoke sends frames via IPC/socket
- Best of both worlds!