{"record":{"id":"c5b2ff9d30ea4ac5","repo":"deepinsight/insightface","slug":"rga-buffer-allocation-failed","errorCode":null,"errorMessage":"RGA buffer allocation failed","messagePattern":"RGA buffer allocation failed","errorType":"exception","errorClass":"std::runtime_error","httpStatus":null,"severity":"error","filePath":"cpp-package/inspireface/cpp/inspireface/image_process/nexus_processor/image_processor_rga.h","lineNumber":191,"sourceCode":"                last_dst_key_ = key;\n            }\n            return it->second;\n        }\n\n        if (buffer_cache_.size() >= 3) {  // Keep max 3 buffers in cache\n            for (auto it = buffer_cache_.begin(); it != buffer_cache_.end();) {\n                if (!(it->first == last_src_key_) && !(it->first == last_dst_key_)) {\n                    it = buffer_cache_.erase(it);\n                } else {\n                    ++it;\n                }\n            }\n        }\n\n        auto& buffer = buffer_cache_[key];\n        if (!buffer.Allocate(key.width, key.height, key.channels)) {\n            INSPIRECV_LOG(ERROR) << \"Failed to allocate RGA buffer\";\n            throw std::runtime_error(\"RGA buffer allocation failed\");\n        }\n\n        if (is_src) {\n            last_src_key_ = key;\n        } else {\n            last_dst_key_ = key;\n        }\n\n        return buffer;\n    }\n\nprivate:\n    std::unordered_map<BufferKey, RGABuffer, BufferKeyHash> buffer_cache_;\n    BufferKey last_src_key_{0, 0, 0};\n    BufferKey last_dst_key_{0, 0, 0};\n    int32_t aligned_width_{0};\n};\n","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/deepinsight/insightface/blob/7fadd420c2351d0ffa8cac403421c1a3ed733365/cpp-package/inspireface/cpp/inspireface/image_process/nexus_processor/image_processor_rga.h#L173-L209","documentation":"In the RGA image processor's buffer cache, when a GetBuffer cache miss occurs a new RGA buffer is allocated via buffer.Allocate(width, height, channels); if the underlying allocation (RGA/malloc/DMA memory) fails, the code throws std::runtime_error(\"RGA buffer allocation failed\"). This aborts the copy/conversion step of the RGA pipeline. It almost always indicates resource exhaustion or dimensions the allocator rejects, not a logic bug in caller code.","triggerScenarios":"Requesting a conversion/copy with unusually large width×height×channels so the RGA buffer allocation exceeds available memory; many concurrent streams creating distinct cache keys and fragmenting/exhausting the cache; running on a device where the RGA device (/dev/rga) or its DMA heap is unavailable or out of memory; memory pressure on embedded boards after long uptime or alongside other camera/AI processes.","commonSituations":"Feeding 4K/high-resolution frames on RK3588/RK3566 boards where CMA or DMA-BUF heap is exhausted; multiple cameras or pipeline instances each allocating new buffer keys because width/height/format differ per frame; OOM conditions on Android/Embedded Linux when InspireFace runs next to other heavy media processes; a first-run failure because the RGA driver isn't loaded.","solutions":["Free memory / reduce concurrent load: close other camera or inference processes and retry to see if allocation succeeds.","Reduce input resolution or reuse a consistent frame size so the buffer cache hits (buffer_cache_[key]) instead of allocating new buffers every frame.","Check RGA availability and memory: verify /dev/rga exists, the rga driver is loaded, and inspect CMA/DMA heap usage (dmesg | grep -i rga, /proc/meminfo).","If the leak is repeated cache growth, bound or clear the buffer cache between sessions and report upstream if buffers are never released."],"exampleFix":"// before\nauto& proc = ...; // ImageProcessorRGA\nproc->CopyImage(img, dst); // may throw std::runtime_error: RGA buffer allocation failed\n// after\ntry {\n    proc->CopyImage(img, dst);\n} catch (const std::runtime_error& e) {\n    LOG(WARNING) << \"RGA allocation failed: \" << e.what()\n                 << \" — retrying with downscaled frame\";\n    auto small = img.Resize(img.Width()/2, img.Height()/2);\n    proc->CopyImage(small, dst);\n}","handlingStrategy":"try-catch","validationCode":"size_t need = (size_t)width * height * channels;\nif (need > kMaxRgaBufferBytes) { /* downscale or reject frame before processing */ }","typeGuard":null,"tryCatchPattern":"try {\n    processor->CopyImage(src, dst);\n} catch (const std::runtime_error& e) {\n    if (std::string(e.what()).find(\"RGA buffer\") != std::string::npos) {\n        // free memory / downscale input and retry once\n    } else throw;\n}","preventionTips":["Normalize input frames to one resolution so buffer_cache_ keys hit instead of allocating new buffers.","Keep only one active RGA processing pipeline per process where possible.","Watch CMA/DMA heap usage on Rockchip boards during load testing."],"tags":["rga","rockchip","memory-allocation","buffer-cache","out-of-memory"],"backgroundTag":"graphics-buffer-allocation-failed","analyzedSha":"7fadd420c2351d0ffa8cac403421c1a3ed733365","analyzedAt":"2026-08-28T15:44:01.850Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}