add SharedMemoryWriter support - without gstreamer

This commit is contained in:
Maik Jurischka
2026-01-29 12:27:37 +01:00
parent cd290bdd07
commit cc97528eca
2 changed files with 122 additions and 20 deletions

View File

@@ -600,10 +600,14 @@ Retrieve all current eHDR settings.
### 21. Enable Shared Memory
Enable shared memory output for direct frame access by external processes. This creates a shared memory region at `/dev/shm/<name>` where frames are written in parallel to the GStreamer pipeline.
Enable shared memory output for direct frame access by external processes. This creates a shared memory region at `/dev/shm/<name>` where frames are written.
**Note:** Cannot be enabled while streaming is active. Must be enabled before starting the stream.
**Important:** Shared memory can be used **with or without** GStreamer:
- **With GStreamer:** Frames are written to both GStreamer pipeline and shared memory
- **Without GStreamer:** Set pipeline to empty string `""` - frames are only written to shared memory
**Command:**
```json
{
@@ -698,7 +702,7 @@ Query the current shared memory configuration.
## Usage Examples
### Complete Workflow Example
### Complete Workflow Example (GStreamer + Shared Memory)
```bash
# 1. Set GStreamer pipeline for UDP streaming
@@ -721,7 +725,7 @@ echo '{"command":"set_ehdr_ratio_max","params":{"value":"24"}}' | socat - UNIX-C
# 3b. (Optional) Enable shared memory output
echo '{"command":"enable_shared_memory","params":{"name":"/vizion_frame","buffer_size":"8294528"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 4. Start streaming
# 4. Start streaming (both GStreamer and shared memory active)
echo '{"command":"start_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 5. Check status
@@ -735,6 +739,36 @@ echo '{"command":"stop_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
echo '{"command":"disable_shared_memory"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
```
### Shared Memory Only Workflow (No GStreamer)
```bash
# 1. Disable GStreamer pipeline
echo '{"command":"set_pipeline","params":{"pipeline":""}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 2. Set video format
echo '{"command":"set_format","params":{"width":"1920","height":"1080","framerate":"30","format":"YUY2"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 3. Configure camera settings
echo '{"command":"set_exposure","params":{"mode":"auto"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
echo '{"command":"set_brightness","params":{"value":"50"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 4. Enable shared memory
echo '{"command":"enable_shared_memory","params":{"name":"/vizion_frame","buffer_size":"8294528"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 5. Start streaming (shared memory only)
echo '{"command":"start_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# Output: "GStreamer pipeline disabled (using shared memory only)"
# 6. Check that shared memory is being updated
ls -l /dev/shm/vizion_frame # Watch file modification time
# 7. Stop streaming
echo '{"command":"stop_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 8. Disable shared memory
echo '{"command":"disable_shared_memory"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
```
### GStreamer Pipeline Examples
```bash
@@ -819,6 +853,35 @@ ls -lh /dev/shm/vizion_frame
watch -n 0.1 'ls -l /dev/shm/vizion_frame'
```
### Shared Memory WITHOUT GStreamer (Shared Memory Only)
To use shared memory without GStreamer, disable the GStreamer pipeline by setting it to an empty string:
```bash
# 1. Disable GStreamer pipeline
echo '{"command":"set_pipeline","params":{"pipeline":""}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 2. Enable shared memory
echo '{"command":"enable_shared_memory","params":{"name":"/vizion_frame","buffer_size":"8294528"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 3. Start streaming (frames will only go to shared memory)
echo '{"command":"start_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# Output: "GStreamer pipeline disabled (using shared memory only)"
# 4. Stop streaming
echo '{"command":"stop_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
# 5. Optionally re-enable GStreamer for next session
echo '{"command":"set_pipeline","params":{"pipeline":"videoconvert ! autovideosink"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
```
**Benefits of Shared Memory Only Mode:**
- Lower CPU usage (no GStreamer overhead)
- Lower memory bandwidth (no duplicate frame copies to GStreamer)
- Suitable for headless systems or custom processing pipelines
- Multiple external processes can still read from shared memory simultaneously
### Using `nc` (netcat with Unix socket support)
```bash
@@ -864,7 +927,7 @@ print(send_command("set_ehdr_ratio_min", {"value": "12"}))
print(send_command("set_ehdr_ratio_max", {"value": "24"}))
print(send_command("get_ehdr_status")) # Get current eHDR settings
# Shared memory control examples
# Shared memory control examples (with GStreamer)
print(send_command("enable_shared_memory", {
"name": "/vizion_frame",
"buffer_size": "8294528"
@@ -874,6 +937,17 @@ print(send_command("start_stream"))
# ... streaming active, external process can read /dev/shm/vizion_frame ...
print(send_command("stop_stream"))
print(send_command("disable_shared_memory"))
# Shared memory only (without GStreamer)
print(send_command("set_pipeline", {"pipeline": ""})) # Disable GStreamer
print(send_command("enable_shared_memory", {
"name": "/vizion_frame",
"buffer_size": "8294528"
}))
print(send_command("start_stream")) # Frames only go to shared memory
# Output: "GStreamer pipeline disabled (using shared memory only)"
print(send_command("stop_stream"))
print(send_command("disable_shared_memory"))
```
### Using C++
@@ -915,7 +989,7 @@ int main() {
std::cout << sendCommand(R"({"command":"set_ehdr_exposure_max","params":{"value":"4"}})") << std::endl;
std::cout << sendCommand(R"({"command":"get_ehdr_status"})") << std::endl;
// Shared memory control examples
// Shared memory control examples (with GStreamer)
std::cout << sendCommand(R"({"command":"enable_shared_memory","params":{"name":"/vizion_frame","buffer_size":"8294528"}})") << std::endl;
std::cout << sendCommand(R"({"command":"get_shared_memory_status"})") << std::endl;
std::cout << sendCommand(R"({"command":"start_stream"})") << std::endl;
@@ -923,6 +997,14 @@ int main() {
std::cout << sendCommand(R"({"command":"stop_stream"})") << std::endl;
std::cout << sendCommand(R"({"command":"disable_shared_memory"})") << std::endl;
// Shared memory only (without GStreamer)
std::cout << sendCommand(R"({"command":"set_pipeline","params":{"pipeline":""}})") << std::endl; // Disable GStreamer
std::cout << sendCommand(R"({"command":"enable_shared_memory","params":{"name":"/vizion_frame","buffer_size":"8294528"}})") << std::endl;
std::cout << sendCommand(R"({"command":"start_stream"})") << std::endl; // Frames only go to shared memory
// Output: "GStreamer pipeline disabled (using shared memory only)"
std::cout << sendCommand(R"({"command":"stop_stream"})") << std::endl;
std::cout << sendCommand(R"({"command":"disable_shared_memory"})") << std::endl;
return 0;
}
```
@@ -1316,7 +1398,11 @@ finally:
- Default pipeline: `videoconvert ! autovideosink` (display locally)
- eHDR features require compatible camera models (VCI/VCS/VLS3/VLS-GM2/TEVS-AR0821/AR0822)
- eHDR settings may be reset to defaults when the camera starts streaming (driver behavior)
- Shared memory output is independent of GStreamer pipeline (both run in parallel)
- Shared memory output can run with or without GStreamer pipeline:
- **With GStreamer:** Both outputs active (parallel operation)
- **Without GStreamer:** Set pipeline to `""` for shared memory only (lower CPU/memory usage)
- Shared memory must be enabled before starting the stream
- At least one output (GStreamer or shared memory) must be configured to start streaming
- Shared memory files are automatically cleaned up when disabled or on clean exit
- Multiple processes can read from the same shared memory region simultaneously
- Shared memory only mode is recommended for headless systems or custom processing applications

View File

@@ -35,8 +35,14 @@ bool StreamingEngine::start(const std::string& gstPipeline) {
return false;
}
// Set pipeline description
gstPipeline_->setPipelineDescription(gstPipeline);
// Check if at least one output is configured
const bool useGStreamer = !gstPipeline.empty();
const bool useSharedMemory = (shmWriter_ && shmWriter_->isCreated());
if (!useGStreamer && !useSharedMemory) {
std::cerr << "No output configured. Enable GStreamer pipeline or shared memory first." << std::endl;
return false;
}
// Start camera streaming
if (VxStartStreaming(camera_) != 0) {
@@ -58,11 +64,17 @@ bool StreamingEngine::start(const std::string& gstPipeline) {
bufferSize_ = calculatedBufferSize;
buffer_ = std::make_unique<uint8_t[]>(bufferSize_);
// Start GStreamer pipeline
if (!gstPipeline_->start()) {
std::cerr << "Failed to start GStreamer pipeline" << std::endl;
VxStopStreaming(camera_);
return false;
// Start GStreamer pipeline if configured
if (useGStreamer) {
gstPipeline_->setPipelineDescription(gstPipeline);
if (!gstPipeline_->start()) {
std::cerr << "Failed to start GStreamer pipeline" << std::endl;
VxStopStreaming(camera_);
return false;
}
std::cout << "GStreamer pipeline started" << std::endl;
} else {
std::cout << "GStreamer pipeline disabled (using shared memory only)" << std::endl;
}
// Start acquisition thread
@@ -85,8 +97,10 @@ void StreamingEngine::stop() {
acquisitionThread_->join();
}
// Stop GStreamer pipeline
gstPipeline_->stop();
// Stop GStreamer pipeline if running
if (gstPipeline_->isRunning()) {
gstPipeline_->stop();
}
// Stop camera streaming
VxStopStreaming(camera_);
@@ -131,11 +145,13 @@ void StreamingEngine::acquisitionLoop() {
default: formatStr = "UNKNOWN"; break;
}
// Push frame to GStreamer pipeline
if (!gstPipeline_->pushBuffer(buffer_.get(), dataSize,
currentFormat_.width, currentFormat_.height,
formatStr)) {
std::cerr << "Failed to push frame to GStreamer pipeline" << std::endl;
// Push frame to GStreamer pipeline if active
if (gstPipeline_->isRunning()) {
if (!gstPipeline_->pushBuffer(buffer_.get(), dataSize,
currentFormat_.width, currentFormat_.height,
formatStr)) {
std::cerr << "Failed to push frame to GStreamer pipeline" << std::endl;
}
}
// Push frame to shared memory if enabled