@@ -686,6 +686,9 @@ int PipelineHandlerBase::start(Camera *camera, const ControlList *controls)
return ret;
}
+ /* A good moment to add an initial clock sample. */
+ data->wallClockRecovery_.addSample();
+
/*
* Reset the delayed controls with the gain and exposure values set by
* the IPA.
@@ -1510,6 +1513,8 @@ void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request
{
request->metadata().set(controls::SensorTimestamp,
bufferControls.get(controls::SensorTimestamp).value_or(0));
+ request->metadata().set(controls::FrameWallClock,
+ bufferControls.get(controls::FrameWallClock).value_or(0));
if (cropParams_.size()) {
std::vector<Rectangle> crops;
@@ -20,6 +20,7 @@
#include "libcamera/internal/bayer_format.h"
#include "libcamera/internal/camera.h"
#include "libcamera/internal/camera_sensor.h"
+#include "libcamera/internal/clock_recovery.h"
#include "libcamera/internal/framebuffer.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/media_object.h"
@@ -177,6 +178,8 @@ public:
Config config_;
+ ClockRecovery wallClockRecovery_;
+
protected:
void fillRequestMetadata(const ControlList &bufferControls,
Request *request);
@@ -781,9 +781,15 @@ void Vc4CameraData::unicamBufferDequeue(FrameBuffer *buffer)
auto [ctrl, delayContext] = delayedCtrls_->get(buffer->metadata().sequence);
/*
* Add the frame timestamp to the ControlList for the IPA to use
- * as it does not receive the FrameBuffer object.
+ * as it does not receive the FrameBuffer object. Also derive a
+ * corresponding wallclock value.
*/
- ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp);
+ wallClockRecovery_.addSample();
+ uint64_t sensorTimestamp = buffer->metadata().timestamp;
+ uint64_t wallClockTimestamp = wallClockRecovery_.getOutput(sensorTimestamp / 1000);
+
+ ctrl.set(controls::SensorTimestamp, sensorTimestamp);
+ ctrl.set(controls::FrameWallClock, wallClockTimestamp);
bayerQueue_.push({ buffer, std::move(ctrl), delayContext });
} else {
embeddedQueue_.push(buffer);