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:
Naushir Patuck 2020-09-18 10:42:23 +01:00 committed by Niklas Söderlund
parent 6bca768a0b
commit 8404d02d75
3 changed files with 33 additions and 25 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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)";
}
} }
} }