diff --git a/plugins/preprocess/preprocess_node.cpp b/plugins/preprocess/preprocess_node.cpp index 047f0f3..7001761 100644 --- a/plugins/preprocess/preprocess_node.cpp +++ b/plugins/preprocess/preprocess_node.cpp @@ -393,33 +393,59 @@ private: DmaBufferPtr src_dma_buf; // Keep alive if we allocate // 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); + // Important: some RGA drivers cannot map DMABUF whose physical address is >4GB. + // MPP decode outputs often come as dma_fd; to avoid kernel-side mapping failures + // (and downstream heap corruption), prefer copying into our own <4GB dma_heap buffer + // when CPU mapping is available. + const bool can_cpu_read_src = (frame->data != nullptr && frame->data_size > 0); + const bool should_copy_src_for_rga = (frame->dma_fd >= 0 && can_cpu_read_src); + + if (should_copy_src_for_rga || (frame->dma_fd < 0 && frame->data)) { + // Use tight/aligned strides for the copied source buffer. + const int copy_wstride = Align16(frame->width); + const int copy_hstride = Align16(frame->height); + const size_t src_size = CalcImageSizeStrided(copy_wstride, copy_hstride, frame->format); src_dma_buf = DmaAlloc(src_size); if (!src_dma_buf || !src_dma_buf->valid()) { std::cerr << "[preprocess] DMA alloc for src failed\n"; return false; } + + // If source is a DMA-BUF, sync it before CPU reads. + if (frame->dma_fd >= 0) { + DmaSyncStartFd(frame->dma_fd); + } + // CPU writes to a DMA-BUF must be flushed before RGA reads it. DmaSyncStartFd(src_dma_buf->fd); - if (!CopyToStridedBuffer(*frame, src_dma_buf->data(), src_dma_buf->size, src_wstride, src_hstride)) { + if (!CopyToStridedBuffer(*frame, src_dma_buf->data(), src_dma_buf->size, copy_wstride, copy_hstride)) { DmaSyncEndFd(src_dma_buf->fd); + if (frame->dma_fd >= 0) { + DmaSyncEndFd(frame->dma_fd); + } std::cerr << "[preprocess] copy src to DMA failed\n"; return false; } DmaSyncEndFd(src_dma_buf->fd); + + if (frame->dma_fd >= 0) { + DmaSyncEndFd(frame->dma_fd); + } + + // Update strides used for RGA to match the copied buffer. + src_wstride = copy_wstride; + src_hstride = copy_hstride; } // 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()) { + 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 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 { return false; } diff --git a/src/utils/dma_alloc.cpp b/src/utils/dma_alloc.cpp index ba1e908..9aeeab2 100644 --- a/src/utils/dma_alloc.cpp +++ b/src/utils/dma_alloc.cpp @@ -169,15 +169,16 @@ DmaBufferPtr DmaAlloc(size_t alloc_size) { // - Some RGA drivers cannot map buffers whose physical address is >4GB; prefer DMA32 heaps. // - CMA heaps are also <4GB friendly but can be small/fragmented under multi-stream load. const char* heap_paths[] = { - // Prefer CMA first when available. + // Prefer DMA32 heaps to keep allocations under 4GB. + // This avoids RGA drivers that cannot map >4GB physical addresses. + "/dev/dma_heap/system-dma32", + "/dev/dma_heap/system-uncached-dma32", + + // CMA is also <4GB friendly, but can be small/fragmented under multi-stream load. "/dev/dma_heap/cma", "/dev/dma_heap/cma-uncached", "/dev/dma_heap/linux,cma", - // Then prefer DMA32 heaps to keep allocations under 4GB. - "/dev/dma_heap/system-dma32", - "/dev/dma_heap/system-uncached-dma32", - // Generic system heaps (may allocate >4GB on high-mem systems). "/dev/dma_heap/system-uncached", "/dev/dma_heap/system",