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+
2326unsigned 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
885895void 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 {
0 commit comments