Files
cuframes-composer/include/cuframes_composer/cpp/layout.hpp
T
gx beb8e1baa0 Phase 11b B-E: ООП-гипотеза проверена end-to-end
Что в этом коммите:

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>
2026-06-03 21:43:18 +01:00

58 lines
2.0 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.
/* 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 */