diff --git a/plugins/preprocess/preprocess_node.cpp b/plugins/preprocess/preprocess_node.cpp index 0488ddd..19cea3f 100644 --- a/plugins/preprocess/preprocess_node.cpp +++ b/plugins/preprocess/preprocess_node.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,21 @@ int ToRgaFormat(PixelFormat fmt) { default: return RK_FORMAT_UNKNOWN; } } + +std::mutex& GlobalRgaMutex() { + static std::mutex* mu = new std::mutex(); + return *mu; +} + +void EnsureRgaInitializedOnce() { + static std::once_flag once; + std::call_once(once, []() { + const IM_STATUS st = imcheckHeader(); + if (st != IM_STATUS_NOERROR && st != IM_STATUS_SUCCESS) { + std::cerr << "[preprocess] imcheckHeader failed: " << imStrError(st) << "\n"; + } + }); +} #endif PixelFormat ParseFormat(const std::string& s) { @@ -285,6 +301,8 @@ private: #if defined(RK3588_ENABLE_RGA) bool ProcessRga(FramePtr frame) { + EnsureRgaInitializedOnce(); + PixelFormat out_fmt = (dst_fmt_ != PixelFormat::UNKNOWN) ? dst_fmt_ : frame->format; int out_w = dst_w_; int out_h = dst_h_; @@ -374,10 +392,8 @@ private: rga_buffer_t dst_buf{}; DmaBufferPtr src_dma_buf; // Keep alive if we allocate - if (frame->dma_fd >= 0) { - src_buf = wrapbuffer_fd_t(frame->dma_fd, frame->width, frame->height, - src_wstride, src_hstride, src_fmt_rga); - } else if (frame->data) { + // Allocate/copy outside the global RGA lock; librga calls are protected below. + if (frame->data && frame->dma_fd < 0) { // Source doesn't have DMA fd, copy to DMA buffer first to avoid >4GB address issue size_t src_size = CalcImageSizeStrided(src_wstride, src_hstride, frame->format); src_dma_buf = DmaAlloc(src_size); @@ -393,6 +409,15 @@ private: return false; } DmaSyncEndFd(src_dma_buf->fd); + } + + // Serialize librga/im2d usage; multiple pipelines call RGA concurrently. + std::lock_guard lock(GlobalRgaMutex()); + + if (frame->dma_fd >= 0) { + src_buf = wrapbuffer_fd_t(frame->dma_fd, frame->width, frame->height, + src_wstride, src_hstride, src_fmt_rga); + } else if (src_dma_buf && src_dma_buf->valid()) { src_buf = wrapbuffer_fd_t(src_dma_buf->fd, frame->width, frame->height, src_wstride, src_hstride, src_fmt_rga); } else { @@ -403,6 +428,17 @@ private: dst_buf = wrapbuffer_fd_t(dma_buf->fd, out_w, out_h, dst_wstride, dst_hstride, dst_fmt_rga); + auto Check = [&](const rga_buffer_t& s, const rga_buffer_t& d) -> bool { + const im_rect sr{0, 0, s.width, s.height}; + const im_rect dr{0, 0, d.width, d.height}; + const IM_STATUS chk = imcheck(s, d, sr, dr); + if (chk != IM_STATUS_NOERROR && chk != IM_STATUS_SUCCESS) { + std::cerr << "[preprocess] RGA imcheck failed: " << imStrError(chk) << "\n"; + return false; + } + return true; + }; + IM_STATUS status = IM_STATUS_SUCCESS; if (need_resize && need_cvt) { @@ -414,14 +450,23 @@ private: } rga_buffer_t tmp = wrapbuffer_fd_t(tmp_dma->fd, out_w, out_h, dst_wstride, dst_hstride, src_fmt_rga); - status = imresize(src_buf, tmp); + if (!Check(src_buf, tmp) || !Check(tmp, dst_buf)) { + return false; + } + status = imresize(src_buf, tmp, 0, 0, 0, 1, nullptr); if (status == IM_STATUS_SUCCESS) { - status = imcvtcolor(tmp, dst_buf, src_fmt_rga, dst_fmt_rga, IM_COLOR_SPACE_DEFAULT); + status = imcvtcolor(tmp, dst_buf, src_fmt_rga, dst_fmt_rga, IM_COLOR_SPACE_DEFAULT, 1, nullptr); } } else if (need_resize) { - status = imresize(src_buf, dst_buf); + if (!Check(src_buf, dst_buf)) { + return false; + } + status = imresize(src_buf, dst_buf, 0, 0, 0, 1, nullptr); } else if (need_cvt) { - status = imcvtcolor(src_buf, dst_buf, src_fmt_rga, dst_fmt_rga, IM_COLOR_SPACE_DEFAULT); + if (!Check(src_buf, dst_buf)) { + return false; + } + status = imcvtcolor(src_buf, dst_buf, src_fmt_rga, dst_fmt_rga, IM_COLOR_SPACE_DEFAULT, 1, nullptr); } if (status != IM_STATUS_SUCCESS) {