<div dir="ltr"><div dir="ltr">Hi Laurent,<div><br></div><div>Thank you for your feedback.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 25 Oct 2021 at 17:44, Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com">laurent.pinchart@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">Hi Naush,<br>
<br>
Thank you for the patch.<br>
<br>
On Fri, Oct 22, 2021 at 04:29:34PM +0100, Naushir Patuck wrote:<br>
> On Fri, 22 Oct 2021 at 16:16, David Plowman wrote:<br>
> <br>
> > Hi Naush<br>
> ><br>
> > Thanks for the new version. I think a lot of stuff is tidier now that<br>
> > we're clear that we're selecting a subdev format.<br>
> ><br>
> > On Fri, 22 Oct 2021 at 15:40, Naushir Patuck wrote:<br>
> > ><br>
> > > Switch the pipeline handler to use the new Unicam media controller based driver.<br>
> > > With this change, we directly talk to the sensor device driver to set controls<br>
> > > and set/get formats in the pipeline handler.<br>
> > ><br>
> > > This change requires the accompanying Raspberry Pi linux kernel change at<br>
> > > <a href="https://github.com/raspberrypi/linux/pull/4645" rel="noreferrer" target="_blank">https://github.com/raspberrypi/linux/pull/4645</a>. If this kernel change is not<br>
> > > present, the pipeline handler will fail to run with an error message informing<br>
> > > the user to update the kernel build.<br>
> > ><br>
> > > Signed-off-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com" target="_blank">naush@raspberrypi.com</a>><br>
> > > ---<br>
> > > .../pipeline/raspberrypi/raspberrypi.cpp | 146 +++++++++++-------<br>
> > > 1 file changed, 90 insertions(+), 56 deletions(-)<br>
> > ><br>
> > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> > > index 1634ca98f481..a31b0f81eba7 100644<br>
> > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> > > @@ -48,6 +48,29 @@ LOG_DEFINE_CATEGORY(RPI)<br>
> > ><br>
> > > namespace {<br>
> > ><br>
> > > +/* Map of mbus codes to supported sizes reported by the sensor. */<br>
> > > +using SensorFormats = std::map<unsigned int, std::vector<Size>>;<br>
> > > +<br>
> > > +SensorFormats populateSensorFormats(std::unique_ptr<CameraSensor> &sensor)<br>
> > > +{<br>
> > > + SensorFormats formats;<br>
> > > +<br>
> > > + for (auto const mbusCode : sensor->mbusCodes())<br>
> > > + formats.emplace(mbusCode, sensor->sizes(mbusCode));<br>
> > > +<br>
> > > + return formats;<br>
> > > +}<br>
> > > +<br>
> > > +inline V4L2DeviceFormat toV4L2DeviceFormat(V4L2SubdeviceFormat &mode)<br>
<br>
s/mode/format/<br>
<br>
(you know how much I like the concept of sensor mode)<br>
<br>
> > > +{<br>
> > > + V4L2DeviceFormat deviceFormat;<br>
> > > + BayerFormat bayer = BayerFormat::fromMbusCode(mode.mbus_code);<br>
> > > +<br>
> > > + deviceFormat.fourcc = bayer.toV4L2PixelFormat();<br>
> > > + deviceFormat.size = mode.size;<br>
> > > + return deviceFormat;<br>
> > > +}<br>
> > > +<br>
> ><br>
> > I guess I wonder slightly whether this should be generally available,<br>
> > but it could easily be a change for another time. (Actually, same<br>
> > question for isRaw just below...)<br>
> <br>
> Agree, this can be addressed separately.<br>
<br>
I'm afraid it can't be this simple :-( There's no 1:1 mapping between<br>
media bus codes and V4L2 pixel formats. How a given format received on a<br>
bus by a DMA engine is stored in memory depends on the device. For<br>
instance, unicam will store BGGR RAW10 as V4L2_PIX_FMT_SBGGR10P, while<br>
another device may store it as V4L2_PIX_FMT_SBGGR10 (expanded to 2 bytes<br>
per pixel in memory). Yet another device may left-align the 10 bits,<br>
storing the data in V4L2_PIX_FMT_SBGGR16 format. This mapping can't be<br>
provided by the libcamera core. Using the BayerFormat class to perform<br>
the conversion with BayerFormat::fromMbusCode().toV4L2PixelFormat() may<br>
work in some cases, but not universally.<br></blockquote><div><br></div><div>I was also a bit unsure about what to do about mbus to v4l2 format conversions.</div><div>I went with using the BayerFormat class table as that was readily available, and</div><div>not needing to duplicate the table in the pipeline handler. Luckily, I think in all (standard)</div><div>cases, the conversion from mbus codes to v4l2 4cc's through the BayerFormat</div><div>class conversion table will be valid for Unicam, but I do take the point this is</div><div>not entirely correct.</div><div><br></div><div>Perhaps I will just bite the bullet and add a similar table into our pipeline handler. As</div><div>you said, avoiding technical debt is a good thing.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
I'm actually surprised the conversion works here, as I think you'll get<br>
V4L2_PIX_FMT_SBGGR10 when you expect V4L2_PIX_FMT_SBGGR10P. One<br>
possibility to fix this would be to set bayer.packing before calling<br>
toV4L2PixelFormat().</blockquote><div><br></div><div>This works because Unicam can support both packed and unpacked formats</div><div>when writing out to SDRAM. As you have noticed, a subsequent change in this</div><div>series adds the option of choosing which to select.</div><div><br></div><div>I'll add the new table in the next revision.</div><div><br></div><div>Regards,</div><div>Naush</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The API is fragile though, and the BayerFormat<br>
class a bit ill-defined (it doesn't tell whether it's supposed to<br>
represent a bus format or a pixel format, and as explained above, it<br>
can't be used interchangeably). This doesn't have to be fixed as part of<br>
this patch series, but I'd like to see that problem addressed, and we<br>
shouldn't build more technical debt.<br>
<br>
> > > bool isRaw(PixelFormat &pixFmt)<br>
> > > {<br>
> > > /*<br>
> > > @@ -74,11 +97,10 @@ double scoreFormat(double desired, double actual)<br>
> > > return score;<br>
> > > }<br>
> > ><br>
> > > -V4L2DeviceFormat findBestMode(V4L2VideoDevice::Formats &formatsMap,<br>
> > > - const Size &req)<br>
> > > +V4L2SubdeviceFormat findBestMode(const SensorFormats &formatsMap, const Size &req)<br>
> > > {<br>
> > > double bestScore = std::numeric_limits<double>::max(), score;<br>
> > > - V4L2DeviceFormat bestMode;<br>
> > > + V4L2SubdeviceFormat bestMode;<br>
> > ><br>
> > > #define PENALTY_AR 1500.0<br>
> > > #define PENALTY_8BIT 2000.0<br>
> > > @@ -88,18 +110,17 @@ V4L2DeviceFormat findBestMode(V4L2VideoDevice::Formats &formatsMap,<br>
> > ><br>
> > > /* Calculate the closest/best mode from the user requested size. */<br>
> > > for (const auto &iter : formatsMap) {<br>
> > > - V4L2PixelFormat v4l2Format = iter.first;<br>
> > > - const PixelFormatInfo &info = PixelFormatInfo::info(v4l2Format);<br>
> > > + const unsigned int mbus_code = iter.first;<br>
<br>
s/mbus_code/mbusCode/<br>
<br>
> > > + const PixelFormat format = BayerFormat::fromMbusCode(mbus_code).toPixelFormat();<br>
<br>
Same issue as above.<br>
<br>
> > > + const PixelFormatInfo &info = PixelFormatInfo::info(format);<br>
> > ><br>
> > > - for (const SizeRange &sz : iter.second) {<br>
<br>
s/sz/size/<br>
<br>
> > > - double modeWidth = sz.contains(req) ? req.width : sz.max.width;<br>
> > > - double modeHeight = sz.contains(req) ? req.height : sz.max.height;<br>
> > > + for (const Size &sz : iter.second) {<br>
> > > double reqAr = static_cast<double>(req.width) / req.height;<br>
> > > - double modeAr = modeWidth / modeHeight;<br>
> > > + double modeAr = sz.width / sz.height;<br>
> > ><br>
> > > /* Score the dimensions for closeness. */<br>
> > > - score = scoreFormat(req.width, modeWidth);<br>
> > > - score += scoreFormat(req.height, modeHeight);<br>
> > > + score = scoreFormat(req.width, sz.width);<br>
> > > + score += scoreFormat(req.height, sz.height);<br>
> > > score += PENALTY_AR * scoreFormat(reqAr, modeAr);<br>
> > ><br>
> > > /* Add any penalties... this is not an exact science! */<br>
> > > @@ -115,12 +136,12 @@ V4L2DeviceFormat findBestMode(V4L2VideoDevice::Formats &formatsMap,<br>
> > ><br>
> > > if (score <= bestScore) {<br>
> > > bestScore = score;<br>
> > > - bestMode.fourcc = v4l2Format;<br>
> > > - bestMode.size = Size(modeWidth, modeHeight);<br>
> > > + bestMode.mbus_code = mbus_code;<br>
> > > + bestMode.size = sz;<br>
> > > }<br>
> > ><br>
> > > - LOG(RPI, Info) << "Mode: " << modeWidth << "x" << modeHeight<br>
> > > - << " fmt " << v4l2Format.toString()<br>
> > > + LOG(RPI, Info) << "Mode: " << sz.width << "x" << sz.height<br>
<br>
You can use sz.toString().<br>
<br>
> > > + << " fmt " << format.toString()<br>
> > > << " Score: " << score<br>
> > > << " (best " << bestScore << ")";<br>
> > > }<br>
> > > @@ -170,6 +191,7 @@ public:<br>
> > > std::unique_ptr<ipa::RPi::IPAProxyRPi> ipa_;<br>
> > ><br>
> > > std::unique_ptr<CameraSensor> sensor_;<br>
> > > + SensorFormats sensorFormats_;<br>
> > > /* Array of Unicam and ISP device streams and associated buffers/streams. */<br>
> > > RPi::Device<Unicam, 2> unicam_;<br>
> > > RPi::Device<Isp, 4> isp_;<br>
> > > @@ -352,9 +374,9 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()<br>
> > > * Calculate the best sensor mode we can use based on<br>
> > > * the user request.<br>
> > > */<br>
> > > - V4L2VideoDevice::Formats fmts = data_->unicam_[Unicam::Image].dev()->formats();<br>
> > > - V4L2DeviceFormat sensorFormat = findBestMode(fmts, cfg.size);<br>
> > > - int ret = data_->unicam_[Unicam::Image].dev()->tryFormat(&sensorFormat);<br>
> > > + V4L2SubdeviceFormat sensorFormat = findBestMode(data_->sensorFormats_, cfg.size);<br>
> > > + V4L2DeviceFormat unicamFormat = toV4L2DeviceFormat(sensorFormat);<br>
> > > + int ret = data_->unicam_[Unicam::Image].dev()->tryFormat(&unicamFormat);<br>
> > > if (ret)<br>
> > > return Invalid;<br>
> > ><br>
> > > @@ -366,7 +388,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()<br>
> > > * fetch the "native" (i.e. untransformed) Bayer order,<br>
> > > * because the sensor may currently be flipped!<br>
> > > */<br>
> > > - V4L2PixelFormat fourcc = sensorFormat.fourcc;<br>
> > > + V4L2PixelFormat fourcc = unicamFormat.fourcc;<br>
> > > if (data_->flipsAlterBayerOrder_) {<br>
> > > BayerFormat bayer = BayerFormat::fromV4L2PixelFormat(fourcc);<br>
> > > bayer.order = data_->nativeBayerOrder_;<br>
> > > @@ -375,15 +397,15 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()<br>
> > > }<br>
> > ><br>
> > > PixelFormat sensorPixFormat = fourcc.toPixelFormat();<br>
> > > - if (cfg.size != sensorFormat.size ||<br>
> > > + if (cfg.size != unicamFormat.size ||<br>
> > > cfg.pixelFormat != sensorPixFormat) {<br>
> > > - cfg.size = sensorFormat.size;<br>
> > > + cfg.size = unicamFormat.size;<br>
> > > cfg.pixelFormat = sensorPixFormat;<br>
> > > status = Adjusted;<br>
> > > }<br>
> > ><br>
> > > - cfg.stride = sensorFormat.planes[0].bpl;<br>
> > > - cfg.frameSize = sensorFormat.planes[0].size;<br>
> > > + cfg.stride = unicamFormat.planes[0].bpl;<br>
> > > + cfg.frameSize = unicamFormat.planes[0].size;<br>
> > ><br>
> > > rawCount++;<br>
> > > } else {<br>
> > > @@ -472,7 +494,8 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,<br>
> > > {<br>
> > > RPiCameraData *data = cameraData(camera);<br>
> > > CameraConfiguration *config = new RPiCameraConfiguration(data);<br>
> > > - V4L2DeviceFormat sensorFormat;<br>
> > > + V4L2SubdeviceFormat sensorFormat;<br>
> > > + V4L2DeviceFormat unicamFormat;<br>
> > > unsigned int bufferCount;<br>
> > > PixelFormat pixelFormat;<br>
> > > V4L2VideoDevice::Formats fmts;<br>
> > > @@ -487,9 +510,9 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,<br>
> > > switch (role) {<br>
> > > case StreamRole::Raw:<br>
> > > size = data->sensor_->resolution();<br>
> > > - fmts = data->unicam_[Unicam::Image].dev()->formats();<br>
> > > - sensorFormat = findBestMode(fmts, size);<br>
> > > - pixelFormat = sensorFormat.fourcc.toPixelFormat();<br>
> > > + sensorFormat = findBestMode(data->sensorFormats_, size);<br>
> > > + unicamFormat = toV4L2DeviceFormat(sensorFormat);<br>
> > > + pixelFormat = BayerFormat::fromMbusCode(sensorFormat.mbus_code).toPixelFormat();<br>
<br>
Same issue as above.<br>
<br>
> > > ASSERT(pixelFormat.isValid());<br>
> > > bufferCount = 2;<br>
> > > rawCount++;<br>
> > > @@ -599,32 +622,30 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)<br>
> > > }<br>
> > ><br>
> > > /* First calculate the best sensor mode we can use based on the user request. */<br>
> > > - V4L2VideoDevice::Formats fmts = data->unicam_[Unicam::Image].dev()->formats();<br>
> > > - V4L2DeviceFormat sensorFormat = findBestMode(fmts, rawStream ? sensorSize : maxSize);<br>
> > > + V4L2SubdeviceFormat sensorFormat = findBestMode(data->sensorFormats_, rawStream ? sensorSize : maxSize);<br>
> > > + V4L2DeviceFormat unicamFormat = toV4L2DeviceFormat(sensorFormat);<br>
<br>
Shouldn't this go after sensor_->setFormat() in case the sensor adjusts<br>
the format ? Actually, as adjustments are not allowed in configure(),<br>
you should check the that format set on the sensor matches the requested<br>
format.<br>
<br>
> > > +<br>
> > > + ret = data->sensor_->setFormat(&sensorFormat);<br>
> > > + if (ret)<br>
> > > + return ret;<br>
> > ><br>
> > > /*<br>
> > > * Unicam image output format. The ISP input format gets set at start,<br>
> > > * just in case we have swapped bayer orders due to flips.<br>
> > > */<br>
> > > - ret = data->unicam_[Unicam::Image].dev()->setFormat(&sensorFormat);<br>
> > > + ret = data->unicam_[Unicam::Image].dev()->setFormat(&unicamFormat);<br>
> > > if (ret)<br>
> > > return ret;<br>
> > ><br>
> > > - /*<br>
> > > - * The control ranges associated with the sensor may need updating<br>
> > > - * after a format change.<br>
> > > - * \todo Use the CameraSensor::setFormat API instead.<br>
> > > - */<br>
> > > - data->sensor_->updateControlInfo();<br>
> > > -<br>
> > > LOG(RPI, Info) << "Sensor: " << camera->id()<br>
> > > - << " - Selected mode: " << sensorFormat.toString();<br>
> > > + << " - Selected sensor mode: " << sensorFormat.toString()<br>
> > > + << " - Selected unicam mode: " << unicamFormat.toString();<br>
<br>
s/mode/format/ on both lines<br>
<br>
> > ><br>
> > > /*<br>
> > > * This format may be reset on start() if the bayer order has changed<br>
> > > * because of flips in the sensor.<br>
> > > */<br>
> > > - ret = data->isp_[Isp::Input].dev()->setFormat(&sensorFormat);<br>
> > > + ret = data->isp_[Isp::Input].dev()->setFormat(&unicamFormat);<br>
> > > if (ret)<br>
> > > return ret;<br>
> > ><br>
> > > @@ -746,8 +767,8 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)<br>
> > > data->ispMinCropSize_ = testCrop.size();<br>
> > ><br>
> > > /* Adjust aspect ratio by providing crops on the input image. */<br>
> > > - Size size = sensorFormat.size.boundedToAspectRatio(maxSize);<br>
> > > - Rectangle crop = size.centeredTo(Rectangle(sensorFormat.size).center());<br>
> > > + Size size = unicamFormat.size.boundedToAspectRatio(maxSize);<br>
> > > + Rectangle crop = size.centeredTo(Rectangle(unicamFormat.size).center());<br>
> > > data->ispCrop_ = crop;<br>
> > ><br>
> > > data->isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &crop);<br>
> > > @@ -761,8 +782,11 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)<br>
> > > * supports it.<br>
> > > */<br>
> > > if (data->sensorMetadata_) {<br>
> > > - format = {};<br>
> > > + V4L2SubdeviceFormat embeddedFormat;<br>
> > > +<br>
> > > + data->sensor_->device()->getFormat(1, &embeddedFormat);<br>
> > > format.fourcc = V4L2PixelFormat(V4L2_META_FMT_SENSOR_DATA);<br>
> > > + format.planes[0].size = embeddedFormat.size.width * embeddedFormat.size.height;<br>
> > ><br>
> > > LOG(RPI, Debug) << "Setting embedded data format.";<br>
> > > ret = data->unicam_[Unicam::Embedded].dev()->setFormat(&format);<br>
> > > @@ -847,9 +871,14 @@ int PipelineHandlerRPi::start(Camera *camera, const ControlList *controls)<br>
> > > * IPA configure may have changed the sensor flips - hence the bayer<br>
> > > * order. Get the sensor format and set the ISP input now.<br>
> > > */<br>
> > > - V4L2DeviceFormat sensorFormat;<br>
> > > - data->unicam_[Unicam::Image].dev()->getFormat(&sensorFormat);<br>
> > > - ret = data->isp_[Isp::Input].dev()->setFormat(&sensorFormat);<br>
> > > + V4L2SubdeviceFormat sensorFormat;<br>
> > > + data->sensor_->device()->getFormat(0, &sensorFormat);<br>
> > > +<br>
> > > + V4L2DeviceFormat ispFormat;<br>
> > > + ispFormat.fourcc = BayerFormat::fromMbusCode(sensorFormat.mbus_code).toV4L2PixelFormat();<br>
> ><br>
> > Generally there's the occasional assumption that fromMbusCode won't<br>
> > return invalid Bayer formats, and I guess we're comfortable with that?<br>
> > It certainly shouldn't be possible.<br>
> <br>
> Yes, I ought to add an assert to ensure the bayer format is valid.<br>
> <br>
> > But it seems good to me, so:<br>
> ><br>
> > Reviewed-by: David Plowman <<a href="mailto:david.plowman@raspberrypi.com" target="_blank">david.plowman@raspberrypi.com</a>><br>
> ><br>
> > > + ispFormat.size = sensorFormat.size;<br>
> > > +<br>
> > > + ret = data->isp_[Isp::Input].dev()->setFormat(&ispFormat);<br>
> > > if (ret) {<br>
> > > stop(camera);<br>
> > > return ret;<br>
> > > @@ -1004,6 +1033,8 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)<br>
> > > if (data->sensor_->init())<br>
> > > return false;<br>
> > ><br>
> > > + data->sensorFormats_ = populateSensorFormats(data->sensor_);<br>
> > > +<br>
> > > ipa::RPi::SensorConfig sensorConfig;<br>
> > > if (data->loadIPA(&sensorConfig)) {<br>
> > > LOG(RPI, Error) << "Failed to load a suitable IPA library";<br>
> > > @@ -1030,6 +1061,11 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)<br>
> > > return false;<br>
> > > }<br>
> > ><br>
> > > + if (!(data->unicam_[Unicam::Image].dev()->caps().device_caps() & V4L2_CAP_IO_MC)) {<br>
> > > + LOG(RPI, Error) << "Unicam driver did not advertise V4L2_CAP_IO_MC, please update your kernel!";<br>
> > > + return false;<br>
> > > + }<br>
> > > +<br>
> > > /*<br>
> > > * Setup our delayed control writer with the sensor default<br>
> > > * gain and exposure delays. Mark VBLANK for priority write.<br>
> > > @@ -1039,7 +1075,7 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)<br>
> > > { V4L2_CID_EXPOSURE, { sensorConfig.exposureDelay, false } },<br>
> > > { V4L2_CID_VBLANK, { sensorConfig.vblankDelay, true } }<br>
> > > };<br>
> > > - data->delayedCtrls_ = std::make_unique<DelayedControls>(data->unicam_[Unicam::Image].dev(), params);<br>
> > > + data->delayedCtrls_ = std::make_unique<DelayedControls>(data->sensor_->device(), params);<br>
> > > data->sensorMetadata_ = sensorConfig.sensorMetadata;<br>
> > ><br>
> > > /* Register the controls that the Raspberry Pi IPA can handle. */<br>
> > > @@ -1066,15 +1102,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)<br>
> > > * As part of answering the final question, we reset the camera to<br>
> > > * no transform at all.<br>
> > > */<br>
> > > -<br>
> > > - V4L2VideoDevice *dev = data->unicam_[Unicam::Image].dev();<br>
> > > - const struct v4l2_query_ext_ctrl *hflipCtrl = dev->controlInfo(V4L2_CID_HFLIP);<br>
> > > + const V4L2Subdevice *sensor = data->sensor_->device();<br>
> > > + const struct v4l2_query_ext_ctrl *hflipCtrl = sensor->controlInfo(V4L2_CID_HFLIP);<br>
> > > if (hflipCtrl) {<br>
> > > /* We assume it will support vflips too... */<br>
> > > data->supportsFlips_ = true;<br>
> > > data->flipsAlterBayerOrder_ = hflipCtrl->flags & V4L2_CTRL_FLAG_MODIFY_LAYOUT;<br>
> > ><br>
> > > - ControlList ctrls(dev->controls());<br>
> > > + ControlList ctrls(data->sensor_->controls());<br>
> > > ctrls.set(V4L2_CID_HFLIP, 0);<br>
> > > ctrls.set(V4L2_CID_VFLIP, 0);<br>
> > > data->setSensorControls(ctrls);<br>
> > > @@ -1082,9 +1117,8 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)<br>
> > ><br>
> > > /* Look for a valid Bayer format. */<br>
> > > BayerFormat bayerFormat;<br>
> > > - for (const auto &iter : dev->formats()) {<br>
> > > - V4L2PixelFormat v4l2Format = iter.first;<br>
> > > - bayerFormat = BayerFormat::fromV4L2PixelFormat(v4l2Format);<br>
> > > + for (const auto &iter : data->sensorFormats_) {<br>
> > > + bayerFormat = BayerFormat::fromMbusCode(iter.first);<br>
> > > if (bayerFormat.isValid())<br>
> > > break;<br>
> > > }<br>
> > > @@ -1271,7 +1305,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)<br>
> > > }<br>
> > > }<br>
> > ><br>
> > > - entityControls.emplace(0, unicam_[Unicam::Image].dev()->controls());<br>
> > > + entityControls.emplace(0, sensor_->controls());<br>
> > > entityControls.emplace(1, isp_[Isp::Input].dev()->controls());<br>
> > ><br>
> > > /* Always send the user transform to the IPA. */<br>
> > > @@ -1406,10 +1440,10 @@ void RPiCameraData::setSensorControls(ControlList &controls)<br>
> > > ControlList vblank_ctrl;<br>
> > ><br>
> > > vblank_ctrl.set(V4L2_CID_VBLANK, controls.get(V4L2_CID_VBLANK));<br>
> > > - unicam_[Unicam::Image].dev()->setControls(&vblank_ctrl);<br>
> > > + sensor_->setControls(&vblank_ctrl);<br>
> > > }<br>
> > ><br>
> > > - unicam_[Unicam::Image].dev()->setControls(&controls);<br>
> > > + sensor_->setControls(&controls);<br>
> > > }<br>
> > ><br>
> > > void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)<br>
<br>
-- <br>
Regards,<br>
<br>
Laurent Pinchart<br>
</blockquote></div></div>