From ccfe0a1af77c3d13e81a913b25206d6a4a4747e4 Mon Sep 17 00:00:00 2001 From: Rishikesh Donadkar Date: Thu, 15 Sep 2022 17:17:34 +0530 Subject: gstreamer: Provide framerate support for libcamerasrc Control the framerate by passing the controls::FrameDurationLimits during Camera::start(). Framerate in gstreamer is expressed as GST_TYPE_FRACTION so we maximise on maintaining it as a fraction throughout and only do arithematic computations as and when required (to compute frame-duration and vice-versa). To weed out abritrary framerate as input, place the clamping via the controls::FrameDurationLimits provided after camera::configure() phase. This is handled by a helper function gst_libcamera_clamp_and_set_frameduration(). Set the bound checked framerate (done in the above mentioned helper) into the caps and pass the ControlList containing the frame-duration to Camera::start(ctrls). Signed-off-by: Rishikesh Donadkar Signed-off-by: Umang Jain Tested-by: Umang Jain Reviewed-by: Kieran Bingham Reviewed-by: Umang Jain --- src/gstreamer/gstlibcamerasrc.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/gstreamer/gstlibcamerasrc.cpp') diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 60032236..8d97d7c2 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -131,6 +131,7 @@ struct GstLibcameraSrcState { std::queue> completedRequests_ LIBCAMERA_TSA_GUARDED_BY(lock_); + ControlList initControls_; guint group_id_; int queueRequest(); @@ -462,6 +463,8 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, GstFlowReturn flow_ret = GST_FLOW_OK; gint ret; + g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps"); + GST_DEBUG_OBJECT(self, "Streaming thread has started"); gint stream_id_num = 0; @@ -504,6 +507,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, /* Fixate caps and configure the stream. */ caps = gst_caps_make_writable(caps); gst_libcamera_configure_stream_from_caps(stream_cfg, caps); + gst_libcamera_get_framerate_from_caps(caps, element_caps); } if (flow_ret != GST_FLOW_OK) @@ -525,6 +529,10 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, goto done; } + /* Check frame duration bounds within controls::FrameDurationLimits */ + gst_libcamera_clamp_and_set_frameduration(state->initControls_, + state->cam_->controls(), element_caps); + /* * Regardless if it has been modified, create clean caps and push the * caps event. Downstream will decide if the caps are acceptable. @@ -534,6 +542,8 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, const StreamConfiguration &stream_cfg = state->config_->at(i); g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg); + gst_libcamera_framerate_to_caps(caps, element_caps); + if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps))) { flow_ret = GST_FLOW_NOT_NEGOTIATED; break; @@ -567,7 +577,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, gst_flow_combiner_add_pad(self->flow_combiner, srcpad); } - ret = state->cam_->start(); + ret = state->cam_->start(&state->initControls_); if (ret) { GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, ("Failed to start the camera: %s", g_strerror(-ret)), @@ -577,6 +587,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, } done: + state->initControls_.clear(); switch (flow_ret) { case GST_FLOW_NOT_NEGOTIATED: GST_ELEMENT_FLOW_ERROR(self, flow_ret); -- cgit v1.2.1