#pragma once #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; uint32_t width = 0; uint32_t height = 0; int channels = 0; // 1 (mono) or 3 (RGB) long long timestamp_ms = 0; // Unix epoch ms int cam_id = 0; // index into the configured camera list // Set when the quality gate ran out of attempts and emitted its best effort // anyway. Carried through to the CamEvent so degraded frames stay identifiable // downstream instead of being silently mixed in with good ones. bool degraded = false; }; // 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 wb_red = 0.0; double wb_blue = 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), MockCameraSource (synthetic frames, no hardware), and // GatedCameraSource (a decorator adding the image-quality gate). // // 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. In free-run this hands over the freshest streamed frame; behind the // quality gate it runs the whole acquire/judge/correct loop. virtual bool trigger() = 0; // Optional: change the acquisition frame rate. Default no-op (e.g. mocks). virtual bool setFrameRate(double /*fps*/) { return false; } // ---- Deliberate acquisition + manual exposure control ---- // Used by GatedCameraSource to shoot, measure and reshoot. Defaults are no-ops // (following setFrameRate above) so mocks and existing tests need no changes; // a source that returns false from acquireFrame simply cannot be gated. // Acquire exactly ONE frame and return it here rather than via the callback, // so the caller can judge it before deciding whether to keep it. virtual bool acquireFrame(Frame& /*out*/, int /*timeout_ms*/) { return false; } virtual bool setExposure(double /*microseconds*/) { return false; } virtual bool setGain(double /*db*/) { return false; } // Turn the camera's own continuous auto-exposure/gain on or off. The gate owns // exposure, so it switches these off; free-run leaves them on. virtual bool setAutoExposureGain(bool /*on*/) { return false; } // Gain actually in effect, in dB (what the camera reports, not what we asked // for) - the noise proxy the policy gates on. virtual double currentGain() { return 0.0; } virtual void setFrameCallback(FrameCallback cb) = 0; // 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 {}; } }; } // namespace fgc