pipeline: rpi: Add RequiresMmap flag to RPi::Stream
Add a new RequiresMmap flag to the RPi::Stream class indicating that buffers handled by the stream must be mmapped after allocation and cached internally. Add a new member function getBuffer(id) which can be used to obtain the mapped buffers for a given buffer id. Add a new member function acquireBuffer() which can be used to obtain any mapped buffer that has not already been acquired by the caller. As a drive-by, add the <algorithm> header to rpi_stream.cpp as it is needed for the std::find_if() function. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
committed by
Kieran Bingham
parent
c258302863
commit
f4839fb3a3
@@ -888,7 +888,7 @@ void PipelineHandlerBase::mapBuffers(Camera *camera, const BufferMap &buffers, u
|
||||
*/
|
||||
for (auto const &it : buffers) {
|
||||
bufferIds.push_back(IPABuffer(mask | it.first,
|
||||
it.second->planes()));
|
||||
it.second.buffer->planes()));
|
||||
data->bufferIds_.insert(mask | it.first);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
*/
|
||||
#include "rpi_stream.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <libcamera/base/log.h>
|
||||
|
||||
/* Maximum number of buffer slots to allocate in the V4L2 device driver. */
|
||||
@@ -17,8 +21,13 @@ LOG_DEFINE_CATEGORY(RPISTREAM)
|
||||
|
||||
namespace RPi {
|
||||
|
||||
const BufferObject Stream::errorBufferObject{ nullptr, false };
|
||||
|
||||
void Stream::setFlags(StreamFlags flags)
|
||||
{
|
||||
/* We don't want dynamic mmapping. */
|
||||
ASSERT(!(flags & StreamFlag::RequiresMmap));
|
||||
|
||||
flags_ |= flags;
|
||||
|
||||
/* Import streams cannot be external. */
|
||||
@@ -27,6 +36,9 @@ void Stream::setFlags(StreamFlags flags)
|
||||
|
||||
void Stream::clearFlags(StreamFlags flags)
|
||||
{
|
||||
/* We don't want dynamic mmapping. */
|
||||
ASSERT(!(flags & StreamFlag::RequiresMmap));
|
||||
|
||||
flags_ &= ~flags;
|
||||
}
|
||||
|
||||
@@ -56,7 +68,7 @@ void Stream::resetBuffers()
|
||||
void Stream::setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers)
|
||||
{
|
||||
for (auto const &buffer : *buffers)
|
||||
bufferMap_.emplace(++id_, buffer.get());
|
||||
bufferEmplace(++id_, buffer.get());
|
||||
}
|
||||
|
||||
const BufferMap &Stream::getBuffers() const
|
||||
@@ -71,7 +83,7 @@ unsigned int Stream::getBufferId(FrameBuffer *buffer) const
|
||||
|
||||
/* Find the buffer in the map, and return the buffer id. */
|
||||
auto it = std::find_if(bufferMap_.begin(), bufferMap_.end(),
|
||||
[&buffer](auto const &p) { return p.second == buffer; });
|
||||
[&buffer](auto const &p) { return p.second.buffer == buffer; });
|
||||
|
||||
if (it == bufferMap_.end())
|
||||
return 0;
|
||||
@@ -81,7 +93,7 @@ unsigned int Stream::getBufferId(FrameBuffer *buffer) const
|
||||
|
||||
void Stream::setExportedBuffer(FrameBuffer *buffer)
|
||||
{
|
||||
bufferMap_.emplace(++id_, buffer);
|
||||
bufferEmplace(++id_, buffer);
|
||||
}
|
||||
|
||||
int Stream::prepareBuffers(unsigned int count)
|
||||
@@ -180,6 +192,27 @@ void Stream::returnBuffer(FrameBuffer *buffer)
|
||||
}
|
||||
}
|
||||
|
||||
const BufferObject &Stream::getBuffer(unsigned int id)
|
||||
{
|
||||
auto const &it = bufferMap_.find(id);
|
||||
if (it == bufferMap_.end())
|
||||
return errorBufferObject;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const BufferObject &Stream::acquireBuffer()
|
||||
{
|
||||
/* No id provided, so pick up the next available buffer if possible. */
|
||||
if (availableBuffers_.empty())
|
||||
return errorBufferObject;
|
||||
|
||||
unsigned int id = getBufferId(availableBuffers_.front());
|
||||
availableBuffers_.pop();
|
||||
|
||||
return getBuffer(id);
|
||||
}
|
||||
|
||||
int Stream::queueAllBuffers()
|
||||
{
|
||||
int ret;
|
||||
@@ -204,6 +237,16 @@ void Stream::releaseBuffers()
|
||||
clearBuffers();
|
||||
}
|
||||
|
||||
void Stream::bufferEmplace(unsigned int id, FrameBuffer *buffer)
|
||||
{
|
||||
if (flags_ & StreamFlag::RequiresMmap)
|
||||
bufferMap_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
|
||||
std::forward_as_tuple(buffer, true));
|
||||
else
|
||||
bufferMap_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
|
||||
std::forward_as_tuple(buffer, false));
|
||||
}
|
||||
|
||||
void Stream::clearBuffers()
|
||||
{
|
||||
availableBuffers_ = std::queue<FrameBuffer *>{};
|
||||
|
||||
@@ -7,22 +7,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <libcamera/base/flags.h>
|
||||
|
||||
#include <libcamera/stream.h>
|
||||
|
||||
#include "libcamera/internal/mapped_framebuffer.h"
|
||||
#include "libcamera/internal/v4l2_videodevice.h"
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
namespace RPi {
|
||||
|
||||
using BufferMap = std::unordered_map<unsigned int, FrameBuffer *>;
|
||||
|
||||
enum BufferMask {
|
||||
MaskID = 0x00ffff,
|
||||
MaskStats = 0x010000,
|
||||
@@ -30,6 +31,21 @@ enum BufferMask {
|
||||
MaskBayerData = 0x040000,
|
||||
};
|
||||
|
||||
struct BufferObject {
|
||||
BufferObject(FrameBuffer *b, bool requiresMmap)
|
||||
: buffer(b), mapped(std::nullopt)
|
||||
{
|
||||
if (requiresMmap)
|
||||
mapped = std::make_optional<MappedFrameBuffer>
|
||||
(b, MappedFrameBuffer::MapFlag::ReadWrite);
|
||||
}
|
||||
|
||||
FrameBuffer *buffer;
|
||||
std::optional<MappedFrameBuffer> mapped;
|
||||
};
|
||||
|
||||
using BufferMap = std::unordered_map<unsigned int, BufferObject>;
|
||||
|
||||
/*
|
||||
* Device stream abstraction for either an internal or external stream.
|
||||
* Used for both Unicam and the ISP.
|
||||
@@ -49,6 +65,11 @@ public:
|
||||
* buffers might be provided by (and returned to) the application.
|
||||
*/
|
||||
External = (1 << 1),
|
||||
/*
|
||||
* Indicates that the stream buffers need to be mmaped and returned
|
||||
* to the pipeline handler when requested.
|
||||
*/
|
||||
RequiresMmap = (1 << 2),
|
||||
};
|
||||
|
||||
using StreamFlags = Flags<StreamFlag>;
|
||||
@@ -82,10 +103,17 @@ public:
|
||||
int queueBuffer(FrameBuffer *buffer);
|
||||
void returnBuffer(FrameBuffer *buffer);
|
||||
|
||||
const BufferObject &getBuffer(unsigned int id);
|
||||
const BufferObject &acquireBuffer();
|
||||
|
||||
int queueAllBuffers();
|
||||
void releaseBuffers();
|
||||
|
||||
/* For error handling. */
|
||||
static const BufferObject errorBufferObject;
|
||||
|
||||
private:
|
||||
void bufferEmplace(unsigned int id, FrameBuffer *buffer);
|
||||
void clearBuffers();
|
||||
int queueToDevice(FrameBuffer *buffer);
|
||||
|
||||
|
||||
@@ -825,7 +825,7 @@ void Vc4CameraData::processStatsComplete(const ipa::RPi::BufferIds &buffers)
|
||||
if (!isRunning())
|
||||
return;
|
||||
|
||||
FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(buffers.stats & RPi::MaskID);
|
||||
FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(buffers.stats & RPi::MaskID).buffer;
|
||||
|
||||
handleStreamBuffer(buffer, &isp_[Isp::Stats]);
|
||||
|
||||
@@ -842,7 +842,7 @@ void Vc4CameraData::prepareIspComplete(const ipa::RPi::BufferIds &buffers)
|
||||
if (!isRunning())
|
||||
return;
|
||||
|
||||
buffer = unicam_[Unicam::Image].getBuffers().at(bayer & RPi::MaskID);
|
||||
buffer = unicam_[Unicam::Image].getBuffers().at(bayer & RPi::MaskID).buffer;
|
||||
LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << (bayer & RPi::MaskID)
|
||||
<< ", timestamp: " << buffer->metadata().timestamp;
|
||||
|
||||
@@ -850,7 +850,7 @@ void Vc4CameraData::prepareIspComplete(const ipa::RPi::BufferIds &buffers)
|
||||
ispOutputCount_ = 0;
|
||||
|
||||
if (sensorMetadata_ && embeddedId) {
|
||||
buffer = unicam_[Unicam::Embedded].getBuffers().at(embeddedId & RPi::MaskID);
|
||||
buffer = unicam_[Unicam::Embedded].getBuffers().at(embeddedId & RPi::MaskID).buffer;
|
||||
handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user