<div dir="ltr"><div>Thanks for the implementation.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 22, 2020 at 9:39 PM Paul Elder <<a href="mailto:paul.elder@ideasonboard.com">paul.elder@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Now that we can generate custom functions and data structures with mojo,<br>
switch the raspberrypi pipeline handler and IPA to use the custom data<br>
structures as defined in the mojom data definition file.<br>
<br>
Signed-off-by: Paul Elder <<a href="mailto:paul.elder@ideasonboard.com" target="_blank">paul.elder@ideasonboard.com</a>><br>
<br>
---<br>
Changes in v2:<br>
- rebased on "libcamera: pipeline: ipa: raspberrypi: Rework drop frame<br>
signalling"<br>
- use newly customized RPi IPA interface<br>
---<br>
include/libcamera/ipa/raspberrypi.h | 37 ++--<br>
src/ipa/raspberrypi/raspberrypi.cpp | 152 +++++++---------<br>
.../pipeline/raspberrypi/raspberrypi.cpp | 171 +++++++++---------<br>
3 files changed, 170 insertions(+), 190 deletions(-)<br>
<br>
diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h<br>
index 4e38d009..3357bf61 100644<br>
--- a/include/libcamera/ipa/raspberrypi.h<br>
+++ b/include/libcamera/ipa/raspberrypi.h<br>
@@ -24,22 +24,27 @@ enum RPiBufferMask {<br>
namespace libcamera {<br>
<br>
/* List of controls handled by the Raspberry Pi IPA */<br>
-static const ControlInfoMap RPiControls = {<br>
- { &controls::AeEnable, ControlInfo(false, true) },<br>
- { &controls::ExposureTime, ControlInfo(0, 999999) },<br>
- { &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },<br>
- { &controls::AeMeteringMode, ControlInfo(0, static_cast<int32_t>(controls::MeteringModeMax)) },<br>
- { &controls::AeConstraintMode, ControlInfo(0, static_cast<int32_t>(controls::ConstraintModeMax)) },<br>
- { &controls::AeExposureMode, ControlInfo(0, static_cast<int32_t>(controls::ExposureModeMax)) },<br>
- { &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },<br>
- { &controls::AwbEnable, ControlInfo(false, true) },<br>
- { &controls::ColourGains, ControlInfo(0.0f, 32.0f) },<br>
- { &controls::AwbMode, ControlInfo(0, static_cast<int32_t>(controls::AwbModeMax)) },<br>
- { &controls::Brightness, ControlInfo(-1.0f, 1.0f) },<br>
- { &controls::Contrast, ControlInfo(0.0f, 32.0f) },<br>
- { &controls::Saturation, ControlInfo(0.0f, 32.0f) },<br>
- { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },<br>
- { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },<br>
+static ControlInfoMap RPiControls;<br>
+<br>
+inline void initializeRPiControls()<br>
+{<br>
+ RPiControls = {<br>
+ { &controls::AeEnable, ControlInfo(false, true) },<br>
+ { &controls::ExposureTime, ControlInfo(0, 999999) },<br>
+ { &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },<br>
+ { &controls::AeMeteringMode, ControlInfo(0, static_cast<int32_t>(controls::MeteringModeMax)) },<br>
+ { &controls::AeConstraintMode, ControlInfo(0, static_cast<int32_t>(controls::ConstraintModeMax)) },<br>
+ { &controls::AeExposureMode, ControlInfo(0, static_cast<int32_t>(controls::ExposureModeMax)) },<br>
+ { &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },<br>
+ { &controls::AwbEnable, ControlInfo(false, true) },<br>
+ { &controls::ColourGains, ControlInfo(0.0f, 32.0f) },<br>
+ { &controls::AwbMode, ControlInfo(0, static_cast<int32_t>(controls::AwbModeMax)) },<br>
+ { &controls::Brightness, ControlInfo(-1.0f, 1.0f) },<br>
+ { &controls::Contrast, ControlInfo(0.0f, 32.0f) },<br>
+ { &controls::Saturation, ControlInfo(0.0f, 32.0f) },<br>
+ { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },<br>
+ { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },<br>
+ };<br>
};<br></blockquote><div>Just out of curiosity.</div><div>Since the RPiControls is not const anymore, and each translation unit has a copy, the content used in generated ipa_proxy_raspberrypi.cpp would be empty.</div><div>Is it an intended behavior?</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
} /* namespace libcamera */<br>
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp<br>
index 0555cc4e..805ced33 100644<br>
--- a/src/ipa/raspberrypi/raspberrypi.cpp<br>
+++ b/src/ipa/raspberrypi/raspberrypi.cpp<br>
@@ -19,6 +19,7 @@<br>
#include <libcamera/ipa/ipa_interface.h><br>
#include <libcamera/ipa/ipa_module_info.h><br>
#include <libcamera/ipa/raspberrypi.h><br>
+#include <libcamera/ipa/raspberrypi_generated.h><br>
#include <libcamera/request.h><br>
#include <libcamera/span.h><br>
<br>
@@ -60,7 +61,7 @@ namespace libcamera {<br>
<br>
LOG_DEFINE_CATEGORY(IPARPI)<br>
<br>
-class IPARPi : public IPAInterface<br>
+class IPARPi : public IPARPiInterface<br>
{<br>
public:<br>
IPARPi()<br>
@@ -68,6 +69,7 @@ public:<br>
frame_count_(0), check_count_(0), mistrust_count_(0),<br>
lsTable_(nullptr)<br>
{<br>
+ initializeRPiControls();<br>
}<br>
<br>
~IPARPi()<br>
@@ -82,12 +84,14 @@ public:<br>
<br>
void configure(const CameraSensorInfo &sensorInfo,<br>
const std::map<unsigned int, IPAStream> &streamConfig,<br>
- const std::map<unsigned int, const ControlInfoMap &> &entityControls,<br>
- const IPAOperationData &data,<br>
- IPAOperationData *response) override;<br>
+ const std::map<unsigned int, ControlInfoMap> &entityControls,<br>
+ const RPiConfigInput &data,<br>
+ RPiConfigOutput *response) override;<br>
void mapBuffers(const std::vector<IPABuffer> &buffers) override;<br>
void unmapBuffers(const std::vector<unsigned int> &ids) override;<br>
- void processEvent(const IPAOperationData &event) override;<br>
+ void signalStatReady(const uint32_t bufferId) override;<br>
+ void signalQueueRequest(const ControlList &controls) override;<br>
+ void signalIspPrepare(const RPiIspPreparePayload &data) override;<br>
<br>
private:<br>
void setMode(const CameraSensorInfo &sensorInfo);<br>
@@ -141,6 +145,11 @@ private:<br>
unsigned int mistrust_count_;<br>
/* LS table allocation passed in from the pipeline handler. */<br>
FileDescriptor lsTableHandle_;<br>
+ /*<br>
+ * LS table allocation passed in from the pipeline handler,<br>
+ * in the context of the pipeline handler.<br>
+ */<br>
+ int32_t lsTableHandlePH_;<br>
void *lsTable_;<br>
};<br>
<br>
@@ -190,15 +199,13 @@ void IPARPi::setMode(const CameraSensorInfo &sensorInfo)<br>
<br>
void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
[[maybe_unused]] const std::map<unsigned int, IPAStream> &streamConfig,<br>
- const std::map<unsigned int, const ControlInfoMap &> &entityControls,<br>
- const IPAOperationData &ipaConfig,<br>
- IPAOperationData *result)<br>
+ const std::map<unsigned int, ControlInfoMap> &entityControls,<br>
+ const RPiConfigInput &ipaConfig,<br>
+ RPiConfigOutput *result)<br>
{<br>
if (entityControls.empty())<br>
return;<br>
<br>
- result->operation = 0;<br>
-<br>
unicam_ctrls_ = entityControls.at(0);<br>
isp_ctrls_ = entityControls.at(1);<br>
/* Setup a metadata ControlList to output metadata. */<br>
@@ -220,11 +227,10 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
helper_->GetDelays(exposureDelay, gainDelay);<br>
sensorMetadata = helper_->SensorEmbeddedDataPresent();<br>
<br>
- result->data.push_back(gainDelay);<br>
- result->data.push_back(exposureDelay);<br>
- result->data.push_back(sensorMetadata);<br>
-<br>
- result->operation |= RPI_IPA_CONFIG_STAGGERED_WRITE;<br>
+ result->op_ |= RPI_IPA_CONFIG_STAGGERED_WRITE;<br>
+ result->staggeredWriteResult_.gainDelay_ = gainDelay;<br>
+ result->staggeredWriteResult_.exposureDelay_ = exposureDelay;<br>
+ result->staggeredWriteResult_.sensorMetadata_ = sensorMetadata;<br>
}<br>
<br>
/* Re-assemble camera mode using the sensor info. */<br>
@@ -240,18 +246,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
*/<br>
frame_count_ = 0;<br>
check_count_ = 0;<br>
- unsigned int drop_frame = 0;<br>
+ result->op_ |= RPI_IPA_CONFIG_DROP_FRAMES;<br>
if (controllerInit_) {<br>
- drop_frame = helper_->HideFramesModeSwitch();<br>
+ result->dropFrameCount_ = helper_->HideFramesModeSwitch();<br>
mistrust_count_ = helper_->MistrustFramesModeSwitch();<br>
} else {<br>
- drop_frame = helper_->HideFramesStartup();<br>
+ result->dropFrameCount_ = helper_->HideFramesStartup();<br>
mistrust_count_ = helper_->MistrustFramesStartup();<br>
}<br>
<br>
- result->data.push_back(drop_frame);<br>
- result->operation |= RPI_IPA_CONFIG_DROP_FRAMES;<br>
-<br>
struct AgcStatus agcStatus;<br>
/* These zero values mean not program anything (unless overwritten). */<br>
agcStatus.shutter_time = 0.0;<br>
@@ -276,15 +279,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) {<br>
ControlList ctrls(unicam_ctrls_);<br>
applyAGC(&agcStatus, ctrls);<br>
- result->controls.push_back(ctrls);<br>
<br>
- result->operation |= RPI_IPA_CONFIG_SENSOR;<br>
+ result->op_ |= RPI_IPA_CONFIG_SENSOR;<br>
+ result->controls_ = ctrls;<br>
}<br>
<br>
lastMode_ = mode_;<br>
<br>
/* Store the lens shading table pointer and handle if available. */<br>
- if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {<br>
+ if (ipaConfig.op_ & RPI_IPA_CONFIG_LS_TABLE) {<br>
/* Remove any previous table, if there was one. */<br>
if (lsTable_) {<br>
munmap(lsTable_, MAX_LS_GRID_SIZE);<br>
@@ -292,7 +295,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
}<br>
<br>
/* Map the LS table buffer into user space. */<br>
- lsTableHandle_ = FileDescriptor(ipaConfig.data[0]);<br>
+ lsTableHandle_ = FileDescriptor(ipaConfig.lsTableHandle_);<br>
+ lsTableHandlePH_ = ipaConfig.lsTableHandleStatic_;<br>
if (lsTableHandle_.isValid()) {<br>
lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,<br>
MAP_SHARED, lsTableHandle_.fd(), 0);<br>
@@ -337,56 +341,38 @@ void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids)<br>
}<br>
}<br>
<br>
-void IPARPi::processEvent(const IPAOperationData &event)<br>
+void IPARPi::signalStatReady(const uint32_t bufferId)<br>
{<br>
- switch (event.operation) {<br>
- case RPI_IPA_EVENT_SIGNAL_STAT_READY: {<br>
- unsigned int bufferId = event.data[0];<br>
-<br>
- if (++check_count_ != frame_count_) /* assert here? */<br>
- LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";<br>
- if (frame_count_ > mistrust_count_)<br>
- processStats(bufferId);<br>
-<br>
- reportMetadata();<br>
-<br>
- IPAOperationData op;<br>
- op.operation = RPI_IPA_ACTION_STATS_METADATA_COMPLETE;<br>
- op.data = { bufferId & RPiBufferMask::ID };<br>
- op.controls = { libcameraMetadata_ };<br>
- queueFrameAction.emit(0, op);<br>
- break;<br>
- }<br>
+ if (++check_count_ != frame_count_) /* assert here? */<br>
+ LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";<br>
+ if (frame_count_ > mistrust_count_)<br>
+ processStats(bufferId);<br>
<br>
- case RPI_IPA_EVENT_SIGNAL_ISP_PREPARE: {<br>
- unsigned int embeddedbufferId = event.data[0];<br>
- unsigned int bayerbufferId = event.data[1];<br>
+ reportMetadata();<br>
<br>
- /*<br>
- * At start-up, or after a mode-switch, we may want to<br>
- * avoid running the control algos for a few frames in case<br>
- * they are "unreliable".<br>
- */<br>
- prepareISP(embeddedbufferId);<br>
- frame_count_++;<br>
-<br>
- /* Ready to push the input buffer into the ISP. */<br>
- IPAOperationData op;<br>
- op.operation = RPI_IPA_ACTION_RUN_ISP;<br>
- op.data = { bayerbufferId & RPiBufferMask::ID };<br>
- queueFrameAction.emit(0, op);<br>
- break;<br>
- }<br>
+ statsMetadataComplete.emit(bufferId & RPiBufferMask::ID, libcameraMetadata_);<br>
+}<br>
<br>
- case RPI_IPA_EVENT_QUEUE_REQUEST: {<br>
- queueRequest(event.controls[0]);<br>
- break;<br>
- }<br>
+void IPARPi::signalQueueRequest(const ControlList &controls)<br>
+{<br>
+ queueRequest(controls);<br>
+}<br>
<br>
- default:<br>
- LOG(IPARPI, Error) << "Unknown event " << event.operation;<br>
- break;<br>
- }<br>
+void IPARPi::signalIspPrepare(const RPiIspPreparePayload &data)<br>
+{<br>
+ unsigned int embeddedbufferId = data.embeddedbufferId_;<br>
+ unsigned int bayerbufferId = data.bayerbufferId_;<br>
+<br>
+ /*<br>
+ * At start-up, or after a mode-switch, we may want to<br>
+ * avoid running the control algos for a few frames in case<br>
+ * they are "unreliable".<br>
+ */<br>
+ prepareISP(embeddedbufferId);<br>
+ frame_count_++;<br>
+<br>
+ /* Ready to push the input buffer into the ISP. */<br>
+ runIsp.emit(bayerbufferId & RPiBufferMask::ID);<br>
}<br>
<br>
void IPARPi::reportMetadata()<br>
@@ -489,6 +475,8 @@ void IPARPi::queueRequest(const ControlList &controls)<br>
/* Clear the return metadata buffer. */<br>
libcameraMetadata_.clear();<br>
<br>
+ LOG(IPARPI, Info) << "Request ctrl length: " << controls.size();<br>
+<br>
for (auto const &ctrl : controls) {<br>
LOG(IPARPI, Info) << "Request ctrl: "<br>
<< controls::<a href="http://controls.at" rel="noreferrer" target="_blank">controls.at</a>(ctrl.first)->name()<br>
@@ -698,10 +686,7 @@ void IPARPi::queueRequest(const ControlList &controls)<br>
<br>
void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)<br>
{<br>
- IPAOperationData op;<br>
- op.operation = RPI_IPA_ACTION_EMBEDDED_COMPLETE;<br>
- op.data = { bufferId & RPiBufferMask::ID };<br>
- queueFrameAction.emit(0, op);<br>
+ embeddedComplete.emit(bufferId & RPiBufferMask::ID);<br>
}<br>
<br>
void IPARPi::prepareISP(unsigned int bufferId)<br>
@@ -762,12 +747,8 @@ void IPARPi::prepareISP(unsigned int bufferId)<br>
if (dpcStatus)<br>
applyDPC(dpcStatus, ctrls);<br>
<br>
- if (!ctrls.empty()) {<br>
- IPAOperationData op;<br>
- op.operation = RPI_IPA_ACTION_V4L2_SET_ISP;<br>
- op.controls.push_back(ctrls);<br>
- queueFrameAction.emit(0, op);<br>
- }<br>
+ if (!ctrls.empty())<br>
+ setIsp.emit(ctrls);<br>
}<br>
}<br>
<br>
@@ -823,10 +804,7 @@ void IPARPi::processStats(unsigned int bufferId)<br>
ControlList ctrls(unicam_ctrls_);<br>
applyAGC(&agcStatus, ctrls);<br>
<br>
- IPAOperationData op;<br>
- op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;<br>
- op.controls.push_back(ctrls);<br>
- queueFrameAction.emit(0, op);<br>
+ setStaggered.emit(ctrls);<br>
}<br>
}<br>
<br>
@@ -1056,7 +1034,7 @@ void IPARPi::applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls)<br>
.grid_width = w,<br>
.grid_stride = w,<br>
.grid_height = h,<br>
- .dmabuf = lsTableHandle_.fd(),<br>
+ .dmabuf = lsTableHandlePH_,<br>
.ref_transform = 0,<br>
.corner_sampled = 1,<br>
.gain_format = GAIN_FORMAT_U4P10<br>
@@ -1136,9 +1114,9 @@ const struct IPAModuleInfo ipaModuleInfo = {<br>
"raspberrypi",<br>
};<br>
<br>
-struct ipa_context *ipaCreate()<br>
+IPAInterface *ipaCreate()<br>
{<br>
- return new IPAInterfaceWrapper(std::make_unique<IPARPi>());<br>
+ return new IPARPi();<br>
}<br>
<br>
}; /* extern "C" */<br>
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
index 50f07182..49e28e0c 100644<br>
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
@@ -16,7 +16,9 @@<br>
#include <libcamera/control_ids.h><br>
#include <libcamera/file_descriptor.h><br>
#include <libcamera/formats.h><br>
+#include <libcamera/ipa/ipa_proxy_raspberrypi.h><br>
#include <libcamera/ipa/raspberrypi.h><br>
+#include <libcamera/ipa/raspberrypi_generated.h><br>
#include <libcamera/logging.h><br>
#include <libcamera/property_ids.h><br>
#include <libcamera/request.h><br>
@@ -142,7 +144,11 @@ public:<br>
int loadIPA();<br>
int configureIPA();<br>
<br>
- void queueFrameAction(unsigned int frame, const IPAOperationData &action);<br>
+ void statsMetadataComplete(uint32_t bufferId, const ControlList &controls);<br>
+ void runIsp(uint32_t bufferId);<br>
+ void embeddedComplete(uint32_t bufferId);<br>
+ void setIsp(const ControlList &controls);<br>
+ void setStaggered(const ControlList &controls);<br>
<br>
/* bufferComplete signal handlers. */<br>
void unicamBufferDequeue(FrameBuffer *buffer);<br>
@@ -154,6 +160,8 @@ public:<br>
void handleExternalBuffer(FrameBuffer *buffer, RPi::RPiStream *stream);<br>
void handleState();<br>
<br>
+ std::unique_ptr<IPAProxyRPi> ipa_;<br>
+<br>
CameraSensor *sensor_;<br>
/* Array of Unicam and ISP device streams and associated buffers/streams. */<br>
RPi::RPiDevice<Unicam, 2> unicam_;<br>
@@ -356,6 +364,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()<br>
PipelineHandlerRPi::PipelineHandlerRPi(CameraManager *manager)<br>
: PipelineHandler(manager), unicam_(nullptr), isp_(nullptr)<br>
{<br>
+ initializeRPiControls();<br>
}<br>
<br>
CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,<br>
@@ -974,11 +983,17 @@ void RPiCameraData::frameStarted(uint32_t sequence)<br>
<br>
int RPiCameraData::loadIPA()<br>
{<br>
- ipa_ = IPAManager::createIPA(pipe_, 1, 1);<br>
+ std::unique_ptr<IPAProxy> ptr = IPAManager::createIPA(pipe_, 1, 1);<br>
+ ipa_ = std::unique_ptr<IPAProxyRPi>{static_cast<IPAProxyRPi*>(std::move(ptr).release())};<br>
+<br>
if (!ipa_)<br>
return -ENOENT;<br>
<br>
- ipa_->queueFrameAction.connect(this, &RPiCameraData::queueFrameAction);<br>
+ ipa_->statsMetadataComplete.connect(this, &RPiCameraData::statsMetadataComplete);<br>
+ ipa_->runIsp.connect(this, &RPiCameraData::runIsp);<br>
+ ipa_->embeddedComplete.connect(this, &RPiCameraData::embeddedComplete);<br>
+ ipa_->setIsp.connect(this, &RPiCameraData::setIsp);<br>
+ ipa_->setStaggered.connect(this, &RPiCameraData::setStaggered);<br>
<br>
IPASettings settings{<br>
.configurationFile = ipa_->configurationFile(sensor_->model() + ".json")<br>
@@ -990,8 +1005,8 @@ int RPiCameraData::loadIPA()<br>
int RPiCameraData::configureIPA()<br>
{<br>
std::map<unsigned int, IPAStream> streamConfig;<br>
- std::map<unsigned int, const ControlInfoMap &> entityControls;<br>
- IPAOperationData ipaConfig = {};<br>
+ std::map<unsigned int, ControlInfoMap> entityControls;<br>
+ RPiConfigInput ipaConfig;<br>
<br>
/* Get the device format to pass to the IPA. */<br>
V4L2DeviceFormat sensorFormat;<br>
@@ -1017,8 +1032,9 @@ int RPiCameraData::configureIPA()<br>
return -ENOMEM;<br>
<br>
/* Allow the IPA to mmap the LS table via the file descriptor. */<br>
- ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;<br>
- ipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };<br>
+ ipaConfig.op_ = RPI_IPA_CONFIG_LS_TABLE;<br>
+ ipaConfig.lsTableHandle_ = lsTable_;<br>
+ ipaConfig.lsTableHandleStatic_ = lsTable_.fd();<br>
}<br>
<br>
CameraSensorInfo sensorInfo = {};<br>
@@ -1029,105 +1045,92 @@ int RPiCameraData::configureIPA()<br>
}<br>
<br>
/* Ready the IPA - it must know about the sensor resolution. */<br>
- IPAOperationData result;<br>
+ RPiConfigOutput result;<br>
<br>
ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,<br>
&result);<br>
<br>
- unsigned int resultIdx = 0;<br>
- if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {<br>
+ if (result.op_ & RPI_IPA_CONFIG_STAGGERED_WRITE) {<br>
+<br>
/*<br>
* Setup our staggered control writer with the sensor default<br>
* gain and exposure delays.<br>
*/<br>
if (!staggeredCtrl_) {<br>
staggeredCtrl_.init(unicam_[Unicam::Image].dev(),<br>
- { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] },<br>
- { V4L2_CID_EXPOSURE, result.data[resultIdx++] } });<br>
- sensorMetadata_ = result.data[resultIdx++];<br>
+ { { V4L2_CID_ANALOGUE_GAIN,<br>
+ result.staggeredWriteResult_.gainDelay_ },<br>
+ { V4L2_CID_EXPOSURE,<br>
+ result.staggeredWriteResult_.exposureDelay_ } });<br>
+ sensorMetadata_ = result.staggeredWriteResult_.sensorMetadata_;<br>
+ }<br>
+<br>
+ if (result.op_ & RPI_IPA_CONFIG_SENSOR) {<br>
+ const ControlList &ctrls = result.controls_;<br>
+ if (!staggeredCtrl_.set(ctrls))<br>
+ LOG(RPI, Error) << "V4L2 staggered set failed";<br>
}<br>
- }<br>
<br>
- if (result.operation & RPI_IPA_CONFIG_SENSOR) {<br>
- const ControlList &ctrls = result.controls[0];<br>
- if (!staggeredCtrl_.set(ctrls))<br>
- LOG(RPI, Error) << "V4L2 staggered set failed";<br>
}<br>
<br>
- if (result.operation & RPI_IPA_CONFIG_DROP_FRAMES) {<br>
+ if (result.op_ & RPI_IPA_CONFIG_DROP_FRAMES) {<br>
/* Configure the number of dropped frames required on startup. */<br>
- dropFrameCount_ = result.data[resultIdx++];<br>
+ dropFrameCount_ = result.dropFrameCount_;<br>
}<br>
<br>
return 0;<br>
}<br>
<br>
-void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,<br>
- const IPAOperationData &action)<br>
+void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &controls)<br>
{<br>
- /*<br>
- * The following actions can be handled when the pipeline handler is in<br>
- * a stopped state.<br>
- */<br>
- switch (action.operation) {<br>
- case RPI_IPA_ACTION_V4L2_SET_STAGGERED: {<br>
- const ControlList &controls = action.controls[0];<br>
- if (!staggeredCtrl_.set(controls))<br>
- LOG(RPI, Error) << "V4L2 staggered set failed";<br>
- goto done;<br>
- }<br>
+ if (state_ == State::Stopped)<br>
+ handleState();<br>
<br>
- case RPI_IPA_ACTION_V4L2_SET_ISP: {<br>
- ControlList controls = action.controls[0];<br>
- isp_[Isp::Input].dev()->setControls(&controls);<br>
- goto done;<br>
- }<br>
- }<br>
+ FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);<br>
+<br>
+ handleStreamBuffer(buffer, &isp_[Isp::Stats]);<br>
+ /* Fill the Request metadata buffer with what the IPA has provided */<br>
+ requestQueue_.front()->metadata() = std::move(controls);<br>
+ state_ = State::IpaComplete;<br>
+ handleState();<br>
+}<br>
<br>
+void RPiCameraData::runIsp(uint32_t bufferId)<br>
+{<br>
if (state_ == State::Stopped)<br>
- goto done;<br>
+ handleState();<br>
<br>
- /*<br>
- * The following actions must not be handled when the pipeline handler<br>
- * is in a stopped state.<br>
- */<br>
- switch (action.operation) {<br>
- case RPI_IPA_ACTION_STATS_METADATA_COMPLETE: {<br>
- unsigned int bufferId = action.data[0];<br>
- FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);<br>
-<br>
- handleStreamBuffer(buffer, &isp_[Isp::Stats]);<br>
- /* Fill the Request metadata buffer with what the IPA has provided */<br>
- requestQueue_.front()->metadata() = std::move(action.controls[0]);<br>
- state_ = State::IpaComplete;<br>
- break;<br>
- }<br>
+ FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);<br>
<br>
- case RPI_IPA_ACTION_EMBEDDED_COMPLETE: {<br>
- unsigned int bufferId = action.data[0];<br>
- FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);<br>
- handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);<br>
- break;<br>
- }<br>
+ LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId<br>
+ << ", timestamp: " << buffer->metadata().timestamp;<br>
<br>
- case RPI_IPA_ACTION_RUN_ISP: {<br>
- unsigned int bufferId = action.data[0];<br>
- FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);<br>
+ isp_[Isp::Input].queueBuffer(buffer);<br>
+ ispOutputCount_ = 0;<br>
+ handleState();<br>
+}<br>
<br>
- LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId<br>
- << ", timestamp: " << buffer->metadata().timestamp;<br>
+void RPiCameraData::embeddedComplete(uint32_t bufferId)<br>
+{<br>
+ if (state_ == State::Stopped)<br>
+ handleState();<br>
<br>
- isp_[Isp::Input].queueBuffer(buffer);<br>
- ispOutputCount_ = 0;<br>
- break;<br>
- }<br>
+ FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);<br>
+ handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);<br>
+ handleState();<br>
+}<br>
<br>
- default:<br>
- LOG(RPI, Error) << "Unknown action " << action.operation;<br>
- break;<br>
- }<br>
+void RPiCameraData::setIsp(const ControlList &controls)<br>
+{<br>
+ ControlList ctrls = controls;<br>
+ isp_[Isp::Input].dev()->setControls(&ctrls);<br>
+ handleState();<br>
+}<br>
<br>
-done:<br>
+void RPiCameraData::setStaggered(const ControlList &controls)<br>
+{<br>
+ if (!staggeredCtrl_.set(controls))<br>
+ LOG(RPI, Error) << "V4L2 staggered set failed";<br>
handleState();<br>
}<br>
<br>
@@ -1227,10 +1230,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)<br>
* application until after the IPA signals so.<br>
*/<br>
if (stream == &isp_[Isp::Stats]) {<br>
- IPAOperationData op;<br>
- op.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY;<br>
- op.data = { RPiBufferMask::STATS | static_cast<unsigned int>(index) };<br>
- ipa_->processEvent(op);<br>
+ ipa_->signalStatReady(RPiBufferMask::STATS | static_cast<unsigned int>(index));<br>
} else {<br>
/* Any other ISP output can be handed back to the application now. */<br>
handleStreamBuffer(buffer, stream);<br>
@@ -1403,7 +1403,6 @@ void RPiCameraData::checkRequestCompleted()<br>
void RPiCameraData::tryRunPipeline()<br>
{<br>
FrameBuffer *bayerBuffer, *embeddedBuffer;<br>
- IPAOperationData op;<br>
<br>
/* If any of our request or buffer queues are empty, we cannot proceed. */<br>
if (state_ != State::Idle || requestQueue_.empty() ||<br>
@@ -1454,9 +1453,7 @@ void RPiCameraData::tryRunPipeline()<br>
* queue the ISP output buffer listed in the request to start the HW<br>
* pipeline.<br>
*/<br>
- op.operation = RPI_IPA_EVENT_QUEUE_REQUEST;<br>
- op.controls = { request->controls() };<br>
- ipa_->processEvent(op);<br>
+ ipa_->signalQueueRequest(request->controls());<br>
<br>
/* Ready to use the buffers, pop them off the queue. */<br>
bayerQueue_.pop();<br>
@@ -1472,10 +1469,10 @@ void RPiCameraData::tryRunPipeline()<br>
<< " Bayer buffer id: " << bayerId<br>
<< " Embedded buffer id: " << embeddedId;<br>
<br>
- op.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE;<br>
- op.data = { RPiBufferMask::EMBEDDED_DATA | embeddedId,<br>
- RPiBufferMask::BAYER_DATA | bayerId };<br>
- ipa_->processEvent(op);<br>
+ RPiIspPreparePayload ispPrepare;<br>
+ ispPrepare.embeddedbufferId_ = RPiBufferMask::EMBEDDED_DATA | embeddedId;<br>
+ ispPrepare.bayerbufferId_ = RPiBufferMask::BAYER_DATA | bayerId;<br>
+ ipa_->signalIspPrepare(ispPrepare);<br>
}<br>
<br>
void RPiCameraData::tryFlushQueues()<br>
-- <br>
2.27.0<br>
<br>
_______________________________________________<br>
libcamera-devel mailing list<br>
<a href="mailto:libcamera-devel@lists.libcamera.org" target="_blank">libcamera-devel@lists.libcamera.org</a><br>
<a href="https://lists.libcamera.org/listinfo/libcamera-devel" rel="noreferrer" target="_blank">https://lists.libcamera.org/listinfo/libcamera-devel</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr">Cheers.<div>Hanlin Chen</div></div></div></div></div></div></div></div></div></div>