[libcamera-devel,v6] gstreamer: Added virtual functions needed to support request pads
diff mbox series

Message ID 20210618183218.449146-1-vedantparanjape160201@gmail.com
State Accepted
Commit 53a0d80af0f9983d6bc0d54b0e85403a08721488
Headers show
Series
  • [libcamera-devel,v6] gstreamer: Added virtual functions needed to support request pads
Related show

Commit Message

Vedant Paranjape June 18, 2021, 6:32 p.m. UTC
This patch adds support for using request pads in libcamerasrc Gst
Element. It allows a user to request multiple streams if the platform
supports multistream output using libcamera.

This was tested on Raspberry Pi 4B+ with a camera connected to CSI port.
It can be tested by running the following command

gst-launch-1.0 libcamerasrc camera-name="<camera-name-here>" name=src src.src ! queue ! videoconvert ! autovideosink src.src_0 ! queue ! videoconvert ! autovideosink

Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com>
---
 src/gstreamer/gstlibcamerasrc.cpp | 53 ++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

Comments

Nicolas Dufresne June 23, 2021, 8:36 p.m. UTC | #1
Le samedi 19 juin 2021 à 00:02 +0530, Vedant Paranjape a écrit :
> This patch adds support for using request pads in libcamerasrc Gst
> Element. It allows a user to request multiple streams if the platform
> supports multistream output using libcamera.
> 
> This was tested on Raspberry Pi 4B+ with a camera connected to CSI port.
> It can be tested by running the following command
> 
> gst-launch-1.0 libcamerasrc camera-name="<camera-name-here>" name=src src.src ! queue ! videoconvert ! autovideosink src.src_0 ! queue ! videoconvert ! autovideosink
> 
> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com>

Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>

> ---
>  src/gstreamer/gstlibcamerasrc.cpp | 53 ++++++++++++++++++++++++++++++-
>  1 file changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> index ccc61590..ea53c2b5 100644
> --- a/src/gstreamer/gstlibcamerasrc.cpp
> +++ b/src/gstreamer/gstlibcamerasrc.cpp
> @@ -361,10 +361,12 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
>  	GST_DEBUG_OBJECT(self, "Streaming thread has started");
>  
>  	guint group_id = gst_util_group_id_next();
> +	gint stream_id_num = 0;
>  	StreamRoles roles;
>  	for (GstPad *srcpad : state->srcpads_) {
>  		/* Create stream-id and push stream-start. */
> -		g_autofree gchar *stream_id = gst_pad_create_stream_id(srcpad, GST_ELEMENT(self), nullptr);
> +		g_autofree gchar *stream_id_intermediate = g_strdup_printf("%i%i", group_id, stream_id_num++);
> +		g_autofree gchar *stream_id = gst_pad_create_stream_id(srcpad, GST_ELEMENT(self), stream_id_intermediate);
>  		GstEvent *event = gst_event_new_stream_start(stream_id);
>  		gst_event_set_group_id(event, group_id);
>  		gst_pad_push_event(srcpad, event);
> @@ -640,6 +642,53 @@ gst_libcamera_src_init(GstLibcameraSrc *self)
>  	self->state = state;
>  }
>  
> +static GstPad *
> +gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,
> +				  const gchar *name, [[maybe_unused]] const GstCaps *caps)
> +{
> +	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
> +	g_autoptr(GstPad) pad = NULL;
> +
> +	GST_DEBUG_OBJECT(self, "new request pad created");
> +
> +	pad = gst_pad_new_from_template(templ, name);
> +	g_object_ref_sink(pad);
> +
> +	if (gst_element_add_pad(element, pad)) {
> +		GLibLocker lock(GST_OBJECT(self));
> +		self->state->srcpads_.push_back(reinterpret_cast<GstPad *>(g_object_ref(pad)));
> +	} else {
> +		GST_ELEMENT_ERROR(element, STREAM, FAILED,
> +				  ("Internal data stream error."),
> +				  ("Could not add pad to element"));
> +		return NULL;
> +	}
> +
> +	return reinterpret_cast<GstPad *>(g_steal_pointer(&pad));
> +}
> +
> +static void
> +gst_libcamera_src_release_pad(GstElement *element, GstPad *pad)
> +{
> +	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
> +
> +	GST_DEBUG_OBJECT(self, "Pad %" GST_PTR_FORMAT " being released", pad);
> +
> +	{
> +		GLibLocker lock(GST_OBJECT(self));
> +		std::vector<GstPad *> &pads = self->state->srcpads_;
> +		auto begin_iterator = pads.begin();
> +		auto end_iterator = pads.end();
> +		auto pad_iterator = std::find(begin_iterator, end_iterator, pad);
> +
> +		if (pad_iterator != end_iterator) {
> +			g_object_unref(*pad_iterator);
> +			pads.erase(pad_iterator);
> +		}
> +	}
> +	gst_element_remove_pad(element, pad);
> +}
> +
>  static void
>  gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
>  {
> @@ -650,6 +699,8 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
>  	object_class->get_property = gst_libcamera_src_get_property;
>  	object_class->finalize = gst_libcamera_src_finalize;
>  
> +	element_class->request_new_pad = gst_libcamera_src_request_new_pad;
> +	element_class->release_pad = gst_libcamera_src_release_pad;
>  	element_class->change_state = gst_libcamera_src_change_state;
>  
>  	gst_element_class_set_metadata(element_class,
Paul Elder June 25, 2021, 11:01 a.m. UTC | #2
Hi Vedant,

On Sat, Jun 19, 2021 at 12:02:18AM +0530, Vedant Paranjape wrote:
> This patch adds support for using request pads in libcamerasrc Gst
> Element. It allows a user to request multiple streams if the platform
> supports multistream output using libcamera.
> 
> This was tested on Raspberry Pi 4B+ with a camera connected to CSI port.
> It can be tested by running the following command
> 
> gst-launch-1.0 libcamerasrc camera-name="<camera-name-here>" name=src src.src ! queue ! videoconvert ! autovideosink src.src_0 ! queue ! videoconvert ! autovideosink
> 
> Signed-off-by: Vedant Paranjape <vedantparanjape160201@gmail.com>

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

> ---
>  src/gstreamer/gstlibcamerasrc.cpp | 53 ++++++++++++++++++++++++++++++-
>  1 file changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> index ccc61590..ea53c2b5 100644
> --- a/src/gstreamer/gstlibcamerasrc.cpp
> +++ b/src/gstreamer/gstlibcamerasrc.cpp
> @@ -361,10 +361,12 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
>  	GST_DEBUG_OBJECT(self, "Streaming thread has started");
>  
>  	guint group_id = gst_util_group_id_next();
> +	gint stream_id_num = 0;
>  	StreamRoles roles;
>  	for (GstPad *srcpad : state->srcpads_) {
>  		/* Create stream-id and push stream-start. */
> -		g_autofree gchar *stream_id = gst_pad_create_stream_id(srcpad, GST_ELEMENT(self), nullptr);
> +		g_autofree gchar *stream_id_intermediate = g_strdup_printf("%i%i", group_id, stream_id_num++);
> +		g_autofree gchar *stream_id = gst_pad_create_stream_id(srcpad, GST_ELEMENT(self), stream_id_intermediate);
>  		GstEvent *event = gst_event_new_stream_start(stream_id);
>  		gst_event_set_group_id(event, group_id);
>  		gst_pad_push_event(srcpad, event);
> @@ -640,6 +642,53 @@ gst_libcamera_src_init(GstLibcameraSrc *self)
>  	self->state = state;
>  }
>  
> +static GstPad *
> +gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,
> +				  const gchar *name, [[maybe_unused]] const GstCaps *caps)
> +{
> +	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
> +	g_autoptr(GstPad) pad = NULL;
> +
> +	GST_DEBUG_OBJECT(self, "new request pad created");
> +
> +	pad = gst_pad_new_from_template(templ, name);
> +	g_object_ref_sink(pad);
> +
> +	if (gst_element_add_pad(element, pad)) {
> +		GLibLocker lock(GST_OBJECT(self));
> +		self->state->srcpads_.push_back(reinterpret_cast<GstPad *>(g_object_ref(pad)));
> +	} else {
> +		GST_ELEMENT_ERROR(element, STREAM, FAILED,
> +				  ("Internal data stream error."),
> +				  ("Could not add pad to element"));
> +		return NULL;
> +	}
> +
> +	return reinterpret_cast<GstPad *>(g_steal_pointer(&pad));
> +}
> +
> +static void
> +gst_libcamera_src_release_pad(GstElement *element, GstPad *pad)
> +{
> +	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
> +
> +	GST_DEBUG_OBJECT(self, "Pad %" GST_PTR_FORMAT " being released", pad);
> +
> +	{
> +		GLibLocker lock(GST_OBJECT(self));
> +		std::vector<GstPad *> &pads = self->state->srcpads_;
> +		auto begin_iterator = pads.begin();
> +		auto end_iterator = pads.end();
> +		auto pad_iterator = std::find(begin_iterator, end_iterator, pad);
> +
> +		if (pad_iterator != end_iterator) {
> +			g_object_unref(*pad_iterator);
> +			pads.erase(pad_iterator);
> +		}
> +	}
> +	gst_element_remove_pad(element, pad);
> +}
> +
>  static void
>  gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
>  {
> @@ -650,6 +699,8 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
>  	object_class->get_property = gst_libcamera_src_get_property;
>  	object_class->finalize = gst_libcamera_src_finalize;
>  
> +	element_class->request_new_pad = gst_libcamera_src_request_new_pad;
> +	element_class->release_pad = gst_libcamera_src_release_pad;
>  	element_class->change_state = gst_libcamera_src_change_state;
>  
>  	gst_element_class_set_metadata(element_class,
> -- 
> 2.25.1
>

Patch
diff mbox series

diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index ccc61590..ea53c2b5 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -361,10 +361,12 @@  gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
 	GST_DEBUG_OBJECT(self, "Streaming thread has started");
 
 	guint group_id = gst_util_group_id_next();
+	gint stream_id_num = 0;
 	StreamRoles roles;
 	for (GstPad *srcpad : state->srcpads_) {
 		/* Create stream-id and push stream-start. */
-		g_autofree gchar *stream_id = gst_pad_create_stream_id(srcpad, GST_ELEMENT(self), nullptr);
+		g_autofree gchar *stream_id_intermediate = g_strdup_printf("%i%i", group_id, stream_id_num++);
+		g_autofree gchar *stream_id = gst_pad_create_stream_id(srcpad, GST_ELEMENT(self), stream_id_intermediate);
 		GstEvent *event = gst_event_new_stream_start(stream_id);
 		gst_event_set_group_id(event, group_id);
 		gst_pad_push_event(srcpad, event);
@@ -640,6 +642,53 @@  gst_libcamera_src_init(GstLibcameraSrc *self)
 	self->state = state;
 }
 
+static GstPad *
+gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,
+				  const gchar *name, [[maybe_unused]] const GstCaps *caps)
+{
+	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
+	g_autoptr(GstPad) pad = NULL;
+
+	GST_DEBUG_OBJECT(self, "new request pad created");
+
+	pad = gst_pad_new_from_template(templ, name);
+	g_object_ref_sink(pad);
+
+	if (gst_element_add_pad(element, pad)) {
+		GLibLocker lock(GST_OBJECT(self));
+		self->state->srcpads_.push_back(reinterpret_cast<GstPad *>(g_object_ref(pad)));
+	} else {
+		GST_ELEMENT_ERROR(element, STREAM, FAILED,
+				  ("Internal data stream error."),
+				  ("Could not add pad to element"));
+		return NULL;
+	}
+
+	return reinterpret_cast<GstPad *>(g_steal_pointer(&pad));
+}
+
+static void
+gst_libcamera_src_release_pad(GstElement *element, GstPad *pad)
+{
+	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
+
+	GST_DEBUG_OBJECT(self, "Pad %" GST_PTR_FORMAT " being released", pad);
+
+	{
+		GLibLocker lock(GST_OBJECT(self));
+		std::vector<GstPad *> &pads = self->state->srcpads_;
+		auto begin_iterator = pads.begin();
+		auto end_iterator = pads.end();
+		auto pad_iterator = std::find(begin_iterator, end_iterator, pad);
+
+		if (pad_iterator != end_iterator) {
+			g_object_unref(*pad_iterator);
+			pads.erase(pad_iterator);
+		}
+	}
+	gst_element_remove_pad(element, pad);
+}
+
 static void
 gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
 {
@@ -650,6 +699,8 @@  gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
 	object_class->get_property = gst_libcamera_src_get_property;
 	object_class->finalize = gst_libcamera_src_finalize;
 
+	element_class->request_new_pad = gst_libcamera_src_request_new_pad;
+	element_class->release_pad = gst_libcamera_src_release_pad;
 	element_class->change_state = gst_libcamera_src_change_state;
 
 	gst_element_class_set_metadata(element_class,