]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
media: v4l: common: Add a function to obtain best size from a list
authorSakari Ailus <sakari.ailus@linux.intel.com>
Fri, 23 Feb 2018 09:50:14 +0000 (04:50 -0500)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 27 Sep 2018 06:20:48 +0000 (08:20 +0200)
Add a function (as well as a helper macro) to obtain the best size in a
list of device specific sizes. This helps writing drivers as well as
aligns interface behaviour across drivers.

The struct in which this information is contained in is typically specific
to the driver, therefore the existing function v4l2_find_nearest_format()
does not address the need.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Sam Bobrowicz <sam@elite-embedded.com>
drivers/media/v4l2-core/v4l2-common.c
include/media/v4l2-common.h

index a5ea1f51729103499c58f3b327ef24252561e526..425fc6af4dd3540fb171f3e7d76c8f453a6edb18 100644 (file)
@@ -396,6 +396,36 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
 }
 EXPORT_SYMBOL_GPL(v4l2_find_nearest_format);
 
+const void *
+__v4l2_find_nearest_size(const void *array, size_t array_size,
+                        size_t entry_size, size_t width_offset,
+                        size_t height_offset, s32 width, s32 height)
+{
+       u32 error, min_error = U32_MAX;
+       const void *best = NULL;
+       unsigned int i;
+
+       if (!array)
+               return NULL;
+
+       for (i = 0; i < array_size; i++, array += entry_size) {
+               const u32 *entry_width = array + width_offset;
+               const u32 *entry_height = array + height_offset;
+
+               error = abs(*entry_width - width) + abs(*entry_height - height);
+               if (error > min_error)
+                       continue;
+
+               min_error = error;
+               best = array;
+               if (!error)
+                       break;
+       }
+
+       return best;
+}
+EXPORT_SYMBOL_GPL(__v4l2_find_nearest_size);
+
 void v4l2_get_timestamp(struct timeval *tv)
 {
        struct timespec ts;
index aac8b7b6e6917c27547113398a8d98fe8fcbac63..6877ee41a5679e2f82afa4aaff627fa42e1c747c 100644 (file)
@@ -262,6 +262,40 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
                const struct v4l2_discrete_probe *probe,
                s32 width, s32 height);
 
+/**
+ * v4l2_find_nearest_size - Find the nearest size among a discrete
+ *     set of resolutions contained in an array of a driver specific struct.
+ *
+ * @array: a driver specific array of image sizes
+ * @array_size: the length of the driver specific array of image sizes
+ * @width_field: the name of the width field in the driver specific struct
+ * @height_field: the name of the height field in the driver specific struct
+ * @width: desired width.
+ * @height: desired height.
+ *
+ * Finds the closest resolution to minimize the width and height differences
+ * between what requested and the supported resolutions. The size of the width
+ * and height fields in the driver specific must equal to that of u32, i.e. four
+ * bytes.
+ *
+ * Returns the best match or NULL if the length of the array is zero.
+ */
+#define v4l2_find_nearest_size(array, array_size, width_field, height_field, \
+                              width, height)                           \
+       ({                                                              \
+               BUILD_BUG_ON(sizeof((array)->width_field) != sizeof(u32) || \
+                            sizeof((array)->height_field) != sizeof(u32)); \
+               (typeof(&(*(array))))__v4l2_find_nearest_size(          \
+                       (array), array_size, sizeof(*(array)),          \
+                       offsetof(typeof(*(array)), width_field),        \
+                       offsetof(typeof(*(array)), height_field),       \
+                       width, height);                                 \
+       })
+const void *
+__v4l2_find_nearest_size(const void *array, size_t array_size,
+                        size_t entry_size, size_t width_offset,
+                        size_t height_offset, s32 width, s32 height);
+
 void v4l2_get_timestamp(struct timeval *tv);
 
 #endif /* V4L2_COMMON_H_ */