Compare commits
10 Commits
fe8b590128
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b769bfe5e | ||
|
|
bb9b5cc619 | ||
|
|
a2d2f256cf | ||
|
|
e8444b09e5 | ||
|
|
530d447717 | ||
|
|
0fd3fe4ce6 | ||
|
|
1c61e76eb4 | ||
|
|
6fdae6be7b | ||
|
|
a6cf510607 | ||
|
|
e729354c8f |
@@ -11,6 +11,9 @@ set(VIZIONSDK_LIB_DIR "${VIZIONSDK_ROOT}/lib")
|
||||
# Add VizionSDK include directory
|
||||
include_directories(${VIZIONSDK_INCLUDE_DIR})
|
||||
|
||||
# Add project include directory
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
# ---------------- GStreamer integration ----------------
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
|
||||
@@ -36,11 +39,11 @@ find_library(VIZIONSDK_LIBRARY
|
||||
|
||||
# Create executable
|
||||
add_executable(vizionStreamer
|
||||
main.cpp
|
||||
SocketServer.cpp
|
||||
CameraController.cpp
|
||||
GStreamerPipeline.cpp
|
||||
StreamingEngine.cpp
|
||||
src/main.cpp
|
||||
src/SocketServer.cpp
|
||||
src/CameraController.cpp
|
||||
src/GStreamerPipeline.cpp
|
||||
src/StreamingEngine.cpp
|
||||
)
|
||||
|
||||
# Link libraries
|
||||
|
||||
37
LICENSE
Normal file
37
LICENSE
Normal file
@@ -0,0 +1,37 @@
|
||||
VizionStreamer
|
||||
Copyright (c) 2025 Maik Jurischka
|
||||
|
||||
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||
|
||||
You are free to:
|
||||
- Share — copy and redistribute the material in any medium or format
|
||||
- Adapt — remix, transform, and build upon the material
|
||||
|
||||
Under the following terms:
|
||||
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made.
|
||||
- NonCommercial — You may not use the material for commercial purposes.
|
||||
- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
|
||||
|
||||
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
|
||||
|
||||
Full license text: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
|
||||
|
||||
===============================================================================
|
||||
|
||||
THIRD-PARTY DEPENDENCIES:
|
||||
|
||||
This software uses the following third-party libraries:
|
||||
|
||||
1. VizionSDK
|
||||
Copyright (c) 2025 TechNexion Ltd.
|
||||
Licensed under MIT License
|
||||
https://github.com/TechNexion-Vision/vizionsdk/blob/main/LICENSE
|
||||
|
||||
2. GStreamer
|
||||
Licensed under LGPL
|
||||
https://gstreamer.freedesktop.org/
|
||||
|
||||
===============================================================================
|
||||
|
||||
DISCLAIMER:
|
||||
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
|
||||
88
README.md
88
README.md
@@ -2,6 +2,8 @@
|
||||
|
||||
High-performance video streaming application for Technexion cameras with GStreamer integration and Unix Domain Socket control interface.
|
||||
|
||||
Depends on: https://github.com/TechNexion-Vision/vizionsdk
|
||||
|
||||
## Features
|
||||
|
||||
- **Continuous Frame Acquisition**: Dedicated thread for frame capture from VizionSDK
|
||||
@@ -131,7 +133,7 @@ firefox http://localhost:8080
|
||||
|
||||
## Socket Control API
|
||||
|
||||
Full API documentation: [SOCKET_API.md](SOCKET_API.md)
|
||||
Full API documentation: [SOCKET_API.md](docs/SOCKET_API.md)
|
||||
|
||||
**Socket Path**: `/tmp/vizion_control.sock`
|
||||
|
||||
@@ -151,6 +153,12 @@ Full API documentation: [SOCKET_API.md](SOCKET_API.md)
|
||||
- `set_sharpness` - Adjust sharpness
|
||||
- `set_gamma` - Adjust gamma
|
||||
- `set_gain` - Adjust gain
|
||||
- `set_ehdr_mode` - Enable/disable eHDR (compatible cameras only)
|
||||
- `set_ehdr_exposure_min` - Set eHDR minimum exposure frames
|
||||
- `set_ehdr_exposure_max` - Set eHDR maximum exposure frames
|
||||
- `set_ehdr_ratio_min` - Set eHDR minimum exposure ratio
|
||||
- `set_ehdr_ratio_max` - Set eHDR maximum exposure ratio
|
||||
- `get_ehdr_status` - Get current eHDR settings
|
||||
|
||||
### Example
|
||||
|
||||
@@ -218,23 +226,32 @@ sudo apt install build-essential cmake pkg-config socat \
|
||||
|
||||
```
|
||||
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
|
||||
├── LICENSE # Project license
|
||||
├── README.md # This file
|
||||
├── include/ # Public header files
|
||||
│ └── vizionstreamer/
|
||||
│ ├── CameraController.h
|
||||
│ ├── SocketServer.h
|
||||
│ ├── StreamingEngine.h
|
||||
│ └── GStreamerPipeline.h
|
||||
├── src/ # Implementation files
|
||||
│ ├── main.cpp
|
||||
│ ├── CameraController.cpp
|
||||
│ ├── SocketServer.cpp
|
||||
│ ├── StreamingEngine.cpp
|
||||
│ └── GStreamerPipeline.cpp
|
||||
├── config/ # Configuration files
|
||||
│ └── VxConfig.conf
|
||||
├── docs/ # Documentation
|
||||
│ └── SOCKET_API.md
|
||||
└── scripts/ # Control scripts
|
||||
├── README.md
|
||||
├── start_stream.sh
|
||||
├── stop_stream.sh
|
||||
├── get_status.sh
|
||||
├── set_pipeline_*.sh
|
||||
└── get_formats.sh
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
@@ -280,11 +297,42 @@ Typical performance:
|
||||
|
||||
## License
|
||||
|
||||
See VizionSDK license terms.
|
||||
**VizionStreamer**
|
||||
Copyright (c) 2025 Maik Jurischka
|
||||
|
||||
This work is licensed under the **Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License** (CC BY-NC-SA 4.0).
|
||||
|
||||
### You are free to:
|
||||
- **Share** — copy and redistribute the material in any medium or format
|
||||
- **Adapt** — remix, transform, and build upon the material
|
||||
|
||||
### Under the following terms:
|
||||
- **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made.
|
||||
- **NonCommercial** — You may not use the material for commercial purposes.
|
||||
- **ShareAlike** — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
|
||||
|
||||
**Full license text**: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
|
||||
|
||||
### Disclaimer
|
||||
|
||||
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
|
||||
|
||||
### Third-Party Dependencies
|
||||
|
||||
This software uses the following dependencies:
|
||||
|
||||
- **VizionSDK**
|
||||
Copyright (c) 2025 TechNexion Ltd.
|
||||
Licensed under MIT License
|
||||
https://github.com/TechNexion-Vision/vizionsdk/blob/main/LICENSE
|
||||
|
||||
- **GStreamer**
|
||||
Licensed under LGPL
|
||||
https://gstreamer.freedesktop.org/
|
||||
|
||||
## Support
|
||||
|
||||
For issues and questions, refer to:
|
||||
- [SOCKET_API.md](SOCKET_API.md) - Complete API reference
|
||||
- [SOCKET_API.md](docs/SOCKET_API.md) - Complete API reference
|
||||
- [scripts/README.md](scripts/README.md) - Script usage guide
|
||||
- VizionSDK documentation at `/opt/vizionsdk/`
|
||||
- VizionSDK documentation at https://developer.technexion.com/docs/vision-software/vizionsdk/
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
VizionStreamer can be controlled via a Unix Domain Socket interface. This allows external applications to configure camera parameters and stream settings at runtime.
|
||||
|
||||
**Copyright (c) 2025 Maik Jurischka**
|
||||
Licensed under CC BY-NC-SA 4.0 - https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
|
||||
## Socket Connection
|
||||
|
||||
- **Socket Path**: `/tmp/vizion_control.sock`
|
||||
@@ -433,6 +436,168 @@ Adjust camera gain.
|
||||
|
||||
---
|
||||
|
||||
### 15. Set eHDR Mode
|
||||
|
||||
Enable or disable eHDR (Enhanced High Dynamic Range) mode.
|
||||
|
||||
**Note:** eHDR features are only available on specific camera models: VCI-AR0821/AR0822, VCS-AR0821/AR0822, VLS3-AR0821/AR0822, VLS-GM2-AR0821/AR0822, and TEVS-AR0821/AR0822.
|
||||
|
||||
**Command:**
|
||||
```json
|
||||
{
|
||||
"command": "set_ehdr_mode",
|
||||
"params": {
|
||||
"mode": "0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `mode`: "0" to enable eHDR, "1" to disable eHDR
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "eHDR mode set successfully"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 16. Set eHDR Exposure Minimum
|
||||
|
||||
Set the minimum number of exposure frames for eHDR.
|
||||
|
||||
**Command:**
|
||||
```json
|
||||
{
|
||||
"command": "set_ehdr_exposure_min",
|
||||
"params": {
|
||||
"value": "1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `value`: Minimum exposure frames (range: 1-4, default: 1)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "eHDR exposure min set successfully"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 17. Set eHDR Exposure Maximum
|
||||
|
||||
Set the maximum number of exposure frames for eHDR.
|
||||
|
||||
**Command:**
|
||||
```json
|
||||
{
|
||||
"command": "set_ehdr_exposure_max",
|
||||
"params": {
|
||||
"value": "4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `value`: Maximum exposure frames (range: 1-4, default: 4)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "eHDR exposure max set successfully"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 18. Set eHDR Ratio Minimum
|
||||
|
||||
Set the minimum exposure ratio for eHDR.
|
||||
|
||||
**Command:**
|
||||
```json
|
||||
{
|
||||
"command": "set_ehdr_ratio_min",
|
||||
"params": {
|
||||
"value": "12"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `value`: Minimum exposure ratio (range: 1-128, default: 12)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "eHDR ratio min set successfully"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 19. Set eHDR Ratio Maximum
|
||||
|
||||
Set the maximum exposure ratio for eHDR.
|
||||
|
||||
**Command:**
|
||||
```json
|
||||
{
|
||||
"command": "set_ehdr_ratio_max",
|
||||
"params": {
|
||||
"value": "24"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `value`: Maximum exposure ratio (range: 1-128, default: 24)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "eHDR ratio max set successfully"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 20. Get eHDR Status
|
||||
|
||||
Retrieve all current eHDR settings.
|
||||
|
||||
**Command:**
|
||||
```json
|
||||
{
|
||||
"command": "get_ehdr_status"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"ehdr_mode": 0,
|
||||
"exposure_min": 1,
|
||||
"exposure_max": 4,
|
||||
"ratio_min": 12,
|
||||
"ratio_max": 24
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Complete Workflow Example
|
||||
@@ -448,6 +613,13 @@ echo '{"command":"set_format","params":{"width":"1920","height":"1080","framerat
|
||||
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
|
||||
|
||||
# 3a. (Optional) Configure eHDR settings (for compatible cameras)
|
||||
echo '{"command":"set_ehdr_mode","params":{"mode":"0"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"set_ehdr_exposure_min","params":{"value":"1"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"set_ehdr_exposure_max","params":{"value":"4"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"set_ehdr_ratio_min","params":{"value":"12"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"set_ehdr_ratio_max","params":{"value":"24"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
|
||||
# 4. Start streaming
|
||||
echo '{"command":"start_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
|
||||
@@ -499,6 +671,27 @@ echo '{"command":"get_status"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"stop_stream"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
```
|
||||
|
||||
### eHDR Control Examples
|
||||
|
||||
```bash
|
||||
# Enable eHDR mode
|
||||
echo '{"command":"set_ehdr_mode","params":{"mode":"0"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
|
||||
# Disable eHDR mode
|
||||
echo '{"command":"set_ehdr_mode","params":{"mode":"1"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
|
||||
# Configure eHDR exposure range
|
||||
echo '{"command":"set_ehdr_exposure_min","params":{"value":"1"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"set_ehdr_exposure_max","params":{"value":"4"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
|
||||
# Configure eHDR ratio range
|
||||
echo '{"command":"set_ehdr_ratio_min","params":{"value":"12"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
echo '{"command":"set_ehdr_ratio_max","params":{"value":"24"}}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
|
||||
# Get current eHDR settings
|
||||
echo '{"command":"get_ehdr_status"}' | socat - UNIX-CONNECT:/tmp/vizion_control.sock
|
||||
```
|
||||
|
||||
### Using `nc` (netcat with Unix socket support)
|
||||
|
||||
```bash
|
||||
@@ -535,6 +728,14 @@ print(send_command("set_format", {
|
||||
}))
|
||||
print(send_command("set_exposure", {"mode": "auto"}))
|
||||
print(send_command("start_stream"))
|
||||
|
||||
# eHDR control examples (for compatible cameras)
|
||||
print(send_command("set_ehdr_mode", {"mode": "0"})) # Enable eHDR
|
||||
print(send_command("set_ehdr_exposure_min", {"value": "1"}))
|
||||
print(send_command("set_ehdr_exposure_max", {"value": "4"}))
|
||||
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
|
||||
```
|
||||
|
||||
### Using C++
|
||||
@@ -569,6 +770,13 @@ std::string sendCommand(const std::string& command) {
|
||||
int main() {
|
||||
std::cout << sendCommand(R"({"command":"get_formats"})") << std::endl;
|
||||
std::cout << sendCommand(R"({"command":"set_brightness","params":{"value":"50"}})") << std::endl;
|
||||
|
||||
// eHDR control examples (for compatible cameras)
|
||||
std::cout << sendCommand(R"({"command":"set_ehdr_mode","params":{"mode":"0"}})") << std::endl;
|
||||
std::cout << sendCommand(R"({"command":"set_ehdr_exposure_min","params":{"value":"1"}})") << std::endl;
|
||||
std::cout << sendCommand(R"({"command":"set_ehdr_exposure_max","params":{"value":"4"}})") << std::endl;
|
||||
std::cout << sendCommand(R"({"command":"get_ehdr_status"})") << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
@@ -587,6 +795,20 @@ The valid ranges for camera parameters depend on the specific camera model. You
|
||||
- Exposure: 1-10000 (in auto mode, value is ignored)
|
||||
- White Balance Temperature: 2800-6500 Kelvin
|
||||
|
||||
**eHDR ranges (for compatible cameras only):**
|
||||
- eHDR Mode: 0 (enable) or 1 (disable)
|
||||
- eHDR Exposure Min: 1-4 (default: 1)
|
||||
- eHDR Exposure Max: 1-4 (default: 4)
|
||||
- eHDR Ratio Min: 1-128 (default: 12)
|
||||
- eHDR Ratio Max: 1-128 (default: 24)
|
||||
|
||||
**Compatible eHDR Camera Models:**
|
||||
- VCI-AR0821/AR0822
|
||||
- VCS-AR0821/AR0822
|
||||
- VLS3-AR0821/AR0822
|
||||
- VLS-GM2-AR0821/AR0822
|
||||
- TEVS-AR0821/AR0822
|
||||
|
||||
## Error Handling
|
||||
|
||||
Always check the `status` field in the response:
|
||||
@@ -661,3 +883,5 @@ curl http://192.168.1.100:8080 > stream.mjpg
|
||||
- Invalid parameter values will return an error response
|
||||
- GStreamer pipeline errors will be reported when starting the stream
|
||||
- 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)
|
||||
@@ -1,7 +1,15 @@
|
||||
/*
|
||||
* VizionStreamer - Camera Control Interface
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vizionsdk/VizionSDK.h>
|
||||
#include "StreamingEngine.h"
|
||||
#include "vizionstreamer/StreamingEngine.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
@@ -33,12 +41,21 @@ private:
|
||||
std::string handleStartStream();
|
||||
std::string handleStopStream();
|
||||
std::string handleSetPipeline(const std::string& pipeline);
|
||||
std::string handleSetEHDRMode(const std::string& value);
|
||||
std::string handleSetEHDRExposureMin(const std::string& value);
|
||||
std::string handleSetEHDRExposureMax(const std::string& value);
|
||||
std::string handleSetEHDRRatioMin(const std::string& value);
|
||||
std::string handleSetEHDRRatioMax(const std::string& value);
|
||||
std::string handleGetEHDRStatus();
|
||||
|
||||
// Helper functions
|
||||
VX_IMAGE_FORMAT stringToFormat(const std::string& format);
|
||||
std::string formatToString(VX_IMAGE_FORMAT format);
|
||||
std::string createErrorResponse(const std::string& error);
|
||||
std::string createSuccessResponse(const std::string& message = "");
|
||||
static VX_IMAGE_FORMAT stringToFormat(const std::string& format);
|
||||
|
||||
static std::string formatToString(VX_IMAGE_FORMAT format);
|
||||
|
||||
static std::string createErrorResponse(const std::string& error);
|
||||
|
||||
static std::string createSuccessResponse(const std::string& message = "");
|
||||
|
||||
std::shared_ptr<VxCamera> camera_;
|
||||
std::shared_ptr<StreamingEngine> streamingEngine_;
|
||||
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* VizionStreamer - GStreamer Pipeline Interface
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* VizionStreamer - Unix Socket Server Interface
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
@@ -19,7 +27,7 @@ public:
|
||||
|
||||
private:
|
||||
void serverLoop();
|
||||
void handleClient(int clientFd);
|
||||
void handleClient(int clientFd) const;
|
||||
|
||||
std::string socketPath_;
|
||||
int serverFd_;
|
||||
@@ -1,7 +1,15 @@
|
||||
/*
|
||||
* VizionStreamer - Streaming Engine Interface
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vizionsdk/VizionSDK.h>
|
||||
#include "GStreamerPipeline.h"
|
||||
#include "vizionstreamer/GStreamerPipeline.h"
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
Diese Scripts ermöglichen die schnelle Steuerung von VizionStreamer über die Unix Domain Socket API.
|
||||
|
||||
**Copyright (c) 2025 Maik Jurischka**
|
||||
Lizenziert unter CC BY-NC-SA 4.0 - https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
|
||||
## Voraussetzung
|
||||
|
||||
VizionStreamer muss laufen:
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
#include "CameraController.h"
|
||||
/*
|
||||
* VizionStreamer - Camera Control Implementation
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#include "vizionstreamer/CameraController.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
@@ -18,9 +26,9 @@ std::string CameraController::processCommand(const std::string& jsonCommand) {
|
||||
return createErrorResponse("Missing command field");
|
||||
}
|
||||
|
||||
const size_t colonPos = jsonCommand.find(":", cmdPos);
|
||||
const size_t quoteStart = jsonCommand.find("\"", colonPos);
|
||||
const size_t quoteEnd = jsonCommand.find("\"", quoteStart + 1);
|
||||
const size_t colonPos = jsonCommand.find(':', cmdPos);
|
||||
const size_t quoteStart = jsonCommand.find('\"', colonPos);
|
||||
const size_t quoteEnd = jsonCommand.find('\"', quoteStart + 1);
|
||||
|
||||
if (quoteStart == std::string::npos || quoteEnd == std::string::npos) {
|
||||
return createErrorResponse("Invalid command format");
|
||||
@@ -33,10 +41,10 @@ std::string CameraController::processCommand(const std::string& jsonCommand) {
|
||||
const size_t pos = jsonCommand.find("\"" + paramName + "\"");
|
||||
if (pos == std::string::npos) return "";
|
||||
|
||||
const size_t colonPos = jsonCommand.find(":", pos);
|
||||
const size_t colonPos = jsonCommand.find(':', pos);
|
||||
|
||||
if (size_t valueStart = jsonCommand.find_first_not_of(" \t\n\r", colonPos + 1); jsonCommand[valueStart] == '\"') {
|
||||
size_t valueEnd = jsonCommand.find("\"", valueStart + 1);
|
||||
size_t valueEnd = jsonCommand.find('\"', valueStart + 1);
|
||||
return jsonCommand.substr(valueStart + 1, valueEnd - valueStart - 1);
|
||||
} else {
|
||||
size_t valueEnd = jsonCommand.find_first_of(",}", valueStart);
|
||||
@@ -74,6 +82,18 @@ std::string CameraController::processCommand(const std::string& jsonCommand) {
|
||||
return handleStopStream();
|
||||
} else if (command == "set_pipeline") {
|
||||
return handleSetPipeline(getParam("pipeline"));
|
||||
} else if (command == "set_ehdr_mode") {
|
||||
return handleSetEHDRMode(getParam("mode"));
|
||||
} else if (command == "set_ehdr_exposure_min") {
|
||||
return handleSetEHDRExposureMin(getParam("value"));
|
||||
} else if (command == "set_ehdr_exposure_max") {
|
||||
return handleSetEHDRExposureMax(getParam("value"));
|
||||
} else if (command == "set_ehdr_ratio_min") {
|
||||
return handleSetEHDRRatioMin(getParam("value"));
|
||||
} else if (command == "set_ehdr_ratio_max") {
|
||||
return handleSetEHDRRatioMax(getParam("value"));
|
||||
} else if (command == "get_ehdr_status") {
|
||||
return handleGetEHDRStatus();
|
||||
} else {
|
||||
return createErrorResponse("Unknown command: " + command);
|
||||
}
|
||||
@@ -86,7 +106,7 @@ std::string CameraController::handleSetFormat(const std::string& width, const st
|
||||
}
|
||||
|
||||
try {
|
||||
VxFormat fmt;
|
||||
VxFormat fmt{};
|
||||
fmt.width = std::stoi(width);
|
||||
fmt.height = std::stoi(height);
|
||||
fmt.framerate = std::stoi(framerate);
|
||||
@@ -111,13 +131,13 @@ std::string CameraController::handleGetFormats() {
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "{\"status\":\"success\",\"formats\":[";
|
||||
oss << R"({"status":"success","formats":[)";
|
||||
for (size_t i = 0; i < fmtList.size(); i++) {
|
||||
if (i > 0) oss << ",";
|
||||
oss << "{\"width\":" << fmtList[i].width
|
||||
<< ",\"height\":" << fmtList[i].height
|
||||
<< ",\"framerate\":" << fmtList[i].framerate
|
||||
<< ",\"format\":\"" << formatToString(fmtList[i].format) << "\"}";
|
||||
<< R"(,"format":")" << formatToString(fmtList[i].format) << "\"}";
|
||||
}
|
||||
oss << "]}";
|
||||
return oss.str();
|
||||
@@ -233,10 +253,93 @@ std::string CameraController::handleSetGain(const std::string& value) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string CameraController::handleSetEHDRMode(const std::string& value) {
|
||||
try {
|
||||
const int mode = std::stoi(value);
|
||||
if (VxSetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_IMAGE_EHDR_MODE, mode) != 0) {
|
||||
return createErrorResponse("Failed to set eHDR mode");
|
||||
}
|
||||
return createSuccessResponse("eHDR mode set successfully");
|
||||
} catch (const std::exception& e) {
|
||||
return createErrorResponse(std::string("Invalid parameters: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string CameraController::handleSetEHDRExposureMin(const std::string& value) {
|
||||
try {
|
||||
const int minExp = std::stoi(value);
|
||||
if (VxSetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_EXPOSURE_MIN_NUMBER, minExp) != 0) {
|
||||
return createErrorResponse("Failed to set eHDR exposure min");
|
||||
}
|
||||
return createSuccessResponse("eHDR exposure min set successfully");
|
||||
} catch (const std::exception& e) {
|
||||
return createErrorResponse(std::string("Invalid parameters: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string CameraController::handleSetEHDRExposureMax(const std::string& value) {
|
||||
try {
|
||||
const int maxExp = std::stoi(value);
|
||||
if (VxSetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_EXPOSURE_MAX_NUMBER, maxExp) != 0) {
|
||||
return createErrorResponse("Failed to set eHDR exposure max");
|
||||
}
|
||||
return createSuccessResponse("eHDR exposure max set successfully");
|
||||
} catch (const std::exception& e) {
|
||||
return createErrorResponse(std::string("Invalid parameters: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string CameraController::handleSetEHDRRatioMin(const std::string& value) {
|
||||
try {
|
||||
const int minRatio = std::stoi(value);
|
||||
if (VxSetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_RATIO_MIN, minRatio) != 0) {
|
||||
return createErrorResponse("Failed to set eHDR ratio min");
|
||||
}
|
||||
return createSuccessResponse("eHDR ratio min set successfully");
|
||||
} catch (const std::exception& e) {
|
||||
return createErrorResponse(std::string("Invalid parameters: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string CameraController::handleSetEHDRRatioMax(const std::string& value) {
|
||||
try {
|
||||
const int maxRatio = std::stoi(value);
|
||||
if (VxSetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_RATIO_MAX, maxRatio) != 0) {
|
||||
return createErrorResponse("Failed to set eHDR ratio max");
|
||||
}
|
||||
return createSuccessResponse("eHDR ratio max set successfully");
|
||||
} catch (const std::exception& e) {
|
||||
return createErrorResponse(std::string("Invalid parameters: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string CameraController::handleGetEHDRStatus() {
|
||||
int mode = 0, flag = 0;
|
||||
int expMin = 0, expMax = 0;
|
||||
int ratioMin = 0, ratioMax = 0;
|
||||
|
||||
if (VxGetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_IMAGE_EHDR_MODE, mode, flag) != 0) {
|
||||
return createErrorResponse("Failed to get eHDR mode");
|
||||
}
|
||||
|
||||
VxGetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_EXPOSURE_MIN_NUMBER, expMin, flag);
|
||||
VxGetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_EXPOSURE_MAX_NUMBER, expMax, flag);
|
||||
VxGetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_RATIO_MIN, ratioMin, flag);
|
||||
VxGetISPImageProcessing(camera_, VX_ISP_IMAGE_PROPERTIES::ISP_EHDR_RATIO_MAX, ratioMax, flag);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << R"({"status":"success","ehdr_mode":)" << mode
|
||||
<< ",\"exposure_min\":" << expMin
|
||||
<< ",\"exposure_max\":" << expMax
|
||||
<< ",\"ratio_min\":" << ratioMin
|
||||
<< ",\"ratio_max\":" << ratioMax << "}";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string CameraController::handleGetStatus() {
|
||||
std::ostringstream oss;
|
||||
oss << "{\"status\":\"success\",\"streaming\":" << (streamingEngine_->isRunning() ? "true" : "false")
|
||||
<< ",\"pipeline\":\"" << gstPipeline_ << "\"}";
|
||||
oss << R"({"status":"success","streaming":)" << (streamingEngine_->isRunning() ? "true" : "false")
|
||||
<< R"(,"pipeline":")" << gstPipeline_ << "\"}";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -285,7 +388,7 @@ VX_IMAGE_FORMAT CameraController::stringToFormat(const std::string& format) {
|
||||
return VX_IMAGE_FORMAT::NONE;
|
||||
}
|
||||
|
||||
std::string CameraController::formatToString(VX_IMAGE_FORMAT format) {
|
||||
std::string CameraController::formatToString(const VX_IMAGE_FORMAT format) {
|
||||
switch (format) {
|
||||
case VX_IMAGE_FORMAT::YUY2: return "YUY2";
|
||||
case VX_IMAGE_FORMAT::UYVY: return "UYVY";
|
||||
@@ -298,12 +401,12 @@ std::string CameraController::formatToString(VX_IMAGE_FORMAT format) {
|
||||
}
|
||||
|
||||
std::string CameraController::createErrorResponse(const std::string& error) {
|
||||
return "{\"status\":\"error\",\"message\":\"" + error + "\"}";
|
||||
return R"({"status":"error","message":")" + error + "\"}";
|
||||
}
|
||||
|
||||
std::string CameraController::createSuccessResponse(const std::string& message) {
|
||||
if (message.empty()) {
|
||||
return "{\"status\":\"success\"}";
|
||||
return R"({"status":"success"})";
|
||||
}
|
||||
return "{\"status\":\"success\",\"message\":\"" + message + "\"}";
|
||||
return R"({"status":"success","message":")" + message + "\"}";
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
#include "GStreamerPipeline.h"
|
||||
/*
|
||||
* VizionStreamer - GStreamer Pipeline Implementation
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#include "vizionstreamer/GStreamerPipeline.h"
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
@@ -1,4 +1,12 @@
|
||||
#include "SocketServer.h"
|
||||
/*
|
||||
* VizionStreamer - Unix Socket Server Implementation
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#include "vizionstreamer/SocketServer.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
@@ -19,10 +27,8 @@ bool SocketServer::start(CommandCallback callback) {
|
||||
|
||||
commandCallback_ = std::move(callback);
|
||||
|
||||
// Remove existing socket file if it exists
|
||||
unlink(socketPath_.c_str());
|
||||
|
||||
// Create Unix domain socket
|
||||
serverFd_ = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (serverFd_ < 0) {
|
||||
std::cerr << "Failed to create socket" << std::endl;
|
||||
@@ -62,14 +68,12 @@ void SocketServer::stop() {
|
||||
|
||||
running_ = false;
|
||||
|
||||
// Close server socket to unblock accept()
|
||||
if (serverFd_ >= 0) {
|
||||
shutdown(serverFd_, SHUT_RDWR);
|
||||
close(serverFd_);
|
||||
serverFd_ = -1;
|
||||
}
|
||||
|
||||
// Wait for server thread to finish
|
||||
if (serverThread_ && serverThread_->joinable()) {
|
||||
serverThread_->join();
|
||||
}
|
||||
@@ -93,7 +97,7 @@ void SocketServer::serverLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
void SocketServer::handleClient(const int clientFd) {
|
||||
void SocketServer::handleClient(const int clientFd) const {
|
||||
char buffer[4096];
|
||||
const ssize_t bytesRead = recv(clientFd, buffer, sizeof(buffer) - 1, 0);
|
||||
|
||||
@@ -101,10 +105,8 @@ void SocketServer::handleClient(const int clientFd) {
|
||||
buffer[bytesRead] = '\0';
|
||||
const std::string command(buffer);
|
||||
|
||||
// Call the command callback
|
||||
const std::string response = commandCallback_(command);
|
||||
|
||||
// Send response back to client
|
||||
send(clientFd, response.c_str(), response.length(), 0);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,18 @@
|
||||
#include "StreamingEngine.h"
|
||||
/*
|
||||
* VizionStreamer - Streaming Engine Implementation
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#include "vizionstreamer/StreamingEngine.h"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
|
||||
StreamingEngine::StreamingEngine(std::shared_ptr<VxCamera> camera)
|
||||
: camera_(std::move(camera)), running_(false), bufferSize_(0) {
|
||||
: camera_(std::move(camera)), running_(false), currentFormat_(), bufferSize_(0) {
|
||||
gstPipeline_ = std::make_unique<GStreamerPipeline>("");
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
/*
|
||||
* VizionStreamer - Main Application
|
||||
* Copyright (c) 2025 Maik Jurischka
|
||||
*
|
||||
* Licensed under CC BY-NC-SA 4.0
|
||||
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <csignal>
|
||||
#include <atomic>
|
||||
#include <vizionsdk/VizionSDK.h>
|
||||
#include "SocketServer.h"
|
||||
#include "CameraController.h"
|
||||
#include "vizionstreamer/SocketServer.h"
|
||||
#include "vizionstreamer/CameraController.h"
|
||||
|
||||
std::atomic<bool> g_running(true);
|
||||
|
||||
@@ -71,10 +79,8 @@ int main() {
|
||||
std::cout << "Initial format: " << fmtList[0].width << "x" << fmtList[0].height
|
||||
<< " @ " << fmtList[0].framerate << " fps" << std::endl;
|
||||
|
||||
// Create camera controller
|
||||
const auto controller = std::make_shared<CameraController>(cam);
|
||||
|
||||
// Start Unix domain socket server
|
||||
const std::string socketPath = "/tmp/vizion_control.sock";
|
||||
SocketServer server(socketPath);
|
||||
|
||||
@@ -88,8 +94,9 @@ int main() {
|
||||
|
||||
std::cout << "\n========================================" << std::endl;
|
||||
std::cout << "VizionStreamer Ready" << std::endl;
|
||||
std::cout << "Author: Maik Jurischka <m.jurischka@scidre.de" << std::endl;
|
||||
std::cout << "========================================" << std::endl;
|
||||
std::cout << "Author: Maik Jurischka <maik@skadilabs.de>" << std::endl;
|
||||
std::cout << "License: CC BY-NC-SA 4.0 -> https://creativecommons.org/licenses/by-nc-sa/4.0/" << std::endl;
|
||||
std::cout << "========================================" << std::endl << std::endl;
|
||||
std::cout << "Control socket: " << socketPath << std::endl;
|
||||
std::cout << "Default pipeline: videoconvert ! autovideosink" << std::endl;
|
||||
std::cout << "\nQuick start:" << std::endl;
|
||||
@@ -98,15 +105,12 @@ int main() {
|
||||
std::cout << R"( 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) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
std::cout << "Shutting down..." << std::endl;
|
||||
|
||||
// Stop streaming engine if running
|
||||
if (controller->getStreamingEngine()->isRunning()) {
|
||||
controller->getStreamingEngine()->stop();
|
||||
}
|
||||
Reference in New Issue
Block a user