beb8e1baa0
Что в этом коммите:
Decoration реализации:
- cpp/label_decoration.hpp/.cpp — FreeType atlas + cugrid_blit_rgba_nv12.
UTF-8 декодер, atlas в VRAM (RAII через CudaBuffer), rebuild при set_text.
- cpp/border_decoration.hpp/.cpp — 4 cugrid_fill_nv12 (top/bottom/left/right).
Cell реализации:
- cpp/camera_cell.hpp/.cpp — cfc_source_get_latest + cugrid_resize_nv12.
Non-owning указатель на cfc_source_t (pool владеет).
- cpp/widget_cell.hpp/.cpp — тёмный fill placeholder.
- cpp/blank_cell.hpp/.cpp — BT.709 black fill.
Layout и Template:
- cpp/template.hpp — LayoutTemplate { name, cells[], priority }.
8×8 микро-сетка (kGridCols=kGridRows=8). to_pixels() переводит в Rect.
- cpp/layout.hpp/.cpp — vector<unique_ptr<Cell>>, apply() создаёт
CameraCell/WidgetCell/BlankCell + Decorations (Label с "{key} prio={N}").
- cpp/template_loader.hpp/.cpp — JSON → vector<LayoutTemplate> через json-c.
builtin_templates() = { tpl_1, tpl_4 } как fallback.
SourcePool:
- cpp/source_pool.hpp/.cpp — owner cfc_source_t*, motion state атомарный,
zone-filter в motion_pulse. Pool entries — non-copyable unique_ptr.
Composer:
- cpp/composer.hpp/.cpp — owner SourcePool + templates + Layout + output.
Алгоритмы: pick_best_fit (min nb_camera_cells >= need + priority tie-break),
collect_active (drawable AND motion_within_TTL), asymmetric hysteresis
(рост сразу через std::includes, сжатие — wait shrink_hysteresis_ms).
Public C++ API: set_motion_mode / set_layout / load_templates / compose_frame.
ООП-гипотеза smoke:
- examples/grid_record_cpp.cpp — минимальный smoke без NVENC. Init composer,
compose_frame N раз, dump NV12 в файл. Проверяет что C++ модель
компилируется, линкуется с C-кодом (source.c, nvenc.c остались на C через
extern "C"), и реально рисует кадр.
Производительность сохранена:
- Один output буфер VMM, передаётся как NV12Ref (read-write reference) во все
cells/decorations — НИКАКИХ memcpy на cells boundary.
- Virtual call overhead: 1 indirect call per cell per frame. Negligible.
- Heap allocations только при apply_template (раз в N секунд при relayout).
Build:
- CMakeLists.txt: CXX language, C++17.
- src/CMakeLists.txt: COMPOSER_SOURCES_CPP добавлен в lib.
- examples/CMakeLists.txt: grid_record_cpp.
Smoke test run jammy:
[cfc/loader] docker/templates.json: loaded 7 templates
[smoke] composer 1920x1080 templates=7 sources=0 motion=0
[smoke] wrote 3317760 bytes (Y=2211840 UV=1105920) to /out/blank.nv12
Build PASS, init PASS, compose PASS, dump PASS.
Что НЕ сделано:
- extern "C" ABI shim для control.c / grid_record.c (старый C-композитор
всё ещё единственный для prod stack).
- Удаление старых composer.c / overlay.c / layouts.c.
- Live deploy в прод (Step 1-3 функциональность).
- JSON ZMQ hot-reload (был в Step 3 C-version, восстановить в C++).
Refs: #195 (Phase 11b C++ refactor).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58 lines
2.0 KiB
C++
58 lines
2.0 KiB
C++
/* Layout — контейнер cells и оркестратор apply_template (Phase 11b).
|
||
*
|
||
* Layout::apply() принимает LayoutTemplate + список активных pool-entries
|
||
* (sorted by priority DESC) + output W×H. Создаёт нужные Cell-подклассы:
|
||
*
|
||
* CameraCell для каждой template-cell с role=CAMERA — берёт source
|
||
* по индексу из active list (active[0]=order 0, active[1]=order 1, ...)
|
||
* Если active меньше чем camera-cells — лишние cells = BlankCell.
|
||
* WidgetCell для template-cell с role=WIDGET — placeholder.
|
||
*
|
||
* Decorations добавляются здесь же:
|
||
* LabelDecoration "{key} prio={N}" в каждый CameraCell.
|
||
* LabelDecoration с именем widget'а в каждый WidgetCell.
|
||
* (Border, Badge — Phase 12+)
|
||
*
|
||
* Layout::render(stream, dst) — итеративно вызывает cell->draw().
|
||
*
|
||
* Лицензия: LGPL-2.1+
|
||
*/
|
||
|
||
#ifndef CUFRAMES_COMPOSER_CPP_LAYOUT_HPP
|
||
#define CUFRAMES_COMPOSER_CPP_LAYOUT_HPP
|
||
|
||
#include "cell.hpp"
|
||
#include "source_pool.hpp"
|
||
#include "template.hpp"
|
||
|
||
#include <memory>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace cfc {
|
||
|
||
class Layout {
|
||
public:
|
||
Layout() = default;
|
||
|
||
/* Применить template — пересоздаёт cells + decorations.
|
||
* active_sorted — список pool-entries, уже отсортированный priority DESC. */
|
||
void apply(const LayoutTemplate& tpl,
|
||
const std::vector<PoolEntry*>& active_sorted,
|
||
int frame_w, int frame_h);
|
||
|
||
/* Прорисовать все cells в dst буфер. */
|
||
void render(CUstream stream, NV12Ref& dst);
|
||
|
||
const std::string& name() const noexcept { return current_name_; }
|
||
int cell_count() const noexcept { return static_cast<int>(cells_.size()); }
|
||
|
||
private:
|
||
std::vector<std::unique_ptr<Cell>> cells_;
|
||
std::string current_name_;
|
||
};
|
||
|
||
} // namespace cfc
|
||
|
||
#endif /* CUFRAMES_COMPOSER_CPP_LAYOUT_HPP */
|