Class VideoManager#
Defined in File video_manager.hpp
Nested Relationships#
Nested Types#
Inheritance Relationships#
Base Type#
public QObject
Class Documentation#
-
class VideoManager : public QObject#
Orchestrates one VideoGrabber + VideoEncoder pair per configured camera.
VideoManager owns the complete video pipeline for a session. It matches the lifecycle of the cameras: open them once at startup, then start/stop recording repeatedly without reopening.
Frames are passed between threads through a lock-free SPSC RingBuffer. All public methods of VideoManager itself must be called from the main thread.
- Thread model
Each camera runs two background threads:
VideoGrabber — grabs frames from Pylon (or generates test patterns).
VideoEncoder — encodes frames via FFmpeg and writes the timestamp CSV.
See also
VideoGrabber, VideoEncoder, FrameTimestampWriter, RecordManager
- Lifecycle
VideoManager vm; int opened = vm.open(settings.video); // opens cameras once // Start/stop can repeat throughout the session vm.start("recordings/2026-06-04_14-32-05", "video", settings.video); // ... recording in progress ... vm.stop(); // blocks until all encoders have flushed and closed their files vm.close(); // release camera handles (called by destructor)
Public Functions
-
explicit VideoManager(QObject *parent = nullptr)#
-
~VideoManager() override#
-
int open(const VideoSettings &settings)#
Opens camera devices (or stub generators) for all configured cameras.
- Parameters:
settings – Video settings from AppSettings. The
camerasvector determines how many devices are opened.- Returns:
The number of cameras successfully opened. May be less than
settings.cameras.size()if some devices fail.
-
void start_preview()#
Starts the grab loop for all cameras without creating encoders.
Call this after open() to see live preview frames in the QML monitor before any recording session begins. Safe to call if grabbers are already running (no-op for those cameras).
-
void start(const QString &sessionDir, const QString &videoBasename, const VideoSettings &settings)#
Starts grabbing and encoding for all open cameras.
Output files:
<sessionDir>/<videoBasename>_N.mp4<sessionDir>/timestamps_camN.csv
- Parameters:
sessionDir – Absolute path to the session folder (must exist).
videoBasename – Basename for video files (e.g.
"video").settings – Video settings (codec, preset, per-camera FPS/resolution).
-
void stop()#
Stops all grabbers and encoders, flushing and closing every file.
Blocks until all encoder threads have exited (up to 10 s per camera).
-
void apply_live_params(int configIndex)#
Re-applies exposure/gain/gamma/black-level/white-balance/ auto-target/digital-shift for one camera to already-open hardware, without stopping or reopening it.
Call this after the caller has mutated the corresponding CameraParameters in place (e.g. via the settings UI). Structural parameters (resolution, pixel format, frame rate, hardware trigger) still require a full close()+open() to take effect and are not touched by this call.
- Parameters:
configIndex – Position in the configured settings.cameras array (VideoManager::CameraUnit::configIndex), not the camera’s position among successfully opened units. No-op if no open unit matches.
-
void request_calibration_frame(int configIndex, uint64_t token = 0)#
Requests one full-resolution frame from the given camera for room (extrinsic) calibration — see VideoGrabber::request_calibration_frame(). Delivered asynchronously via calibration_frame_ready(), echoing token back verbatim so a caller that requests one frame per “shot” can reject a reply for a shot it has already moved past. No-op if no open unit matches configIndex.
-
bool is_recording() const#
- Returns:
truewhile a recording session is active.
-
bool is_previewing() const#
- Returns:
truewhile a live preview session is active (started via start_preview(), not yet stopped by start()/close()). Used to guard actions that would race with a running ActionCommandTicker, which touches Pylon’s CTlFactory from a background thread for as long as either preview or recording keeps it alive.
-
int camera_count() const#
- Returns:
The number of cameras that were successfully opened.
-
int64_t total_frames_encoded() const#
- Returns:
Total frames encoded across all cameras since the last start().
-
int64_t total_frames_dropped() const#
- Returns:
Total frames dropped (ring buffer overflow) since last start().
-
CameraStats camera_stats(int index) const#
Returns a performance snapshot for one camera.
- Parameters:
index – Zero-based camera index. Returns a zeroed struct if out of range.
Signals
-
void camera_opened(int cameraIndex, int width, int height, double fps)#
Emitted on the main thread when a camera device is successfully opened.
-
void camera_closed(int cameraIndex)#
Emitted when a camera device is closed.
-
void frame_dropped(int cameraIndex, int64_t frameId)#
Emitted each time a frame is dropped because the ring buffer was full.
- Parameters:
cameraIndex – Which camera dropped the frame.
frameId – The frame counter value of the dropped frame.
-
void camera_error(int cameraIndex, QString message)#
Emitted when a camera grab or encode error occurs.
-
void recording_stopped()#
Emitted when all encoders have finished (files closed and flushed).
-
void frame_preview(int cameraIndex, QImage frame)#
Throttled (~15 fps) BGR preview for live QML display.
-
void calibration_frame_ready(int cameraIndex, QImage frame, uint64_t token)#
Full-resolution frame delivered in response to request_calibration_frame(). token is whatever was passed to request_calibration_frame().
-
void action_command_capability(int cameraIndex, bool supported)#
Passthrough of VideoGrabber::action_command_capability() — reports whether a camera’s firmware supports GigE Vision Action Command triggering, once probed at open() time. Only fires for cameras that actually requested Action1 triggering (hwTriggerEnabled && hwTriggerSource == “Action1”).
-
struct CameraStats#
Per-camera real-time performance snapshot.