diff --git a/README.md b/README.md new file mode 100644 index 0000000..df80bb6 --- /dev/null +++ b/README.md @@ -0,0 +1,290 @@ +# VizionStreamer + +High-performance video streaming application for Vizion cameras with GStreamer integration and Unix Domain Socket control interface. + +## Features + +- **Continuous Frame Acquisition**: Dedicated thread for frame capture from VizionSDK +- **GStreamer Integration**: Flexible video processing and output +- **Socket Control API**: Runtime configuration via JSON commands over Unix Domain Socket +- **Camera Parameter Control**: Exposure, white balance, brightness, contrast, etc. +- **Multiple Output Options**: Display, UDP/TCP streaming, file recording, RTSP, MJPEG +- **Performance Monitoring**: Real-time FPS statistics +- **Thread-Safe**: Mutex-protected operations + +## Quick Start + +### Build + +```bash +cmake -B build -S . +cmake --build build +``` + +### Run + +```bash +# Start VizionStreamer +./build/vizionStreamer +``` + +### Start Streaming (Default Pipeline) + +In another terminal: + +```bash +# Start streaming with default pipeline (local display) +./scripts/start_stream.sh + +# Stop streaming +./scripts/stop_stream.sh +``` + +That's it! The default pipeline `videoconvert ! autovideosink` is already configured. + +## Architecture + +``` +┌─────────────────┐ +│ VizionSDK │ +│ Camera │ +└────────┬────────┘ + │ VxGetImage() + ▼ +┌─────────────────┐ +│ Acquisition │ +│ Loop Thread │ (StreamingEngine) +└────────┬────────┘ + │ Push frames + ▼ +┌─────────────────┐ +│ GStreamer │ +│ Pipeline │ (appsrc → processing → output) +└────────┬────────┘ + │ + ▼ + Display/Stream/File + +┌─────────────────┐ +│ Socket Server │ ← JSON commands +│ (Control API) │ +└─────────────────┘ +``` + +## Control Scripts + +Located in `scripts/` directory: + +| Script | Description | +|--------|-------------| +| `start_stream.sh` | Start streaming (use default or configured pipeline) | +| `stop_stream.sh` | Stop streaming | +| `get_status.sh` | Show streaming status and current pipeline | +| `get_formats.sh` | List available camera formats | +| `set_pipeline_display.sh` | Set pipeline for local display | +| `set_pipeline_udp.sh [host] [port]` | Set pipeline for UDP streaming | +| `set_pipeline_file.sh [path]` | Set pipeline for file recording | +| `set_pipeline_mjpeg.sh [port]` | Set pipeline for MJPEG HTTP streaming | + +See [scripts/README.md](scripts/README.md) for detailed usage. + +## Common Use Cases + +### Local Display +```bash +./build/vizionStreamer +# In another terminal: +./scripts/start_stream.sh +``` + +### UDP Streaming to Remote Host +```bash +./build/vizionStreamer +# In another terminal: +./scripts/set_pipeline_udp.sh 192.168.1.100 5000 +./scripts/start_stream.sh + +# On receiving machine: +gst-launch-1.0 udpsrc port=5000 ! application/x-rtp,encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink +``` + +### Record to File +```bash +./build/vizionStreamer +# In another terminal: +./scripts/set_pipeline_file.sh /tmp/recording.mp4 +./scripts/start_stream.sh +# Let it run, then: +./scripts/stop_stream.sh +``` + +### MJPEG HTTP Streaming +```bash +./build/vizionStreamer +# In another terminal: +./scripts/set_pipeline_mjpeg.sh 8080 +./scripts/start_stream.sh + +# View in browser: +firefox http://localhost:8080 +``` + +## Socket Control API + +Full API documentation: [SOCKET_API.md](SOCKET_API.md) + +**Socket Path**: `/tmp/vizion_control.sock` + +### Available Commands + +- `get_formats` - List camera formats +- `set_format` - Change resolution/framerate/format +- `start_stream` - Start streaming +- `stop_stream` - Stop streaming +- `get_status` - Get streaming status +- `set_pipeline` - Configure GStreamer pipeline +- `set_exposure` - Configure exposure +- `set_whitebalance` - Configure white balance +- `set_brightness` - Adjust brightness +- `set_contrast` - Adjust contrast +- `set_saturation` - Adjust saturation +- `set_sharpness` - Adjust sharpness +- `set_gamma` - Adjust gamma +- `set_gain` - Adjust gain + +### Example + +```bash +# Manual command +echo '{"command":"start_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock + +# Set custom pipeline +echo '{"command":"set_pipeline","params":{"pipeline":"videoconvert ! x264enc ! rtph264pay ! udpsink host=192.168.1.100 port=5000"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock + +# Get status +echo '{"command":"get_status"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock +``` + +## GStreamer Pipeline Examples + +### Display +``` +videoconvert ! autovideosink +``` + +### UDP H.264 Streaming +``` +videoconvert ! x264enc tune=zerolatency bitrate=2000 ! rtph264pay ! udpsink host=192.168.1.100 port=5000 +``` + +### File Recording +``` +videoconvert ! x264enc ! mp4mux ! filesink location=/tmp/output.mp4 +``` + +### TCP Streaming +``` +videoconvert ! x264enc ! h264parse ! mpegtsmux ! tcpserversink host=0.0.0.0 port=5000 +``` + +### MJPEG HTTP +``` +videoconvert ! jpegenc ! multipartmux ! tcpserversink host=0.0.0.0 port=8080 +``` + +### Tee (Display + Record) +``` +tee name=t ! queue ! videoconvert ! autovideosink t. ! queue ! x264enc ! mp4mux ! filesink location=out.mp4 +``` + +## Dependencies + +- **VizionSDK**: Camera interface (located at `/opt/vizionsdk`) +- **GStreamer 1.0**: Video processing (`gstreamer-1.0`, `gstreamer-app-1.0`) +- **CMake**: Build system (>= 3.20) +- **C++23**: Compiler support +- **socat**: For socket communication (control scripts) + +### Install Dependencies (Debian/Ubuntu) + +```bash +sudo apt install build-essential cmake pkg-config socat \ + libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \ + gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-ugly gstreamer1.0-x +``` + +## Project Structure + +``` +vizionStreamer/ +├── main.cpp # Main application +├── SocketServer.{h,cpp} # Unix domain socket server +├── CameraController.{h,cpp} # Command processing & camera control +├── StreamingEngine.{h,cpp} # Acquisition loop & streaming +├── GStreamerPipeline.{h,cpp} # GStreamer pipeline wrapper +├── CMakeLists.txt # Build configuration +├── config/ +│ └── VxConfig.conf # VizionSDK configuration +├── scripts/ # Control scripts +│ ├── README.md +│ ├── start_stream.sh +│ ├── stop_stream.sh +│ ├── get_status.sh +│ ├── set_pipeline_*.sh +│ └── get_formats.sh +├── SOCKET_API.md # Complete API documentation +└── README.md # This file +``` + +## Configuration Files + +### VxConfig.conf + +Automatically copied to build directory during build. Contains VizionSDK camera configuration. + +## Performance + +The acquisition loop displays statistics every second: + +``` +FPS: 30 | Total frames: 1234 | Frame size: 4147200 bytes +``` + +Typical performance: +- **Local Display**: 30 FPS @ 1080p +- **UDP Streaming**: 30 FPS @ 1080p with H.264 encoding +- **File Recording**: Limited by disk I/O + +## Troubleshooting + +### No cameras found +- Check camera connection +- Run `/opt/vizionsdk/init_driver.sh` if needed +- Check `dmesg` for USB errors + +### Pipeline fails to start +- Verify GStreamer plugins are installed +- Test pipeline manually: `gst-launch-1.0 videotestsrc ! YOUR_PIPELINE` +- Check pipeline syntax + +### Socket connection refused +- Ensure VizionStreamer is running +- Check socket exists: `ls -l /tmp/vizion_control.sock` +- Verify permissions + +### Low FPS +- Reduce resolution or framerate +- Use hardware encoding if available (`vaapih264enc` instead of `x264enc`) +- Check CPU usage + +## License + +See VizionSDK license terms. + +## Support + +For issues and questions, refer to: +- [SOCKET_API.md](SOCKET_API.md) - Complete API reference +- [scripts/README.md](scripts/README.md) - Script usage guide +- VizionSDK documentation at `/opt/vizionsdk/` diff --git a/main.cpp b/main.cpp index e1920b7..a4a9271 100644 --- a/main.cpp +++ b/main.cpp @@ -71,11 +71,16 @@ int main() { return -1; } - std::cout << "\nVizion Streamer is running." << std::endl; + std::cout << "\n========================================" << std::endl; + std::cout << "VizionStreamer Ready" << std::endl; + std::cout << "========================================" << std::endl; std::cout << "Control socket: " << socketPath << std::endl; - std::cout << "Default GStreamer pipeline: videoconvert ! autovideosink" << std::endl; - std::cout << "Use socket commands to start streaming and configure pipeline.\n" << std::endl; - std::cout << "Press Ctrl+C to exit.\n" << std::endl; + std::cout << "Default pipeline: videoconvert ! autovideosink" << std::endl; + std::cout << "\nQuick start:" << std::endl; + std::cout << " echo '{\"command\":\"start_stream\"}' | socat - UNIX-CONNECT:" << socketPath << std::endl; + std::cout << "\nTo change pipeline before starting:" << std::endl; + std::cout << " echo '{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"YOUR_PIPELINE\"}}' | socat - UNIX-CONNECT:" << socketPath << std::endl; + std::cout << "\nPress Ctrl+C to exit.\n" << std::endl; // Main loop - keep running until signaled to stop while (g_running) { diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..97c9a92 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,151 @@ +# VizionStreamer Control Scripts + +Diese Scripts ermöglichen die schnelle Steuerung von VizionStreamer über die Unix Domain Socket API. + +## Voraussetzung + +VizionStreamer muss laufen: +```bash +cd /home/maik/CLionProjects/vizionStreamer +./build/vizionStreamer +``` + +## Schnellstart (Standard-Pipeline) + +Die Standard-Pipeline `videoconvert ! autovideosink` ist bereits gesetzt. Einfach starten: + +```bash +./scripts/start_stream.sh +``` + +Das Video wird lokal angezeigt. Zum Stoppen: + +```bash +./scripts/stop_stream.sh +``` + +## Pipeline ändern + +### Lokale Anzeige (Standard) +```bash +./scripts/set_pipeline_display.sh +./scripts/start_stream.sh +``` + +### UDP-Streaming (H.264) +```bash +# Standard: 192.168.1.100:5000 +./scripts/set_pipeline_udp.sh + +# Eigene IP/Port +./scripts/set_pipeline_udp.sh 192.168.1.50 5001 + +# Dann starten +./scripts/start_stream.sh +``` + +**Stream empfangen:** +```bash +gst-launch-1.0 udpsrc port=5000 ! application/x-rtp,encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink +``` + +### Aufnahme in Datei +```bash +# Standard: /tmp/vizion_recording.mp4 +./scripts/set_pipeline_file.sh + +# Eigene Datei +./scripts/set_pipeline_file.sh /home/user/videos/recording.mp4 + +# Dann starten +./scripts/start_stream.sh +``` + +### MJPEG HTTP-Stream +```bash +# Standard: Port 8080 +./scripts/set_pipeline_mjpeg.sh + +# Eigener Port +./scripts/set_pipeline_mjpeg.sh 8090 + +# Dann starten +./scripts/start_stream.sh +``` + +**Stream ansehen:** +```bash +# Im Browser +firefox http://localhost:8080 + +# Mit FFplay +ffplay http://localhost:8080 +``` + +## Status & Information + +### Status abfragen +```bash +./scripts/get_status.sh +``` + +Zeigt: +- Streaming-Status (läuft/gestoppt) +- Aktuelle Pipeline + +### Verfügbare Formate +```bash +./scripts/get_formats.sh +``` + +Zeigt alle verfügbaren Kamera-Auflösungen und Formate. + +## Typischer Workflow + +```bash +# 1. VizionStreamer starten (Terminal 1) +./build/vizionStreamer + +# 2. Status prüfen (Terminal 2) +./scripts/get_status.sh + +# 3. Pipeline für UDP-Streaming setzen +./scripts/set_pipeline_udp.sh 192.168.1.100 5000 + +# 4. Streaming starten +./scripts/start_stream.sh + +# 5. Stream empfangen (auf Zielrechner) +gst-launch-1.0 udpsrc port=5000 ! application/x-rtp,encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink + +# 6. Bei Bedarf stoppen +./scripts/stop_stream.sh + +# 7. Pipeline ändern +./scripts/set_pipeline_display.sh + +# 8. Erneut starten +./scripts/start_stream.sh +``` + +## Wichtige Hinweise + +- Pipeline kann nur geändert werden, wenn Streaming gestoppt ist +- Standard-Pipeline ist bereits gesetzt - kein `set_pipeline` vor dem ersten Start nötig +- Mit `start_stream.sh` sofort loslegen! +- Alle Scripts benötigen `socat` (installieren mit: `sudo apt install socat`) +- Status-Scripts benötigen optional `python3` für formatierte JSON-Ausgabe + +## Eigene Pipelines + +Sie können jede beliebige GStreamer-Pipeline verwenden: + +```bash +SOCKET="/tmp/vizion_control.sock" +echo '{"command":"set_pipeline","params":{"pipeline":"IHRE_PIPELINE"}}' | socat - UNIX-CONNECT:$SOCKET +``` + +Beispiele: +- `videoconvert ! xvimagesink` - Einfache lokale Anzeige +- `videoconvert ! x264enc ! flvmux ! rtmpsink location=rtmp://server/live/stream` - RTMP-Streaming +- `tee name=t ! queue ! videoconvert ! autovideosink t. ! queue ! x264enc ! filesink location=out.mp4` - Gleichzeitig anzeigen und aufnehmen diff --git a/scripts/get_formats.sh b/scripts/get_formats.sh new file mode 100755 index 0000000..c7a6cc6 --- /dev/null +++ b/scripts/get_formats.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Get available camera formats + +SOCKET="/tmp/vizion_control.sock" + +echo '{"command":"get_formats"}' | socat - UNIX-CONNECT:$SOCKET | python3 -m json.tool 2>/dev/null || echo '{"command":"get_formats"}' | socat - UNIX-CONNECT:$SOCKET diff --git a/scripts/get_status.sh b/scripts/get_status.sh new file mode 100755 index 0000000..06de8b4 --- /dev/null +++ b/scripts/get_status.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Get streaming status + +SOCKET="/tmp/vizion_control.sock" + +echo '{"command":"get_status"}' | socat - UNIX-CONNECT:$SOCKET | python3 -m json.tool 2>/dev/null || echo '{"command":"get_status"}' | socat - UNIX-CONNECT:$SOCKET diff --git a/scripts/set_pipeline_display.sh b/scripts/set_pipeline_display.sh new file mode 100755 index 0000000..93a8450 --- /dev/null +++ b/scripts/set_pipeline_display.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Set pipeline for local display (default) + +SOCKET="/tmp/vizion_control.sock" + +echo "Setting display pipeline (default)..." +echo '{"command":"set_pipeline","params":{"pipeline":"videoconvert ! autovideosink"}}' | socat - UNIX-CONNECT:$SOCKET + +echo "" +echo "Pipeline set. Start display with start_stream.sh" diff --git a/scripts/set_pipeline_file.sh b/scripts/set_pipeline_file.sh new file mode 100755 index 0000000..6822fc9 --- /dev/null +++ b/scripts/set_pipeline_file.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Set pipeline for recording to file + +SOCKET="/tmp/vizion_control.sock" +FILE="${1:-/tmp/vizion_recording.mp4}" + +echo "Setting file recording pipeline to $FILE..." +echo "{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"videoconvert ! x264enc ! mp4mux ! filesink location=$FILE\"}}" | socat - UNIX-CONNECT:$SOCKET + +echo "" +echo "Pipeline set. Start recording with start_stream.sh" +echo "Recording will be saved to: $FILE" diff --git a/scripts/set_pipeline_mjpeg.sh b/scripts/set_pipeline_mjpeg.sh new file mode 100755 index 0000000..6878b21 --- /dev/null +++ b/scripts/set_pipeline_mjpeg.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Set pipeline for MJPEG HTTP streaming + +SOCKET="/tmp/vizion_control.sock" +PORT="${1:-8080}" + +echo "Setting MJPEG HTTP streaming pipeline on port $PORT..." +echo "{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"videoconvert ! jpegenc ! multipartmux ! tcpserversink host=0.0.0.0 port=$PORT\"}}" | socat - UNIX-CONNECT:$SOCKET + +echo "" +echo "Pipeline set. Start streaming with start_stream.sh" +echo "View stream in browser: http://localhost:$PORT" diff --git a/scripts/set_pipeline_udp.sh b/scripts/set_pipeline_udp.sh new file mode 100755 index 0000000..d7ba913 --- /dev/null +++ b/scripts/set_pipeline_udp.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Set pipeline for UDP streaming (H.264) + +SOCKET="/tmp/vizion_control.sock" +HOST="${1:-192.168.1.100}" +PORT="${2:-5000}" + +echo "Setting UDP streaming pipeline to $HOST:$PORT..." +echo "{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"videoconvert ! x264enc tune=zerolatency bitrate=2000 ! rtph264pay ! udpsink host=$HOST port=$PORT\"}}" | socat - UNIX-CONNECT:$SOCKET + +echo "" +echo "Pipeline set. Start streaming with start_stream.sh" +echo "To receive stream on target machine:" +echo " gst-launch-1.0 udpsrc port=$PORT ! application/x-rtp,encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink" diff --git a/scripts/start_stream.sh b/scripts/start_stream.sh new file mode 100755 index 0000000..cae0433 --- /dev/null +++ b/scripts/start_stream.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Quick start script - starts streaming with default pipeline + +SOCKET="/tmp/vizion_control.sock" + +echo "Starting stream with default pipeline (videoconvert ! autovideosink)..." +echo '{"command":"start_stream"}' | socat - UNIX-CONNECT:$SOCKET + +echo "Stream started. Use stop_stream.sh to stop." diff --git a/scripts/stop_stream.sh b/scripts/stop_stream.sh new file mode 100755 index 0000000..71caa14 --- /dev/null +++ b/scripts/stop_stream.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Stop streaming + +SOCKET="/tmp/vizion_control.sock" + +echo "Stopping stream..." +echo '{"command":"stop_stream"}' | socat - UNIX-CONNECT:$SOCKET