[libcamera-devel] [PATCH 2/2] gstreamer: src: Add transform property

Nicolas Dufresne nicolas at ndufresne.ca
Tue Jun 13 16:39:33 CEST 2023


Le mardi 13 juin 2023 à 12:34 +0200, Robert Mader via libcamera-devel a écrit :
> This allows users to request a transform using the Gstreamer
> equivalent. If the combined transform of the requested one and a
> possible rotation from the camera properties is not fully supported by
> the sensor, the remaining transform will be passed down to downstream
> elements as tag.
> 
> The later is common for 90/270 degree rotations. Thus, a side effect of
> this feature is that libcamerasrc now behaves similar to pipewiresrc in
> regards to rotated cameras in e.g. phones, allowing apps to compensate
> accordingly.
> 
> Signed-off-by: Robert Mader <robert.mader at collabora.com>
> ---
>  src/gstreamer/gstlibcamera-utils.cpp | 72 ++++++++++++++++++++++++++++
>  src/gstreamer/gstlibcamera-utils.h   |  5 ++
>  src/gstreamer/gstlibcamerasrc.cpp    | 41 +++++++++++++++-
>  3 files changed, 117 insertions(+), 1 deletion(-)
> 
> diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
> index 750ec351..43ce75cb 100644
> --- a/src/gstreamer/gstlibcamera-utils.cpp
> +++ b/src/gstreamer/gstlibcamera-utils.cpp
> @@ -553,3 +553,75 @@ gst_libcamera_get_camera_manager(int &ret)
>  
>  	return cm;
>  }
> +
> +libcamera::Transform
> +gst_libcamera_orientation_to_transform(GstVideoOrientationMethod orientation)
> +{
> +	switch (orientation) {
> +	case GST_VIDEO_ORIENTATION_90R:
> +		return Transform::Rot90;
> +	case GST_VIDEO_ORIENTATION_180:
> +		return Transform::Rot180;
> +	case GST_VIDEO_ORIENTATION_90L:
> +		return Transform::Rot270;
> +	case GST_VIDEO_ORIENTATION_HORIZ:
> +		return Transform::HFlip;
> +	case GST_VIDEO_ORIENTATION_VERT:
> +		return Transform::VFlip;
> +	case GST_VIDEO_ORIENTATION_UL_LR:
> +		return Transform::Transpose;
> +	case GST_VIDEO_ORIENTATION_UR_LL:
> +		return Transform::Rot180Transpose;
> +	case GST_VIDEO_ORIENTATION_IDENTITY:
> +	default:
> +		return Transform::Identity;
> +	}
> +}
> +
> +GstVideoOrientationMethod
> +gst_libcamera_transform_to_orientation(libcamera::Transform transform)
> +{
> +	switch (transform) {
> +	case Transform::Rot90:
> +		return GST_VIDEO_ORIENTATION_90R;
> +	case Transform::Rot180:
> +		return GST_VIDEO_ORIENTATION_180;
> +	case Transform::Rot270:
> +		return GST_VIDEO_ORIENTATION_90L;
> +	case Transform::HFlip:
> +		return GST_VIDEO_ORIENTATION_HORIZ;
> +	case Transform::VFlip:
> +		return GST_VIDEO_ORIENTATION_VERT;
> +	case Transform::Transpose:
> +		return GST_VIDEO_ORIENTATION_UL_LR;
> +	case Transform::Rot180Transpose:
> +		return GST_VIDEO_ORIENTATION_UR_LL;
> +	case Transform::Identity:
> +	default:
> +		return GST_VIDEO_ORIENTATION_IDENTITY;
> +	}
> +}
> +
> +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..84d26c47 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,10 @@ gboolean gst_task_resume(GstTask *task);
>  #endif
>  std::shared_ptr<libcamera::CameraManager> gst_libcamera_get_camera_manager(int &ret);
>  
> +libcamera::Transform gst_libcamera_orientation_to_transform(GstVideoOrientationMethod orientation);
> +GstVideoOrientationMethod gst_libcamera_transform_to_orientation(libcamera::Transform transform);
> +const char *gst_libcamera_transform_to_tag_string(libcamera::Transform transform);

nit: Just to follow the style, I'd been adding empty line between each
declaration to ease the readability. The style checker didn't allow to indent it
further though.

> +
>  /**
>   * \class GLibLocker
>   * \brief A simple scoped mutex locker for GMutex
> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> index 721b35c2..9d9437d0 100644
> --- a/src/gstreamer/gstlibcamerasrc.cpp
> +++ b/src/gstreamer/gstlibcamerasrc.cpp
> @@ -147,6 +147,8 @@ struct _GstLibcameraSrc {
>  
>  	gchar *camera_name;
>  
> +	GstVideoOrientationMethod transform;
> +
>  	GstLibcameraSrcState *state;
>  	GstLibcameraAllocator *allocator;
>  	GstFlowCombiner *flow_combiner;
> @@ -154,7 +156,9 @@ struct _GstLibcameraSrc {
>  
>  enum {
>  	PROP_0,
> -	PROP_CAMERA_NAME
> +	PROP_CAMERA_NAME,
> +	PROP_TRANSFORM,
> +	PROP_LAST
>  };
>  
>  G_DEFINE_TYPE_WITH_CODE(GstLibcameraSrc, gst_libcamera_src, GST_TYPE_ELEMENT,
> @@ -461,6 +465,8 @@ 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;
> +	libcamera::Transform tag_transform;
> +	const char* tag_string;
>  	gint ret;
>  
>  	g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps");
> @@ -513,12 +519,27 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
>  	if (flow_ret != GST_FLOW_OK)
>  		goto done;
>  
> +	state->config_->transform =
> +		gst_libcamera_orientation_to_transform (self->transform);
> +
>  	/* Validate the configuration. */
>  	if (state->config_->validate() == CameraConfiguration::Invalid) {
>  		flow_ret = GST_FLOW_NOT_NEGOTIATED;
>  		goto done;
>  	}
>  
> +	tag_transform = (gst_libcamera_orientation_to_transform (self->transform) ^
> +			 state->config_->transform);
> +	tag_string = gst_libcamera_transform_to_tag_string(tag_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,
> +							       tag_string, NULL));
> +		gst_pad_push_event (srcpad, tag_event);
> +	}
> +
>  	ret = state->cam_->configure(state->config_.get());
>  	if (ret) {
>  		GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS,
> @@ -659,6 +680,11 @@ gst_libcamera_src_set_property(GObject *object, guint prop_id,
>  		g_free(self->camera_name);
>  		self->camera_name = g_value_dup_string(value);
>  		break;
> +	case PROP_TRANSFORM:
> +		self->transform =
> +			static_cast<GstVideoOrientationMethod>(
> +				g_value_get_enum(value));
> +		break;
>  	default:
>  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
>  		break;
> @@ -676,6 +702,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,
>  	case PROP_CAMERA_NAME:
>  		g_value_set_string(value, self->camera_name);
>  		break;
> +        case PROP_TRANSFORM:
> +                g_value_set_enum(value, self->transform);
> +                break;
>  	default:
>  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
>  		break;
> @@ -845,4 +874,14 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
>  						  | G_PARAM_CONSTRUCT
>  						  | G_PARAM_READWRITE
>  						  | G_PARAM_STATIC_STRINGS)));
> +
> +	g_object_class_install_property (object_class, PROP_TRANSFORM,
> +		g_param_spec_enum ("transform", "Transform",

Shouldn't this be "video-direction" and this patch should implement the
GstVideoDirection interface ? Every other element in gstreamer do that.

> +				   "Request a transform (rotation and/or flip).",
> +				   GST_TYPE_VIDEO_ORIENTATION_METHOD,
> +				   GST_VIDEO_ORIENTATION_IDENTITY,
> +				   (GParamFlags)(GST_PARAM_MUTABLE_READY
> +						 | G_PARAM_CONSTRUCT
> +						 | G_PARAM_READWRITE
> +						 | G_PARAM_STATIC_STRINGS)));
>  }



More information about the libcamera-devel mailing list