summaryrefslogtreecommitdiff
path: root/src/gstreamer
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2020-01-20 16:52:14 -0500
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-03-07 01:57:45 +0200
commit1d8cbaf214199c55ba9c7210fa900001d59cc24c (patch)
treec0ffa59f587e85e6c7f50d7041fb3cf6774d36d2 /src/gstreamer
parent58feb69f8522892620825b691b4669e7c37e74b2 (diff)
gst: libcamerasrc: Add a task for the streaming thread
Use a GstTask as our internal streaming thread. Unlike GstBaseSrc, we will be running a streaming thread at the element level rather than per pad. This is needed to combine buffer request for multiple pads. Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/gstreamer')
-rw-r--r--src/gstreamer/gstlibcamerasrc.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index fd0eaf5a..35f75124 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -27,7 +27,11 @@ struct GstLibcameraSrcState {
struct _GstLibcameraSrc {
GstElement parent;
+
+ GRecMutex stream_lock;
+ GstTask *task;
GstPad *srcpad;
+
gchar *camera_name;
GstLibcameraSrcState *state;
@@ -114,6 +118,30 @@ gst_libcamera_src_open(GstLibcameraSrc *self)
}
static void
+gst_libcamera_src_task_run(gpointer user_data)
+{
+ GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data);
+
+ GST_DEBUG_OBJECT(self, "Streaming thread is now capturing");
+}
+
+static void
+gst_libcamera_src_task_enter(GstTask *task, GThread *thread, gpointer user_data)
+{
+ GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data);
+
+ GST_DEBUG_OBJECT(self, "Streaming thread has started");
+}
+
+static void
+gst_libcamera_src_task_leave(GstTask *task, GThread *thread, gpointer user_data)
+{
+ GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data);
+
+ GST_DEBUG_OBJECT(self, "Streaming thread is about to stop");
+}
+
+static void
gst_libcamera_src_close(GstLibcameraSrc *self)
{
GstLibcameraSrcState *state = self->state;
@@ -183,9 +211,24 @@ gst_libcamera_src_change_state(GstElement *element, GstStateChange transition)
return GST_STATE_CHANGE_FAILURE;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
+ /* This needs to be called after pads activation.*/
+ if (!gst_task_pause(self->task))
+ return GST_STATE_CHANGE_FAILURE;
+ ret = GST_STATE_CHANGE_NO_PREROLL;
+ break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
ret = GST_STATE_CHANGE_NO_PREROLL;
break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ /*
+ * \todo this might require some thread unblocking in the future
+ * if the streaming thread starts doing any kind of blocking
+ * operations. If this was the case, we would need to do so
+ * before pad deactivation, so before chaining to the parent
+ * change_state function.
+ */
+ gst_task_join(self->task);
+ break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_libcamera_src_close(self);
break;
@@ -202,6 +245,8 @@ gst_libcamera_src_finalize(GObject *object)
GObjectClass *klass = G_OBJECT_CLASS(gst_libcamera_src_parent_class);
GstLibcameraSrc *self = GST_LIBCAMERA_SRC(object);
+ g_rec_mutex_clear(&self->stream_lock);
+ g_clear_object(&self->task);
g_free(self->camera_name);
delete self->state;
@@ -214,6 +259,12 @@ gst_libcamera_src_init(GstLibcameraSrc *self)
GstLibcameraSrcState *state = new GstLibcameraSrcState();
GstPadTemplate *templ = gst_element_get_pad_template(GST_ELEMENT(self), "src");
+ g_rec_mutex_init(&self->stream_lock);
+ self->task = gst_task_new(gst_libcamera_src_task_run, self, nullptr);
+ gst_task_set_enter_callback(self->task, gst_libcamera_src_task_enter, self, nullptr);
+ gst_task_set_leave_callback(self->task, gst_libcamera_src_task_leave, self, nullptr);
+ gst_task_set_lock(self->task, &self->stream_lock);
+
self->srcpad = gst_pad_new_from_template(templ, "src");
gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
self->state = state;