97 lines
3.1 KiB
C++
97 lines
3.1 KiB
C++
#ifndef CMVR_ES_CAMERA_PTZ_ACTIVITY_REGISTRY_H
|
|
#define CMVR_ES_CAMERA_PTZ_ACTIVITY_REGISTRY_H
|
|
|
|
#include <atomic>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "devices/camera/abstract_camera.h"
|
|
|
|
namespace cmvr::service {
|
|
|
|
// Tracks PTZ commands whose START has not yet been paired with a successful
|
|
// STOP. The registry is an operational control boundary; it never invokes a
|
|
// camera lifecycle method.
|
|
class CameraPtzActivityRegistry final {
|
|
public:
|
|
enum class DispatchResult {
|
|
Success,
|
|
RejectedByStopAll,
|
|
RejectedByDispatchFence,
|
|
DeviceFailure,
|
|
};
|
|
|
|
using DispatchFence = std::function<bool()>;
|
|
|
|
DispatchResult control(
|
|
const std::string& device_id,
|
|
const std::shared_ptr<device::AbstractCamera>& camera,
|
|
device::PtzCommand command,
|
|
bool stop,
|
|
int speed,
|
|
DispatchFence dispatch_fence = {});
|
|
|
|
// Reconciles externally stopped camera PTZ state with this registry. A
|
|
// camera backend can call this if it stops PTZ outside CameraService.
|
|
void markCameraStopped(const std::string& device_id);
|
|
|
|
// StopAll must close the process-wide admission gate before calling this.
|
|
// A true result means every tracked START received a successful matching
|
|
// STOP. Failed entries are retained so a later StopAll can retry them.
|
|
bool stopAllActivities(std::vector<std::string>* failures = nullptr);
|
|
|
|
// StopAll must close the process-wide admission gate first. Stops only PTZ
|
|
// commands tracked for device_id. Calls for different physical cameras may
|
|
// execute concurrently; calls for one camera remain ordered with control().
|
|
bool stopActivitiesForDevice(
|
|
const std::string& device_id,
|
|
std::vector<std::string>* failures = nullptr);
|
|
|
|
std::size_t activeCommandCount() const;
|
|
// Does not wait for per-device driver I/O. This conservative snapshot
|
|
// includes devices with an admitted or historical dispatch state, allowing
|
|
// StopAll to cover activity absent from the DeviceManager snapshot.
|
|
std::vector<std::string> trackedDeviceIds() const;
|
|
std::vector<std::string> activeDeviceIds() const;
|
|
void clearForTesting();
|
|
|
|
private:
|
|
struct PtzCommandHash {
|
|
std::size_t operator()(device::PtzCommand command) const noexcept
|
|
{
|
|
return static_cast<std::size_t>(command);
|
|
}
|
|
};
|
|
|
|
struct ActiveCommand {
|
|
std::shared_ptr<device::AbstractCamera> camera;
|
|
int speed{0};
|
|
};
|
|
|
|
using CameraCommands = std::unordered_map<
|
|
device::PtzCommand, ActiveCommand, PtzCommandHash>;
|
|
|
|
struct DeviceState {
|
|
mutable std::mutex mutex;
|
|
CameraCommands commands;
|
|
std::atomic<std::size_t> active_command_count{0U};
|
|
};
|
|
|
|
std::shared_ptr<DeviceState> stateForDevice(
|
|
const std::string& device_id,
|
|
bool create);
|
|
|
|
mutable std::mutex states_mutex_;
|
|
std::unordered_map<std::string, std::shared_ptr<DeviceState>> states_;
|
|
};
|
|
|
|
CameraPtzActivityRegistry& globalCameraPtzActivityRegistry();
|
|
|
|
} // namespace cmvr::service
|
|
|
|
#endif // CMVR_ES_CAMERA_PTZ_ACTIVITY_REGISTRY_H
|