v4l2object: Add function to get crop regions from device
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>
Wed, 13 Oct 2021 08:33:12 +0000 (17:33 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 11 Mar 2022 15:02:08 +0000 (15:02 +0000)
Get the current crop bounding region from the V4L2 device so
that it can be provided to applications and used to validate
crop settings. Also make the default crop region available so
that it can be used to reset the crop when appropriate.

Uses the selection API when available with fallback to the crop
API for older kernels.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1089>

subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.h

index 824049d..5644648 100644 (file)
@@ -4415,6 +4415,60 @@ gst_v4l2_object_setup_padding (GstV4l2Object * obj)
   return gst_v4l2_object_set_crop (obj, &crop);
 }
 
+static gboolean
+gst_v4l2_object_get_crop_rect (GstV4l2Object * obj, guint target,
+    struct v4l2_rect *result)
+{
+  struct v4l2_rect *res_rect;
+
+  struct v4l2_selection sel = { 0 };
+  struct v4l2_cropcap cropcap = { 0 };
+
+  GST_V4L2_CHECK_OPEN (obj);
+
+  if (target != V4L2_SEL_TGT_CROP_BOUNDS && target != V4L2_SEL_TGT_CROP_DEFAULT)
+    return FALSE;
+
+  sel.type = obj->type;
+  sel.target = target;
+
+  res_rect = &sel.r;
+
+  if (obj->ioctl (obj->video_fd, VIDIOC_G_SELECTION, &sel) < 0) {
+    if (errno != ENOTTY) {
+      GST_WARNING_OBJECT (obj->dbg_obj,
+          "Failed to get default crop rectangle with VIDIOC_G_SELECTION: %s",
+          g_strerror (errno));
+      return FALSE;
+    } else {
+      if (obj->ioctl (obj->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) {
+        GST_WARNING_OBJECT (obj->dbg_obj, "VIDIOC_CROPCAP failed");
+        return FALSE;
+      }
+      if (target == V4L2_SEL_TGT_CROP_BOUNDS)
+        res_rect = &cropcap.bounds;
+      else if (target == V4L2_SEL_TGT_CROP_DEFAULT)
+        res_rect = &cropcap.defrect;
+    }
+  }
+
+  *result = *res_rect;
+  return TRUE;
+}
+
+gboolean
+gst_v4l2_object_get_crop_bounds (GstV4l2Object * obj, struct v4l2_rect * result)
+{
+  return gst_v4l2_object_get_crop_rect (obj, V4L2_SEL_TGT_CROP_BOUNDS, result);
+}
+
+gboolean
+gst_v4l2_object_get_crop_default (GstV4l2Object * obj,
+    struct v4l2_rect * result)
+{
+  return gst_v4l2_object_get_crop_rect (obj, V4L2_SEL_TGT_CROP_DEFAULT, result);
+}
+
 gboolean
 gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps)
 {
index 4b75afd..64245da 100644 (file)
@@ -315,6 +315,8 @@ GstStructure * gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
 
 /* crop / compose */
 gboolean     gst_v4l2_object_set_crop (GstV4l2Object * obj, struct v4l2_rect *result);
+gboolean     gst_v4l2_object_get_crop_bounds (GstV4l2Object * obj, struct v4l2_rect *bounds);
+gboolean     gst_v4l2_object_get_crop_default (GstV4l2Object * obj, struct v4l2_rect *bounds);
 
 /* TODO Move to proper namespace */
 /* open/close the device */