fwt_software/include/fgc/ICameraSource.h

164 lines
7.0 KiB
C++

#pragma once
#include "fgc/CameraProfile.h"
#include "fgc/RawImage.h"
#include "fgc/SettleRule.h"
#include "fgc/ThermalStats.h"
#include <cstdint>
#include <functional>
#include <optional>
#include <string>
#include <vector>
namespace fgc {
// One captured frame, owning a copy of its pixel buffer (was image_store_8bit).
struct Frame {
std::vector<uint8_t> data; // as delivered: BayerRG12p stays packed
uint32_t width = 0;
uint32_t height = 0;
int channels = 0; // values per pixel as delivered: 3 (RGB) or 1 (mono, Bayer mosaic)
// How `data` is laid out. Unknown only for a format the program does not
// handle; `channels` then says what it holds, as before layouts existed.
PixelLayout layout = PixelLayout::Unknown;
long long timestamp_ms = 0; // Unix epoch ms
int cam_id = 0; // index into the configured camera list
// What the camera says it exposed this frame with (its per-frame chunk
// data). Negative when the profile does not turn chunk data on.
double exposure_us = -1.0;
double gain_db = -1.0;
double wb_red = -1.0; // BalanceRatio, red against green
double wb_blue = -1.0;
// Sampled from `data` on arrival (see RawImage.h); invalid when the layout
// is Unknown.
BrightnessSample brightness;
// Set by a thermal camera only: how to read its Mono16 counts.
std::optional<ThermalFrameInfo> thermal;
};
// Live per-camera identity, sensor telemetry, and acquisition stats, for the
// expanded camera view. Populated by deviceInfo(); fields the source can't read
// are left at their defaults.
struct CameraDeviceInfo {
std::string id;
std::string model;
std::string serial;
bool streaming = false;
// Current frame geometry as delivered.
uint32_t width = 0;
uint32_t height = 0;
long long payload_bytes = 0;
// Live sensor telemetry (read from the camera, throttled).
double exposure_us = 0.0;
double gain_db = 0.0;
double temperature_c = 0.0;
double actual_fps = 0.0;
// Cumulative acquisition stats since the source was created.
long long frames_delivered = 0;
long long frames_dropped = 0; // incomplete/invalid deliveries
long long restarts = 0; // stream restarts (restart-on-stall)
};
// Abstraction over the camera array. Implemented by VimbaCameraSource (Allied
// Vision Vimba X) and MockCameraSource (synthetic frames, no hardware).
//
// Completed frames are delivered to the callback set via setFrameCallback();
// the consumer (ImagePipeline) encodes and stores them.
class ICameraSource {
public:
using FrameCallback = std::function<void(const Frame&)>;
virtual ~ICameraSource() = default;
virtual void open() = 0; // acquire/open cameras
virtual void close() = 0;
virtual void start() = 0; // begin acquisition
virtual void stop() = 0;
// Capture one image and deliver it to the frame callback. Returns true on
// success. The camera free-runs, so this hands over the freshest complete
// frame; it returns false when no frame newer than the last one is available
// yet, and the caller simply retries.
virtual bool trigger() = 0;
// Apply a profile to one camera, identified by its index in the order the
// source opened them (the same index Frame::cam_id carries). The backend
// loads the profile's settings XML through its SDK - see CameraProfile.h.
// Default: no-op, for sources with nothing to configure.
virtual bool setProfile(int /*camera_index*/, const CameraProfile& /*profile*/) {
return false;
}
virtual void setFrameCallback(FrameCallback cb) = 0;
// ---- For the keep rule (SettleRule.h) ---------------------------------------
// The most recent frames camera 0 delivered, with their brightness, exposure
// and gain. Sequence numbers count up for the session; framesSince(n) returns
// the frames after n, oldest first (only the last few dozen are kept).
// frameSeq() is the newest sequence number. Default: no frames, and the scan
// keeps its fixed settle wait.
virtual uint64_t frameSeq() { return 0; }
virtual std::vector<FrameStats> framesSince(uint64_t /*after*/) { return {}; }
// A numeric camera feature (IntensityControllerTarget, ExposureAutoMax...).
// False if the camera has no such feature.
virtual bool readFeature(int /*camera_index*/, const std::string& /*name*/, double& /*value*/) {
return false;
}
// Number of cameras this source manages.
virtual int cameraCount() const = 0;
// Live identity/telemetry/stats per camera, for the expanded camera view.
// Default: none. Implementations may refresh a throttled cache, so non-const.
virtual std::vector<CameraDeviceInfo> deviceInfo() { return {}; }
// Why one camera delivers nothing right now ("not found on the network"),
// or empty while it works. For a camera the scan can do without (the
// thermal one), which reconnects by itself rather than stopping the run.
// Default: always working.
virtual std::string offline(int /*camera_index*/) { return {}; }
// ---- For `test camera` only ------------------------------------------------
// The camera's configuration otherwise changes through setProfile() and
// nothing else; these let the self-test drive a camera to known extremes and
// then put it back. Defaults: unsupported, which the test reports as "not
// checked" rather than as a fault.
// The next complete frame from one camera that arrives after this call, into
// `out`. False if none arrives within `timeout_ms`. The stream must be
// running (start()); this does not start it.
virtual bool grabFrame(int /*camera_index*/, Frame& /*out*/, int /*timeout_ms*/) {
return false;
}
// Set one camera feature by its GenICam name, the value given as text ("Off",
// "66.4", "true"). False if the camera has no such feature or refuses it.
virtual bool setFeature(int /*camera_index*/, const std::string& /*name*/,
const std::string& /*value*/) {
return false;
}
// A numeric feature's range. False if absent or not numeric.
virtual bool featureRange(int /*camera_index*/, const std::string& /*name*/,
double& /*min*/, double& /*max*/) {
return false;
}
// Put a camera back on the profile it was configured with, undoing every
// setFeature() since. False if that failed - which leaves the camera on
// settings nobody chose, so callers must say so loudly.
virtual bool restoreProfile(int /*camera_index*/) { return false; }
// Reboot one camera (GenICam DeviceReset), reopen it and put it back on its
// profile. The last resort for a stream that nothing else will restart - and
// the operator's `camera reset`. Blocks while the camera comes back (seconds).
virtual bool resetCamera(int /*camera_index*/) { return false; }
};
} // namespace fgc