Skip to content

Commit 1a2086e

Browse files
committed
core: Allocate buffers through the dma heap
Switch to using the dma heap allocator for all libcamera framebuffers that will be used in requests. Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
1 parent 1133868 commit 1a2086e

File tree

2 files changed

+61
-29
lines changed

2 files changed

+61
-29
lines changed

core/libcamera_app.cpp

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
#include <sys/ioctl.h>
1919
#include <sys/stat.h>
2020

21+
#include <linux/dma-buf.h>
2122
#include <linux/videodev2.h>
2223

24+
#include <libcamera/base/shared_fd.h>
25+
2326
unsigned int LibcameraApp::verbosity = 2;
2427

2528
// If we definitely appear to be running the old camera stack, complain and give up.
@@ -492,9 +495,6 @@ void LibcameraApp::Teardown()
492495
}
493496
mapped_buffers_.clear();
494497

495-
delete allocator_;
496-
allocator_ = nullptr;
497-
498498
configuration_.reset();
499499

500500
frame_buffers_.clear();
@@ -717,6 +717,18 @@ void LibcameraApp::queueRequest(CompletedRequest *completed_request)
717717

718718
for (auto const &p : buffers)
719719
{
720+
struct dma_buf_sync dma_sync {};
721+
dma_sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
722+
auto &list = frame_buffers_[const_cast<Stream *>(p.first)];
723+
auto it = std::find_if(list.begin(), list.end(),
724+
[&p] (auto &b) { return b.get() == p.second;} );
725+
if (it == list.end())
726+
throw std::runtime_error("failed to identify request buffer");
727+
728+
int ret = ::ioctl(it->get()->planes()[0].fd.get(), DMA_BUF_IOCTL_SYNC, &dma_sync);
729+
if (ret)
730+
throw std::runtime_error("failed to sync dma buf on queue request");
731+
720732
if (request->addBuffer(p.first, p.second) < 0)
721733
throw std::runtime_error("failed to add buffer to request in QueueRequest");
722734
}
@@ -847,33 +859,31 @@ void LibcameraApp::setupCapture()
847859

848860
// Next allocate all the buffers we need, mmap them and store them on a free list.
849861

850-
allocator_ = new FrameBufferAllocator(camera_);
851862
for (StreamConfiguration &config : *configuration_)
852863
{
853864
Stream *stream = config.stream();
865+
std::vector<std::unique_ptr<FrameBuffer>> fb;
854866

855-
if (allocator_->allocate(stream) < 0)
856-
throw std::runtime_error("failed to allocate capture buffers");
857-
858-
for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream))
867+
for (unsigned int i = 0; i < config.bufferCount; i++)
859868
{
860-
// "Single plane" buffers appear as multi-plane here, but we can spot them because then
861-
// planes all share the same fd. We accumulate them so as to mmap the buffer only once.
862-
size_t buffer_size = 0;
863-
for (unsigned i = 0; i < buffer->planes().size(); i++)
864-
{
865-
const FrameBuffer::Plane &plane = buffer->planes()[i];
866-
buffer_size += plane.length;
867-
if (i == buffer->planes().size() - 1 || plane.fd.get() != buffer->planes()[i + 1].fd.get())
868-
{
869-
void *memory = mmap(NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, plane.fd.get(), 0);
870-
mapped_buffers_[buffer.get()].push_back(
871-
libcamera::Span<uint8_t>(static_cast<uint8_t *>(memory), buffer_size));
872-
buffer_size = 0;
873-
}
874-
}
875-
frame_buffers_[stream].push(buffer.get());
869+
std::string name("libcamera-apps" + std::to_string(i));
870+
libcamera::UniqueFD fd = dma_heap_.alloc(name.c_str(), config.frameSize);
871+
872+
if (!fd.isValid())
873+
throw std::runtime_error("failed to allocate capture buffers for stream");
874+
875+
std::vector<FrameBuffer::Plane> plane(1);
876+
plane[0].fd = libcamera::SharedFD(std::move(fd));
877+
plane[0].offset = 0;
878+
plane[0].length = config.frameSize;
879+
880+
fb.push_back(std::make_unique<FrameBuffer>(plane));
881+
void *memory = mmap(NULL, config.frameSize, PROT_READ | PROT_WRITE, MAP_SHARED, plane[0].fd.get(), 0);
882+
mapped_buffers_[fb.back().get()].push_back(
883+
libcamera::Span<uint8_t>(static_cast<uint8_t *>(memory), config.frameSize));
876884
}
885+
886+
frame_buffers_[stream] = std::move(fb);
877887
}
878888
LOG(2, "Buffers allocated and mapped");
879889

@@ -884,7 +894,15 @@ void LibcameraApp::setupCapture()
884894

885895
void LibcameraApp::makeRequests()
886896
{
887-
auto free_buffers(frame_buffers_);
897+
std::map<Stream *, std::queue<FrameBuffer *>> free_buffers;
898+
899+
for (auto &kv : frame_buffers_)
900+
{
901+
free_buffers[kv.first] = {};
902+
for (auto &b : kv.second)
903+
free_buffers[kv.first].push(b.get());
904+
}
905+
888906
while (true)
889907
{
890908
for (StreamConfiguration &config : *configuration_)
@@ -925,6 +943,21 @@ void LibcameraApp::requestComplete(Request *request)
925943
return;
926944
}
927945

946+
struct dma_buf_sync dma_sync {};
947+
dma_sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
948+
for (auto const &buffer_map : request->buffers())
949+
{
950+
auto &list = frame_buffers_[const_cast<Stream *>(buffer_map.first)];
951+
auto it = std::find_if(list.begin(), list.end(),
952+
[&buffer_map] (auto &b) { return b.get() == buffer_map.second; } );
953+
if (it == list.end())
954+
throw std::runtime_error("failed to identify request buffer");
955+
956+
int ret = ::ioctl(it->get()->planes()[0].fd.get(), DMA_BUF_IOCTL_SYNC, &dma_sync);
957+
if (ret)
958+
throw std::runtime_error("failed to sync dma buf on returned request");
959+
}
960+
928961
CompletedRequest *r = new CompletedRequest(sequence_++, request);
929962
CompletedRequestPtr payload(r, [this](CompletedRequest *cr) { this->queueRequest(cr); });
930963
{

core/libcamera_app.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
#include <libcamera/control_ids.h>
2727
#include <libcamera/controls.h>
2828
#include <libcamera/formats.h>
29-
#include <libcamera/framebuffer_allocator.h>
3029
#include <libcamera/logging.h>
3130
#include <libcamera/property_ids.h>
3231

3332
#include "core/completed_request.hpp"
33+
#include "core/dma_heaps.hpp"
3434
#include "core/post_processor.hpp"
3535
#include "core/stream_info.hpp"
3636

@@ -51,7 +51,6 @@ class LibcameraApp
5151
using CameraManager = libcamera::CameraManager;
5252
using Camera = libcamera::Camera;
5353
using CameraConfiguration = libcamera::CameraConfiguration;
54-
using FrameBufferAllocator = libcamera::FrameBufferAllocator;
5554
using StreamRole = libcamera::StreamRole;
5655
using StreamRoles = std::vector<libcamera::StreamRole>;
5756
using PixelFormat = libcamera::PixelFormat;
@@ -237,8 +236,8 @@ class LibcameraApp
237236
std::unique_ptr<CameraConfiguration> configuration_;
238237
std::map<FrameBuffer *, std::vector<libcamera::Span<uint8_t>>> mapped_buffers_;
239238
std::map<std::string, Stream *> streams_;
240-
FrameBufferAllocator *allocator_ = nullptr;
241-
std::map<Stream *, std::queue<FrameBuffer *>> frame_buffers_;
239+
DmaHeap dma_heap_;
240+
std::map<Stream *, std::vector<std::unique_ptr<FrameBuffer>>> frame_buffers_;
242241
std::vector<std::unique_ptr<Request>> requests_;
243242
std::mutex completed_requests_mutex_;
244243
std::set<CompletedRequest *> completed_requests_;

0 commit comments

Comments
 (0)