mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-16 00:45:07 +03:00
libcamera: pipeline: ipa: raspberrypi: Rework drop frame signalling
The IPA now signals up front how many frames it wants the pipeline handler to drop. This makes it easier to handle up-coming changes to the buffer handling for import/export buffers. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: David Plowman <david.plowman@raspberrypi.com> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
parent
6bca768a0b
commit
8404d02d75
3 changed files with 33 additions and 25 deletions
|
@ -14,6 +14,7 @@ enum RPiConfigParameters {
|
||||||
RPI_IPA_CONFIG_LS_TABLE = (1 << 0),
|
RPI_IPA_CONFIG_LS_TABLE = (1 << 0),
|
||||||
RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),
|
RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),
|
||||||
RPI_IPA_CONFIG_SENSOR = (1 << 2),
|
RPI_IPA_CONFIG_SENSOR = (1 << 2),
|
||||||
|
RPI_IPA_CONFIG_DROP_FRAMES = (1 << 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RPiOperations {
|
enum RPiOperations {
|
||||||
|
@ -21,7 +22,6 @@ enum RPiOperations {
|
||||||
RPI_IPA_ACTION_V4L2_SET_ISP,
|
RPI_IPA_ACTION_V4L2_SET_ISP,
|
||||||
RPI_IPA_ACTION_STATS_METADATA_COMPLETE,
|
RPI_IPA_ACTION_STATS_METADATA_COMPLETE,
|
||||||
RPI_IPA_ACTION_RUN_ISP,
|
RPI_IPA_ACTION_RUN_ISP,
|
||||||
RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME,
|
|
||||||
RPI_IPA_ACTION_EMBEDDED_COMPLETE,
|
RPI_IPA_ACTION_EMBEDDED_COMPLETE,
|
||||||
RPI_IPA_EVENT_SIGNAL_STAT_READY,
|
RPI_IPA_EVENT_SIGNAL_STAT_READY,
|
||||||
RPI_IPA_EVENT_SIGNAL_ISP_PREPARE,
|
RPI_IPA_EVENT_SIGNAL_ISP_PREPARE,
|
||||||
|
|
|
@ -65,8 +65,8 @@ class IPARPi : public IPAInterface
|
||||||
public:
|
public:
|
||||||
IPARPi()
|
IPARPi()
|
||||||
: lastMode_({}), controller_(), controllerInit_(false),
|
: lastMode_({}), controller_(), controllerInit_(false),
|
||||||
frame_count_(0), check_count_(0), hide_count_(0),
|
frame_count_(0), check_count_(0), mistrust_count_(0),
|
||||||
mistrust_count_(0), lsTable_(nullptr)
|
lsTable_(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +137,6 @@ private:
|
||||||
uint64_t frame_count_;
|
uint64_t frame_count_;
|
||||||
/* For checking the sequencing of Prepare/Process calls. */
|
/* For checking the sequencing of Prepare/Process calls. */
|
||||||
uint64_t check_count_;
|
uint64_t check_count_;
|
||||||
/* How many frames the pipeline handler should hide, or "drop". */
|
|
||||||
unsigned int hide_count_;
|
|
||||||
/* How many frames we should avoid running control algos on. */
|
/* How many frames we should avoid running control algos on. */
|
||||||
unsigned int mistrust_count_;
|
unsigned int mistrust_count_;
|
||||||
/* LS table allocation passed in from the pipeline handler. */
|
/* LS table allocation passed in from the pipeline handler. */
|
||||||
|
@ -242,14 +240,18 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
|
||||||
*/
|
*/
|
||||||
frame_count_ = 0;
|
frame_count_ = 0;
|
||||||
check_count_ = 0;
|
check_count_ = 0;
|
||||||
|
unsigned int drop_frame = 0;
|
||||||
if (controllerInit_) {
|
if (controllerInit_) {
|
||||||
hide_count_ = helper_->HideFramesModeSwitch();
|
drop_frame = helper_->HideFramesModeSwitch();
|
||||||
mistrust_count_ = helper_->MistrustFramesModeSwitch();
|
mistrust_count_ = helper_->MistrustFramesModeSwitch();
|
||||||
} else {
|
} else {
|
||||||
hide_count_ = helper_->HideFramesStartup();
|
drop_frame = helper_->HideFramesStartup();
|
||||||
mistrust_count_ = helper_->MistrustFramesStartup();
|
mistrust_count_ = helper_->MistrustFramesStartup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result->data.push_back(drop_frame);
|
||||||
|
result->operation |= RPI_IPA_CONFIG_DROP_FRAMES;
|
||||||
|
|
||||||
struct AgcStatus agcStatus;
|
struct AgcStatus agcStatus;
|
||||||
/* These zero values mean not program anything (unless overwritten). */
|
/* These zero values mean not program anything (unless overwritten). */
|
||||||
agcStatus.shutter_time = 0.0;
|
agcStatus.shutter_time = 0.0;
|
||||||
|
@ -366,13 +368,11 @@ void IPARPi::processEvent(const IPAOperationData &event)
|
||||||
* they are "unreliable".
|
* they are "unreliable".
|
||||||
*/
|
*/
|
||||||
prepareISP(embeddedbufferId);
|
prepareISP(embeddedbufferId);
|
||||||
|
frame_count_++;
|
||||||
|
|
||||||
/* Ready to push the input buffer into the ISP. */
|
/* Ready to push the input buffer into the ISP. */
|
||||||
IPAOperationData op;
|
IPAOperationData op;
|
||||||
if (++frame_count_ > hide_count_)
|
|
||||||
op.operation = RPI_IPA_ACTION_RUN_ISP;
|
op.operation = RPI_IPA_ACTION_RUN_ISP;
|
||||||
else
|
|
||||||
op.operation = RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME;
|
|
||||||
op.data = { bayerbufferId & RPiIpaMask::ID };
|
op.data = { bayerbufferId & RPiIpaMask::ID };
|
||||||
queueFrameAction.emit(0, op);
|
queueFrameAction.emit(0, op);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -132,7 +132,7 @@ class RPiCameraData : public CameraData
|
||||||
public:
|
public:
|
||||||
RPiCameraData(PipelineHandler *pipe)
|
RPiCameraData(PipelineHandler *pipe)
|
||||||
: CameraData(pipe), sensor_(nullptr), state_(State::Stopped),
|
: CameraData(pipe), sensor_(nullptr), state_(State::Stopped),
|
||||||
dropFrame_(false), ispOutputCount_(0)
|
dropFrameCount_(0), ispOutputCount_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,14 +180,15 @@ public:
|
||||||
std::queue<FrameBuffer *> embeddedQueue_;
|
std::queue<FrameBuffer *> embeddedQueue_;
|
||||||
std::deque<Request *> requestQueue_;
|
std::deque<Request *> requestQueue_;
|
||||||
|
|
||||||
|
unsigned int dropFrameCount_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkRequestCompleted();
|
void checkRequestCompleted();
|
||||||
void tryRunPipeline();
|
void tryRunPipeline();
|
||||||
void tryFlushQueues();
|
void tryFlushQueues();
|
||||||
FrameBuffer *updateQueue(std::queue<FrameBuffer *> &q, uint64_t timestamp, V4L2VideoDevice *dev);
|
FrameBuffer *updateQueue(std::queue<FrameBuffer *> &q, uint64_t timestamp, V4L2VideoDevice *dev);
|
||||||
|
|
||||||
bool dropFrame_;
|
unsigned int ispOutputCount_;
|
||||||
int ispOutputCount_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RPiCameraConfiguration : public CameraConfiguration
|
class RPiCameraConfiguration : public CameraConfiguration
|
||||||
|
@ -1007,6 +1008,7 @@ int RPiCameraData::configureIPA()
|
||||||
ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,
|
ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,
|
||||||
&result);
|
&result);
|
||||||
|
|
||||||
|
unsigned int resultIdx = 0;
|
||||||
if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {
|
if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {
|
||||||
/*
|
/*
|
||||||
* Setup our staggered control writer with the sensor default
|
* Setup our staggered control writer with the sensor default
|
||||||
|
@ -1014,9 +1016,9 @@ int RPiCameraData::configureIPA()
|
||||||
*/
|
*/
|
||||||
if (!staggeredCtrl_) {
|
if (!staggeredCtrl_) {
|
||||||
staggeredCtrl_.init(unicam_[Unicam::Image].dev(),
|
staggeredCtrl_.init(unicam_[Unicam::Image].dev(),
|
||||||
{ { V4L2_CID_ANALOGUE_GAIN, result.data[0] },
|
{ { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] },
|
||||||
{ V4L2_CID_EXPOSURE, result.data[1] } });
|
{ V4L2_CID_EXPOSURE, result.data[resultIdx++] } });
|
||||||
sensorMetadata_ = result.data[2];
|
sensorMetadata_ = result.data[resultIdx++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,6 +1028,11 @@ int RPiCameraData::configureIPA()
|
||||||
LOG(RPI, Error) << "V4L2 staggered set failed";
|
LOG(RPI, Error) << "V4L2 staggered set failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.operation & RPI_IPA_CONFIG_DROP_FRAMES) {
|
||||||
|
/* Configure the number of dropped frames required on startup. */
|
||||||
|
dropFrameCount_ = result.data[resultIdx++];
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,7 +1084,6 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME:
|
|
||||||
case RPI_IPA_ACTION_RUN_ISP: {
|
case RPI_IPA_ACTION_RUN_ISP: {
|
||||||
unsigned int bufferId = action.data[0];
|
unsigned int bufferId = action.data[0];
|
||||||
FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers()->at(bufferId).get();
|
FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers()->at(bufferId).get();
|
||||||
|
@ -1086,7 +1092,6 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,
|
||||||
<< ", timestamp: " << buffer->metadata().timestamp;
|
<< ", timestamp: " << buffer->metadata().timestamp;
|
||||||
|
|
||||||
isp_[Isp::Input].dev()->queueBuffer(buffer);
|
isp_[Isp::Input].dev()->queueBuffer(buffer);
|
||||||
dropFrame_ = (action.operation == RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME) ? true : false;
|
|
||||||
ispOutputCount_ = 0;
|
ispOutputCount_ = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1252,7 +1257,7 @@ void RPiCameraData::clearIncompleteRequests()
|
||||||
void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream)
|
void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream)
|
||||||
{
|
{
|
||||||
if (stream->isExternal()) {
|
if (stream->isExternal()) {
|
||||||
if (!dropFrame_) {
|
if (!dropFrameCount_) {
|
||||||
Request *request = buffer->request();
|
Request *request = buffer->request();
|
||||||
pipe_->completeBuffer(camera_, request, buffer);
|
pipe_->completeBuffer(camera_, request, buffer);
|
||||||
}
|
}
|
||||||
|
@ -1264,7 +1269,7 @@ void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream
|
||||||
* simply memcpy to the Request buffer and requeue back to the
|
* simply memcpy to the Request buffer and requeue back to the
|
||||||
* device.
|
* device.
|
||||||
*/
|
*/
|
||||||
if (stream == &unicam_[Unicam::Image] && !dropFrame_) {
|
if (stream == &unicam_[Unicam::Image] && !dropFrameCount_) {
|
||||||
const Stream *rawStream = static_cast<const Stream *>(&isp_[Isp::Input]);
|
const Stream *rawStream = static_cast<const Stream *>(&isp_[Isp::Input]);
|
||||||
Request *request = requestQueue_.front();
|
Request *request = requestQueue_.front();
|
||||||
FrameBuffer *raw = request->findBuffer(const_cast<Stream *>(rawStream));
|
FrameBuffer *raw = request->findBuffer(const_cast<Stream *>(rawStream));
|
||||||
|
@ -1309,7 +1314,7 @@ void RPiCameraData::checkRequestCompleted()
|
||||||
* If we are dropping this frame, do not touch the request, simply
|
* If we are dropping this frame, do not touch the request, simply
|
||||||
* change the state to IDLE when ready.
|
* change the state to IDLE when ready.
|
||||||
*/
|
*/
|
||||||
if (!dropFrame_) {
|
if (!dropFrameCount_) {
|
||||||
Request *request = requestQueue_.front();
|
Request *request = requestQueue_.front();
|
||||||
if (request->hasPendingBuffers())
|
if (request->hasPendingBuffers())
|
||||||
return;
|
return;
|
||||||
|
@ -1328,10 +1333,13 @@ void RPiCameraData::checkRequestCompleted()
|
||||||
* frame.
|
* frame.
|
||||||
*/
|
*/
|
||||||
if (state_ == State::IpaComplete &&
|
if (state_ == State::IpaComplete &&
|
||||||
((ispOutputCount_ == 3 && dropFrame_) || requestCompleted)) {
|
((ispOutputCount_ == 3 && dropFrameCount_) || requestCompleted)) {
|
||||||
state_ = State::Idle;
|
state_ = State::Idle;
|
||||||
if (dropFrame_)
|
if (dropFrameCount_) {
|
||||||
LOG(RPI, Info) << "Dropping frame at the request of the IPA";
|
dropFrameCount_--;
|
||||||
|
LOG(RPI, Info) << "Dropping frame at the request of the IPA ("
|
||||||
|
<< dropFrameCount_ << " left)";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue