aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--drivers/media/v4l2-core/v4l2-common.c30
-rw-r--r--include/media/v4l2-common.h34
2 files changed, 64 insertions, 0 deletions
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 96c1b31de9e3..9b65529dfaf6 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -383,6 +383,36 @@ v4l2_find_nearest_format(const struct v4l2_frmsize_discrete *sizes,
}
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;
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index f3aa1d728c0b..38947dc42ab6 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -333,6 +333,40 @@ v4l2_find_nearest_format(const struct v4l2_frmsize_discrete *sizes,
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);
+
+/**
* v4l2_get_timestamp - helper routine to get a timestamp to be used when
* filling streaming metadata. Internally, it uses ktime_get_ts(),
* which is the recommended way to get it.