[libcamera-devel] [PATCH] gstreamer: src: Send image-orientation tag

Robert Mader robert.mader at collabora.com
Wed Jun 14 18:21:53 CEST 2023


Matching the validated Transform of the configuration, if the transform
is not the Identity. As we currently always request a configuration with
`Identity` transform, this can be the case if camera has a rotation
property (90/180/270 degree) and the sensor can't do rotation in
question. Sending the orientation-tag allows downstream elements to
compensate accordingly.

This matches current pipewiresrc behavior and can be tested with e.g.:
gst-launch-1.0 libcamerasrc ! videoconvert ! videoflip video-direction=auto ! gtksink

Signed-off-by: Robert Mader <robert.mader at collabora.com>
---
 src/gstreamer/gstlibcamera-utils.cpp | 24 ++++++++++++++++++++++++
 src/gstreamer/gstlibcamera-utils.h   |  3 +++
 src/gstreamer/gstlibcamerasrc.cpp    | 11 +++++++++++
 3 files changed, 38 insertions(+)

diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
index 750ec351..3bfbc354 100644
--- a/src/gstreamer/gstlibcamera-utils.cpp
+++ b/src/gstreamer/gstlibcamera-utils.cpp
@@ -553,3 +553,27 @@ gst_libcamera_get_camera_manager(int &ret)
 
 	return cm;
 }
+
+const char *
+gst_libcamera_transform_to_tag_string(libcamera::Transform transform)
+{
+	switch (transform) {
+	case Transform::Rot90:
+		return "rotate-90";
+	case Transform::Rot180:
+		return "rotate-180";
+	case Transform::Rot270:
+		return "rotate-270";
+	case Transform::HFlip:
+		return "flip-rotate-0";
+	case Transform::VFlip:
+		return "flip-rotate-180";
+	case Transform::Transpose:
+		return "flip-rotate-270";
+	case Transform::Rot180Transpose:
+		return "flip-rotate-90";
+	case Transform::Identity:
+	default:
+		return "rotate-0";
+	}
+}
diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h
index fd304a8b..499533c4 100644
--- a/src/gstreamer/gstlibcamera-utils.h
+++ b/src/gstreamer/gstlibcamera-utils.h
@@ -11,6 +11,7 @@
 #include <libcamera/camera_manager.h>
 #include <libcamera/controls.h>
 #include <libcamera/stream.h>
+#include <libcamera/transform.h>
 
 #include <gst/gst.h>
 #include <gst/video/video.h>
@@ -30,6 +31,8 @@ gboolean gst_task_resume(GstTask *task);
 #endif
 std::shared_ptr<libcamera::CameraManager> gst_libcamera_get_camera_manager(int &ret);
 
+const char *gst_libcamera_transform_to_tag_string(libcamera::Transform transform);
+
 /**
  * \class GLibLocker
  * \brief A simple scoped mutex locker for GMutex
diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index a10cbd4f..b41f52d7 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -461,6 +461,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
 	GLibRecLocker lock(&self->stream_lock);
 	GstLibcameraSrcState *state = self->state;
 	GstFlowReturn flow_ret = GST_FLOW_OK;
+	const char *transform_tag;
 	gint ret;
 
 	g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps");
@@ -519,6 +520,16 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
 		goto done;
 	}
 
+	transform_tag = gst_libcamera_transform_to_tag_string(state->config_->transform);
+	for (gsize i = 0; i < state->srcpads_.size(); i++) {
+		GstPad *srcpad = state->srcpads_[i];
+		GstEvent *tag_event;
+
+		tag_event = gst_event_new_tag(gst_tag_list_new(GST_TAG_IMAGE_ORIENTATION,
+							       transform_tag, NULL));
+		gst_pad_push_event(srcpad, tag_event);
+	}
+
 	ret = state->cam_->configure(state->config_.get());
 	if (ret) {
 		GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS,
-- 
2.41.0



More information about the libcamera-devel mailing list