81 lines
2.6 KiB
C++
81 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include "fgc/ICameraSource.h"
|
|
#include "fgc/IControlChannel.h"
|
|
|
|
#include <atomic>
|
|
#include <condition_variable>
|
|
#include <functional>
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <queue>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
namespace fgc {
|
|
|
|
// Gimbal orientation in degrees, stamped onto each CamEvent.
|
|
struct Orientation {
|
|
float yaw_deg = 0.f;
|
|
float pitch_deg = 0.f;
|
|
};
|
|
|
|
// Consumes captured frames and turns them into stored artifacts: rotate 90 deg
|
|
// CCW, encode to JPEG XL, write to <output_dir>/<label>/<timestamp>.jxl, and
|
|
// publish a CamEvent. Runs a background worker so encoding never blocks
|
|
// acquisition. Split out of the old VimbaHandler::SaveImage so any camera
|
|
// source (real or mock) can feed it.
|
|
class ImagePipeline {
|
|
public:
|
|
struct Params {
|
|
std::string output_dir;
|
|
std::vector<std::string> labels = {"RGB", "ACR", "NIR"}; // by camera index
|
|
std::string tower;
|
|
double jxl_distance = 2.0; // 0 = lossless
|
|
int jxl_effort = 3;
|
|
bool demo = false; // copy demo_image instead of encoding
|
|
std::string demo_image = "test_smoke.jxl";
|
|
bool display = false; // show an OpenCV preview window
|
|
};
|
|
|
|
// orientation: returns the current gimbal yaw+pitch (degrees) for CamEvent.
|
|
ImagePipeline(IControlChannel& channel, std::function<Orientation()> orientation, Params params);
|
|
~ImagePipeline();
|
|
|
|
void start();
|
|
void stop();
|
|
|
|
// Enqueue a frame for processing (thread-safe; copies the frame).
|
|
void submit(const Frame& frame);
|
|
|
|
// Runtime-adjustable encoder settings (console "set camera ..." commands).
|
|
void setDistance(double d) { params_.jxl_distance = d; }
|
|
void setEffort(int e) { params_.jxl_effort = e; }
|
|
void setDisplay(bool on) { params_.display = on; }
|
|
|
|
// Last CamEvent published (camera label, heading/pitch, timestamp), for the
|
|
// UI's camera panel. Thread-safe; nullopt until the first capture is saved.
|
|
std::optional<CamEvent> lastEvent() const;
|
|
|
|
private:
|
|
void run();
|
|
void process(const Frame& frame);
|
|
std::string labelFor(int cam_id) const;
|
|
|
|
IControlChannel& channel_;
|
|
std::function<Orientation()> orientation_;
|
|
Params params_;
|
|
|
|
std::queue<Frame> queue_;
|
|
std::mutex mutex_;
|
|
std::condition_variable cv_;
|
|
std::atomic<bool> running_{false};
|
|
std::thread worker_;
|
|
|
|
mutable std::mutex last_event_mutex_;
|
|
std::optional<CamEvent> last_event_;
|
|
};
|
|
|
|
} // namespace fgc
|