@@ -48,7 +48,7 @@ public:
bool supportsEvents(v4l2_event_subscription &sub);
int setFrameStartEnabled(bool enable);
- Signal<uint32_t> frameStart;
+ Signal<const v4l2_event &> eventReady;
void updateControlInfo();
@@ -16,6 +16,8 @@
#include "libcamera/internal/v4l2_subdevice.h"
#include "libcamera/internal/v4l2_videodevice.h"
+struct v4l2_event;
+
namespace libcamera {
class CameraSensor;
@@ -58,7 +60,7 @@ public:
FrameBuffer *queueBuffer(FrameBuffer *rawBuffer);
void tryReturnBuffer(FrameBuffer *buffer);
Signal<FrameBuffer *> &bufferReady() { return output_->bufferReady; }
- Signal<uint32_t> &frameStart() { return csi2_->frameStart; }
+ Signal<const v4l2_event &> eventReady() { return csi2_->eventReady; }
Signal<> bufferAvailable;
@@ -11,6 +11,7 @@
#include <vector>
#include <linux/intel-ipu3.h>
+#include <linux/videodev2.h>
#include <libcamera/base/log.h>
#include <libcamera/base/utils.h>
@@ -63,7 +64,7 @@ public:
void statBufferReady(FrameBuffer *buffer);
void queuePendingRequests();
void cancelPendingRequests();
- void frameStart(uint32_t sequence);
+ void handleEvent(const v4l2_event &event);
CIO2Device cio2_;
ImgUDevice *imgu_;
@@ -1089,8 +1090,8 @@ int PipelineHandlerIPU3::registerCameras()
data->delayedCtrls_ =
std::make_unique<DelayedControls>(cio2->sensor()->device(),
params);
- data->cio2_.frameStart().connect(data.get(),
- &IPU3CameraData::frameStart);
+ data->cio2_.eventReady().connect(data.get(),
+ &IPU3CameraData::handleEvent);
/* Convert the sensor rotation to a transformation */
const auto &rotation = data->properties_.get(properties::Rotation);
@@ -1313,7 +1314,7 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
* Record the sensor's timestamp in the request metadata.
*
* \todo The sensor timestamp should be better estimated by connecting
- * to the V4L2Device::frameStart signal.
+ * to the V4L2Device::eventReady signal for frame sync events.
*/
request->_d()->metadata().set(controls::SensorTimestamp,
buffer->metadata().timestamp);
@@ -1382,9 +1383,14 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer)
* TestPatternMode one. Other controls are handled through the delayed
* controls class.
*/
-void IPU3CameraData::frameStart(uint32_t sequence)
+
+void IPU3CameraData::handleEvent(const v4l2_event &event)
{
- delayedCtrls_->applyControls(sequence);
+ if (event.type != V4L2_EVENT_FRAME_SYNC)
+ return;
+
+ auto frameSyncEvent = &event.u.frame_sync;
+ delayedCtrls_->applyControls(frameSyncEvent->frame_sequence);
if (processingRequests_.empty())
return;
@@ -17,6 +17,7 @@
#include <linux/media-bus-format.h>
#include <linux/media.h>
#include <linux/media/arm/mali-c55-config.h>
+#include <linux/videodev2.h>
#include <libcamera/base/log.h>
#include <libcamera/base/utils.h>
@@ -198,6 +199,8 @@ public:
PixelFormat adjustRawFormat(const PixelFormat &pixFmt) const;
Size adjustRawSizes(const PixelFormat &pixFmt, const Size &rawSize) const;
+ void handleEvent(const v4l2_event &event);
+
Stream frStream_;
Stream dsStream_;
@@ -451,6 +454,15 @@ Size MaliC55CameraData::adjustRawSizes(const PixelFormat &rawFmt, const Size &si
return bestSize;
}
+void MaliC55CameraData::handleEvent(const v4l2_event &event)
+{
+ if (event.type != V4L2_EVENT_FRAME_SYNC)
+ return;
+
+ auto frameSyncEvent = &event.u.frame_sync;
+ delayedCtrls_->applyControls(frameSyncEvent->frame_sequence);
+}
+
int MaliC55CameraData::loadIPA()
{
int ret;
@@ -1849,8 +1861,7 @@ bool PipelineHandlerMaliC55::registerSensorCamera(MediaLink *ispLink)
V4L2Subdevice *sensorSubdev = in->sensor_->device();
data->delayedCtrls_ = std::make_unique<DelayedControls>(sensorSubdev,
params);
- isp_->frameStart.connect(data->delayedCtrls_.get(),
- &DelayedControls::applyControls);
+ isp_->eventReady.connect(data.get(), &MaliC55CameraData::handleEvent);
/* \todo Init properties. */
@@ -1913,8 +1924,7 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera(MediaLink *link)
data->delayedCtrls_ =
std::make_unique<DelayedControls>(sensor->device(), params);
- isp_->frameStart.connect(data->delayedCtrls_.get(),
- &DelayedControls::applyControls);
+ isp_->eventReady.connect(data.get(), &MaliC55CameraData::handleEvent);
ivc_->bufferReady.connect(mem->cru_.get(), &RZG2LCRU::returnBuffer);
@@ -106,6 +106,8 @@ public:
const PipelineHandlerRkISP1 *pipe() const;
int loadIPA(unsigned int hwRevision, uint32_t supportedBlocks);
+ void handleEvent(const v4l2_event &event);
+
Stream mainPathStream_;
Stream selfPathStream_;
std::unique_ptr<CameraSensor> sensor_;
@@ -430,6 +432,15 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision, uint32_t supportedBlocks)
return 0;
}
+void RkISP1CameraData::handleEvent(const v4l2_event &event)
+{
+ if (event.type != V4L2_EVENT_FRAME_SYNC)
+ return;
+
+ auto frameSyncEvent = &event.u.frame_sync;
+ delayedCtrls_->applyControls(frameSyncEvent->frame_sequence);
+}
+
int RkISP1CameraData::loadTuningFile(const std::string &path)
{
int ret;
@@ -1472,8 +1483,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)
data->delayedCtrls_ =
std::make_unique<DelayedControls>(data->sensor_->device(),
params);
- isp_->frameStart.connect(data->delayedCtrls_.get(),
- &DelayedControls::applyControls);
+ isp_->eventReady.connect(data.get(), &RkISP1CameraData::handleEvent);
uint32_t supportedBlocks = kDefaultExtParamsBlocks;
@@ -873,7 +873,7 @@ int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &camera
/* Setup the general IPA signal handlers. */
data->frontendDevice()->dequeueTimeout.connect(data, &RPi::CameraData::cameraTimeout);
- data->frontendDevice()->frameStart.connect(data, &RPi::CameraData::frameStarted);
+ data->frontendDevice()->eventReady.connect(data, &RPi::CameraData::handleEvent);
data->ipa_->setDelayedControls.connect(data, &CameraData::setDelayedControls);
data->ipa_->setLensControls.connect(data, &CameraData::setLensControls);
data->ipa_->metadataReady.connect(data, &CameraData::metadataReady);
@@ -1392,12 +1392,17 @@ void CameraData::cameraTimeout()
clearIncompleteRequests();
}
-void CameraData::frameStarted(uint32_t sequence)
+void CameraData::handleEvent(const v4l2_event &event)
{
- LOG(RPI, Debug) << "Frame start " << sequence;
+ if (event.type != V4L2_EVENT_FRAME_SYNC)
+ return;
+
+ auto frameSyncEvent = &event.u.frame_sync;
+
+ LOG(RPI, Debug) << "Frame start " << frameSyncEvent->frame_sequence;
/* Write any controls for the next frame as soon as we can. */
- delayedCtrls_->applyControls(sequence);
+ delayedCtrls_->applyControls(frameSyncEvent->frame_sequence);
}
void CameraData::clearIncompleteRequests()
@@ -36,6 +36,8 @@
using namespace std::chrono_literals;
+struct v4l2_event;
+
namespace libcamera {
namespace RPi {
@@ -86,7 +88,7 @@ public:
virtual void platformSetIspCrop(unsigned int index, const Rectangle &ispCrop) = 0;
void cameraTimeout();
- void frameStarted(uint32_t sequence);
+ void handleEvent(const v4l2_event &event);
void clearIncompleteRequests();
void handleStreamBuffer(FrameBuffer *buffer, Stream *stream);
@@ -299,6 +299,8 @@ public:
return stream - &streams_.front();
}
+ void handleEvent(const v4l2_event &event);
+
struct Entity {
/* The media entity, always valid. */
MediaEntity *entity;
@@ -988,6 +990,15 @@ void SimpleCameraData::clearIncompleteRequests()
}
}
+void SimpleCameraData::handleEvent(const v4l2_event &event)
+{
+ if (event.type != V4L2_EVENT_FRAME_SYNC)
+ return;
+
+ auto frameSyncEvent = &event.u.frame_sync;
+ delayedCtrls_->applyControls(frameSyncEvent->frame_sequence);
+}
+
void SimpleCameraData::tryCompleteRequest(Request *request)
{
if (request->hasPendingBuffers())
@@ -1676,8 +1687,8 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
stop(camera);
return ret;
}
- frameStartEmitter->frameStart.connect(data->delayedCtrls_.get(),
- &DelayedControls::applyControls);
+ frameStartEmitter->eventReady.connect(data,
+ &SimpleCameraData::handleEvent);
}
ret = video->streamOn();
@@ -1716,8 +1727,8 @@ void SimplePipelineHandler::stopDevice(Camera *camera)
if (frameStartEmitter) {
frameStartEmitter->setFrameStartEnabled(false);
- frameStartEmitter->frameStart.disconnect(data->delayedCtrls_.get(),
- &DelayedControls::applyControls);
+ frameStartEmitter->eventReady.connect(data,
+ &SimpleCameraData::handleEvent);
}
if (data->useConversion_) {
@@ -493,7 +493,7 @@ bool V4L2Device::supportsEvents(v4l2_event_subscription &sub)
* \param[in] enable True to enable frame start events, false to disable them
*
* This function enables or disables generation of frame start events. Once
- * enabled, the events are signalled through the frameStart signal.
+ * enabled, the events are signalled through the eventReady signal.
*
* \return 0 on success, a negative error code otherwise
*/
@@ -518,8 +518,8 @@ int V4L2Device::setFrameStartEnabled(bool enable)
}
/**
- * \var V4L2Device::frameStart
- * \brief A Signal emitted when capture of a frame has started
+ * \var V4L2Device::eventReady
+ * \brief A Signal emitted when a V4L2 event is received
*/
/**
@@ -857,15 +857,7 @@ void V4L2Device::eventAvailable()
return;
}
- if (event.type != V4L2_EVENT_FRAME_SYNC) {
- LOG(V4L2, Error)
- << "Spurious event (" << event.type
- << "), disabling event notifier";
- fdEventNotifier_->setEnabled(false);
- return;
- }
-
- frameStart.emit(event.u.frame_sync.frame_sequence);
+ eventReady.emit(event);
}
static const std::map<uint32_t, ColorSpace> v4l2ToColorSpace = {
Currently V4L2Device emits a signal for the V4L2_EVENT_FRAME_SYNC event, with a Signal signature that is specific to it. Replace this with a generic Signal<const v4l2_event &> and leave the Slots to decide how to handle the event. This will allow us to easily extend handling to other events in the future. Update the existing slots to handle the new Signal signature. Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> --- Changes in v2: - Reworked to drop V4L2Event class and simply use the kernel uAPI directly for the new Signal. --- include/libcamera/internal/v4l2_device.h | 2 +- src/libcamera/pipeline/ipu3/cio2.h | 4 +++- src/libcamera/pipeline/ipu3/ipu3.cpp | 18 ++++++++++++------ src/libcamera/pipeline/mali-c55/mali-c55.cpp | 18 ++++++++++++++---- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 14 ++++++++++++-- src/libcamera/pipeline/rpi/common/pipeline_base.cpp | 13 +++++++++---- src/libcamera/pipeline/rpi/common/pipeline_base.h | 4 +++- src/libcamera/pipeline/simple/simple.cpp | 19 +++++++++++++++---- src/libcamera/v4l2_device.cpp | 16 ++++------------ 9 files changed, 73 insertions(+), 35 deletions(-)