#pragma once #include #include #include #include #include #include #include #include "behavior/behavior_event.h" #include "hw/frame_buffer.h" #include "frame/rect.h" namespace rk3588 { struct FaceDetResult; struct FaceRecogResult; struct PoseResult; enum class PixelFormat { NV12, YUV420, RGB, BGR, UNKNOWN }; struct Detection { int cls_id = -1; float score = 0.0f; Rect bbox{}; int track_id = -1; }; struct DetectionResult { std::vector items; int img_w = 0; int img_h = 0; std::string model_name; }; struct FrameTransformMeta { bool valid = false; bool letterbox = false; int src_w = 0; int src_h = 0; int dst_w = 0; int dst_h = 0; float scale_x = 1.0f; float scale_y = 1.0f; float pad_x = 0.0f; float pad_y = 0.0f; }; struct FramePlane { uint8_t* data = nullptr; int stride = 0; // bytes per row int size = 0; // valid bytes in this plane int offset = 0; // offset from base data pointer }; struct Frame { int width = 0; int height = 0; PixelFormat format = PixelFormat::UNKNOWN; // Fallback stride for single-plane formats; prefer per-plane stride. int stride = 0; int dma_fd = -1; uint64_t pts = 0; // microseconds uint64_t frame_id = 0; uint8_t* data = nullptr; // base pointer if mapped to CPU size_t data_size = 0; // total mapped buffer size int plane_count = 0; std::array planes{}; // Optional owner to keep underlying buffer alive (e.g., shared_ptr> or MPP buffer). std::shared_ptr data_owner; std::shared_ptr buffer; std::shared_ptr det; std::shared_ptr behavior_events; std::shared_ptr pose; // Face recognition pipeline meta (kept separate from user_meta to avoid conflicts with publish). std::shared_ptr face_det; std::shared_ptr face_recog; std::shared_ptr transform_meta; std::shared_ptr user_meta; int DmaFd() const { return buffer ? buffer->DmaFd() : dma_fd; } void SetDmaFd(int fd) { dma_fd = fd; if (buffer) buffer->SetDmaFd(fd); } const std::shared_ptr& Owner() const { return buffer ? buffer->Owner() : data_owner; } void SetOwner(std::shared_ptr owner) { data_owner = std::move(owner); if (buffer) buffer->SetOwner(data_owner); } void SyncStart() const { if (buffer) { buffer->SyncStart(); } else if (dma_fd >= 0) { DmaSyncStartFd(dma_fd); } } void SyncEnd() const { if (buffer) { buffer->SyncEnd(); } else if (dma_fd >= 0) { DmaSyncEndFd(dma_fd); } } std::shared_ptr EnsureBuffer() { if (!buffer) buffer = std::make_shared(); return buffer; } void SyncBufferFromFrame() { EnsureBuffer(); buffer->SetDmaFd(dma_fd); buffer->SetOwner(data_owner); const int count = std::min(plane_count, static_cast(planes.size())); std::vector plane_list; plane_list.reserve(static_cast(std::max(0, count))); for (int i = 0; i < count; ++i) { const FramePlane& p = planes[i]; plane_list.push_back({p.data, p.stride, p.size, p.offset}); } buffer->SetPlanes(std::move(plane_list)); } }; } // namespace rk3588