cmvr-es/cmvr-es/service/grpc/server/include/camera_ptz_activity_registry.h

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