18
18
#include < sys/ioctl.h>
19
19
#include < sys/stat.h>
20
20
21
+ #include < linux/dma-buf.h>
21
22
#include < linux/videodev2.h>
22
23
24
+ #include < libcamera/base/shared_fd.h>
25
+
23
26
unsigned int LibcameraApp::verbosity = 2 ;
24
27
25
28
// If we definitely appear to be running the old camera stack, complain and give up.
@@ -492,9 +495,6 @@ void LibcameraApp::Teardown()
492
495
}
493
496
mapped_buffers_.clear ();
494
497
495
- delete allocator_;
496
- allocator_ = nullptr ;
497
-
498
498
configuration_.reset ();
499
499
500
500
frame_buffers_.clear ();
@@ -717,6 +717,18 @@ void LibcameraApp::queueRequest(CompletedRequest *completed_request)
717
717
718
718
for (auto const &p : buffers)
719
719
{
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
+
720
732
if (request->addBuffer (p.first , p.second ) < 0 )
721
733
throw std::runtime_error (" failed to add buffer to request in QueueRequest" );
722
734
}
@@ -847,33 +859,31 @@ void LibcameraApp::setupCapture()
847
859
848
860
// Next allocate all the buffers we need, mmap them and store them on a free list.
849
861
850
- allocator_ = new FrameBufferAllocator (camera_);
851
862
for (StreamConfiguration &config : *configuration_)
852
863
{
853
864
Stream *stream = config.stream ();
865
+ std::vector<std::unique_ptr<FrameBuffer>> fb;
854
866
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++)
859
868
{
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 ));
876
884
}
885
+
886
+ frame_buffers_[stream] = std::move (fb);
877
887
}
878
888
LOG (2 , " Buffers allocated and mapped" );
879
889
@@ -884,7 +894,15 @@ void LibcameraApp::setupCapture()
884
894
885
895
void LibcameraApp::makeRequests ()
886
896
{
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
+
888
906
while (true )
889
907
{
890
908
for (StreamConfiguration &config : *configuration_)
@@ -925,6 +943,21 @@ void LibcameraApp::requestComplete(Request *request)
925
943
return ;
926
944
}
927
945
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
+
928
961
CompletedRequest *r = new CompletedRequest (sequence_++, request);
929
962
CompletedRequestPtr payload (r, [this ](CompletedRequest *cr) { this ->queueRequest (cr); });
930
963
{
0 commit comments