d8e69c6392
User: "при движении объект оборачивается в рамку, но функционал не
учитывает что сетки могут переключаться и координаты ячеек меняются".
Был баг: detbox-overlay хранил cell_x/y/w/h из --detection-cell CLI
(заданы при старте), при смене layout рамки рисовались по старым
координатам — мимо камеры.
Изменения:
- overlay.h/.c: новый API cfc_overlay_detbox_set_cell_geom(ov,x,y,w,h).
Mutex-защищённое обновление detbox config'а — composer вызывает
перед каждым draw.
- CameraCell: добавлено поле source_key (хранит cuframes-key камеры,
рендерящейся в этом cell). Layout::apply передаёт его из pool entry.
- Layout::find_camera_cell_rect(key) — возвращает Rect текущей cell
для камеры с заданным cuframes-key (или nullptr если её нет в layout).
- SourcePool::by_frigate_camera(name) — lookup pool-entry по
Frigate-camera-key (frigate event'ы приходят с этим именем).
- Composer::compose_frame: перед draw каждого DETECTION_BOXES overlay'я
— lookup frigate→cuframes_key→layout cell rect, обновляет detbox geom.
Если камера не в layout сейчас — cell_w/h=0, detbox draw skip'ает.
Теперь bbox от Frigate переезжает за камерой:
- tpl_1 → bbox в full screen 1920×1080
- tpl_3 → bbox в main 1440×810
- tpl_4 → bbox в quad ячейке 960×540
- камера не в layout → bbox скрыт
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
97 lines
3.1 KiB
C++
97 lines
3.1 KiB
C++
/* SourcePool — пул cuframes-источников композитора (Phase 11b).
|
||
*
|
||
* Каждая запись: cuframes_key + frigate_camera + priority + cfc_source_t* +
|
||
* motion state (last_motion_ms, zone-filter). Pool создаётся при старте
|
||
* композитора (через add() вызовы) и живёт всю сессию.
|
||
*
|
||
* Cells (CameraCell) держат non-owning указатели на cfc_source_t — pool
|
||
* владеет.
|
||
*
|
||
* Лицензия: LGPL-2.1+
|
||
*/
|
||
|
||
#ifndef CUFRAMES_COMPOSER_CPP_SOURCE_POOL_HPP
|
||
#define CUFRAMES_COMPOSER_CPP_SOURCE_POOL_HPP
|
||
|
||
#include "../source.h"
|
||
|
||
#include <atomic>
|
||
#include <memory>
|
||
#include <mutex>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace cfc {
|
||
|
||
struct PoolEntry {
|
||
std::string cuframes_key;
|
||
std::string frigate_camera;
|
||
int priority = 0;
|
||
cfc_source_t* source = nullptr;
|
||
std::atomic<std::int64_t> last_motion_ms{0};
|
||
std::vector<std::string> required_zones;
|
||
|
||
/* Получить snapshot для drawable-checks без локов. */
|
||
cfc_source_state_t state() const {
|
||
if (!source) return CFC_SOURCE_DISCONNECTED;
|
||
cfc_source_snapshot_t s{};
|
||
cfc_source_get_latest(source, &s);
|
||
return s.state;
|
||
}
|
||
|
||
bool drawable() const {
|
||
cfc_source_state_t st = state();
|
||
return st == CFC_SOURCE_ACTIVE || st == CFC_SOURCE_STALE;
|
||
}
|
||
};
|
||
|
||
class SourcePool {
|
||
public:
|
||
SourcePool() = default;
|
||
~SourcePool();
|
||
|
||
SourcePool(const SourcePool&) = delete;
|
||
SourcePool& operator=(const SourcePool&) = delete;
|
||
|
||
/* Параметры подписки cuframes (default per cfc_source_config_t). */
|
||
struct SubscribeOpts {
|
||
int cuda_device = 0;
|
||
std::string consumer_prefix = "composer";
|
||
int reconnect_min_ms = 1000;
|
||
int reconnect_max_ms = 30000;
|
||
int stale_threshold_ms = 500;
|
||
int dead_threshold_ms = 5000;
|
||
};
|
||
|
||
/* Добавить источник в pool. Возвращает индекс или -1. */
|
||
int add(const std::string& cuframes_key,
|
||
const std::string& frigate_camera,
|
||
int priority,
|
||
const std::vector<std::string>& zones,
|
||
const SubscribeOpts& opts);
|
||
|
||
int size() const { return static_cast<int>(entries_.size()); }
|
||
PoolEntry* by_index(int i) { return i >= 0 && i < size() ? entries_[i].get() : nullptr; }
|
||
PoolEntry* by_key(const std::string& key);
|
||
PoolEntry* by_frigate_camera(const std::string& frigate_camera);
|
||
|
||
/* Уведомить о motion (вызывается из Frigate MQTT subscriber'а через
|
||
* C-shim). Если zone-filter задан — проверяет пересечение. */
|
||
void motion_pulse(const std::string& frigate_camera,
|
||
const std::vector<std::string>& current_zones);
|
||
|
||
/* Итерация (для best-fit selection и health). */
|
||
template <typename F>
|
||
void for_each(F&& fn) {
|
||
for (auto& e : entries_) fn(*e);
|
||
}
|
||
|
||
private:
|
||
std::vector<std::unique_ptr<PoolEntry>> entries_;
|
||
std::mutex mu_;
|
||
};
|
||
|
||
} // namespace cfc
|
||
|
||
#endif /* CUFRAMES_COMPOSER_CPP_SOURCE_POOL_HPP */
|