Files
cuframes-composer/include/cuframes_composer/cpp/source_pool.hpp
T
gx d8e69c6392 Phase 11b: detection-box bbox следует за камерой при смене layout
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>
2026-06-04 10:25:25 +01:00

97 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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 */