#pragma once #include "fgc/CameraProfile.h" #include "fgc/RawImage.h" #include "fgc/SettleRule.h" #include #include #include #include namespace fgc { // One captured frame, owning a copy of its pixel buffer (was image_store_8bit). struct Frame { std::vector 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; }; // 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; 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 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 deviceInfo() { 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