[libcamera-devel,RFC,4/6] pipeline: simple: Propagate frame interval through pipeline
diff mbox series

Message ID 20210316155211.6679-5-m.cichy@pengutronix.de
State Superseded
Headers show
Series
  • Add propagation of sensor frame interval
Related show

Commit Message

Marian Cichy March 16, 2021, 3:52 p.m. UTC
By propagating the frame interval from the sensor to the camera
interface, userspace applications can query the frame interval there.
This is useful for example with the gstreamer libcamerasrc, which can
integrate this information into the Gstreamer pipeline, which is a
valuable information for other elements.

Signed-off-by: Marian Cichy <m.cichy@pengutronix.de>
---
 src/libcamera/pipeline/simple/simple.cpp | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index d7128156..296412e2 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -182,6 +182,7 @@  public:
 	std::vector<std::unique_ptr<FrameBuffer>> converterBuffers_;
 	bool useConverter_;
 	std::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_;
+	Fraction frameInterval_;
 };
 
 class SimpleCameraConfiguration : public CameraConfiguration
@@ -458,6 +459,7 @@  int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format,
 				   V4L2Subdevice::Whence whence)
 {
 	SimplePipelineHandler *pipe = static_cast<SimplePipelineHandler *>(pipe_);
+	Fraction frameInterval;
 	int ret;
 
 	/*
@@ -478,6 +480,14 @@  int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format,
 			ret = subdev->getFormat(source->index(), format, whence);
 			if (ret < 0)
 				return ret;
+		} else {
+			V4L2Subdevice *subdev = pipe->subdev(source->entity());
+			ret = subdev->getFrameInterval(source->index(), &frameInterval);
+			if (ret < 0)
+				LOG(SimplePipeline, Debug) << "Getting frame interval from sensor failed";
+			else
+				LOG(SimplePipeline, Debug) << "Sensor frame interval: "
+							  << frameInterval.toString();
 		}
 
 		if (sink->entity()->function() != MEDIA_ENT_F_IO_V4L) {
@@ -488,6 +498,18 @@  int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format,
 			if (ret < 0)
 				return ret;
 
+			/* set frameinterval on all subdevs if we got one from the sensor */
+			if (frameInterval.numerator != 0 && frameInterval.denominator != 0) {
+				ret = subdev->setFrameInterval(sink->index(), &frameInterval);
+				if (ret == 0) {
+					LOG(SimplePipeline, Debug) << "Set frame interval: "
+								  << frameInterval.toString();
+					/* Always remember the last frame interval we successfully
+					 * set, as this determines the final frame interval at the end */
+					frameInterval_ = frameInterval;
+				}
+			}
+
 			if (format->mbus_code != sourceFormat.mbus_code ||
 			    format->size != sourceFormat.size) {
 				LOG(SimplePipeline, Debug)
@@ -668,6 +690,7 @@  CameraConfiguration *SimplePipelineHandler::generateConfiguration(Camera *camera
 		StreamConfiguration cfg{ StreamFormats{ formats } };
 		cfg.pixelFormat = formats.begin()->first;
 		cfg.size = formats.begin()->second[0].max;
+		cfg.frameInterval = data->frameInterval_;
 
 		config->addConfiguration(cfg);
 	}