pipeline: raspberrypi: Add a Unicam dequeue timeout

Enable the V4L2VideoDevice dequeue timeout for the Unicam Image node, and
connect the timeout signal to a slot in the pipeline handler. This slot will
log an error message informing the user of a possible hardware stall.

The timeout is calculated as 2x the maximum frame length possible for a given
mode, returned by the IPA.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Naushir Patuck 2022-04-06 13:35:53 +01:00 committed by Laurent Pinchart
parent 16f3d2de50
commit 04faa8477a
3 changed files with 22 additions and 0 deletions

View file

@ -41,6 +41,7 @@ struct IPAConfig {
struct StartConfig { struct StartConfig {
libcamera.ControlList controls; libcamera.ControlList controls;
int32 dropFrameCount; int32 dropFrameCount;
uint32 maxSensorFrameLengthMs;
}; };
interface IPARPiInterface { interface IPARPiInterface {

View file

@ -280,6 +280,8 @@ void IPARPi::start(const ControlList &controls, ipa::RPi::StartConfig *startConf
} }
startConfig->dropFrameCount = dropFrameCount_; startConfig->dropFrameCount = dropFrameCount_;
const Duration maxSensorFrameDuration = mode_.max_frame_length * mode_.line_length;
startConfig->maxSensorFrameLengthMs = maxSensorFrameDuration.get<std::milli>();
firstStart_ = false; firstStart_ = false;
lastRunTimestamp_ = 0; lastRunTimestamp_ = 0;

View file

@ -45,6 +45,8 @@
#include "dma_heaps.h" #include "dma_heaps.h"
#include "rpi_stream.h" #include "rpi_stream.h"
using namespace std::chrono_literals;
namespace libcamera { namespace libcamera {
LOG_DEFINE_CATEGORY(RPI) LOG_DEFINE_CATEGORY(RPI)
@ -208,6 +210,7 @@ public:
void setIspControls(const ControlList &controls); void setIspControls(const ControlList &controls);
void setDelayedControls(const ControlList &controls); void setDelayedControls(const ControlList &controls);
void setSensorControls(ControlList &controls); void setSensorControls(ControlList &controls);
void unicamTimeout();
/* bufferComplete signal handlers. */ /* bufferComplete signal handlers. */
void unicamBufferDequeue(FrameBuffer *buffer); void unicamBufferDequeue(FrameBuffer *buffer);
@ -1050,6 +1053,14 @@ int PipelineHandlerRPi::start(Camera *camera, const ControlList *controls)
} }
} }
/*
* Set the dequeue timeout to the larger of 2x the maximum possible
* frame duration or 1 second.
*/
utils::Duration timeout =
std::max<utils::Duration>(1s, 2 * startConfig.maxSensorFrameLengthMs * 1ms);
data->unicam_[Unicam::Image].dev()->setDequeueTimeout(timeout);
return 0; return 0;
} }
@ -1192,6 +1203,7 @@ int PipelineHandlerRPi::registerCamera(MediaDevice *unicam, MediaDevice *isp, Me
data->isp_[Isp::Stats] = RPi::Stream("ISP Stats", ispCapture3); data->isp_[Isp::Stats] = RPi::Stream("ISP Stats", ispCapture3);
/* Wire up all the buffer connections. */ /* Wire up all the buffer connections. */
data->unicam_[Unicam::Image].dev()->dequeueTimeout.connect(data.get(), &RPiCameraData::unicamTimeout);
data->unicam_[Unicam::Image].dev()->frameStart.connect(data.get(), &RPiCameraData::frameStarted); data->unicam_[Unicam::Image].dev()->frameStart.connect(data.get(), &RPiCameraData::frameStarted);
data->unicam_[Unicam::Image].dev()->bufferReady.connect(data.get(), &RPiCameraData::unicamBufferDequeue); data->unicam_[Unicam::Image].dev()->bufferReady.connect(data.get(), &RPiCameraData::unicamBufferDequeue);
data->isp_[Isp::Input].dev()->bufferReady.connect(data.get(), &RPiCameraData::ispInputDequeue); data->isp_[Isp::Input].dev()->bufferReady.connect(data.get(), &RPiCameraData::ispInputDequeue);
@ -1773,6 +1785,13 @@ void RPiCameraData::setSensorControls(ControlList &controls)
sensor_->setControls(&controls); sensor_->setControls(&controls);
} }
void RPiCameraData::unicamTimeout()
{
LOG(RPI, Error) << "Unicam has timed out!";
LOG(RPI, Error) << "Please check that your camera sensor connector is attached securely.";
LOG(RPI, Error) << "Alternatively, try another cable and/or sensor.";
}
void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer) void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)
{ {
RPi::Stream *stream = nullptr; RPi::Stream *stream = nullptr;