From 7dc71fd6fef7a242d108d5c8cb7683aa9fd4511f Mon Sep 17 00:00:00 2001
From: Paul Elder <paul.elder@ideasonboard.com>
Date: Tue, 22 Nov 2022 10:54:55 +0000
Subject: test-source: add test source class

The test_source class is an implementation of the video_source class
that generates a test pattern in userspace to provide video. We have
some operations which are implemented as no-ops. To quiet the
compiler warnings this causes, flag their arguments as unused.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 include/uvcgadget/test-source.h |  20 ++++++
 lib/meson.build                 |   1 +
 lib/test-source.c               | 146 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+)
 create mode 100644 include/uvcgadget/test-source.h
 create mode 100644 lib/test-source.c

diff --git a/include/uvcgadget/test-source.h b/include/uvcgadget/test-source.h
new file mode 100644
index 0000000..994a128
--- /dev/null
+++ b/include/uvcgadget/test-source.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Test video source
+ *
+ * Copyright (C) 2018 Paul Elder
+ *
+ * Contact: Paul Elder <paul.elder@ideasonboard.com>
+ */
+#ifndef __TEST_VIDEO_SOURCE_H__
+#define __TEST_VIDEO_SOURCE_H__
+
+#include "video-source.h"
+
+struct events;
+struct video_source;
+
+struct video_source *test_video_source_create(void);
+void test_video_source_init(struct video_source *src, struct events *events);
+
+#endif /* __TEST_VIDEO_SOURCE_H__ */
diff --git a/lib/meson.build b/lib/meson.build
index 7db7519..2d9ad10 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -4,6 +4,7 @@ libuvcgadget_sources = files([
   'configfs.c',
   'events.c',
   'stream.c',
+  'test-source.c',
   'uvc.c',
   'v4l2.c',
   'v4l2-source.c',
diff --git a/lib/test-source.c b/lib/test-source.c
new file mode 100644
index 0000000..743d8b3
--- /dev/null
+++ b/lib/test-source.c
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Test video source
+ *
+ * Copyright (C) 2018 Paul Elder
+ *
+ * Contact: Paul Elder <paul.elder@ideasonboard.com>
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/videodev2.h>
+
+#include "events.h"
+#include "test-source.h"
+#include "tools.h"
+#include "video-buffers.h"
+
+#define BLACK   0x80108010
+#define BLUE    0x7620f020
+#define CYAN    0x10bc9abc
+#define GREEN   0x2aad1aad
+#define GREY    0x80b480b4
+#define MAGENTA 0xe64ed64e
+#define RED     0xf03f663f
+#define WHITE   0x80eb80eb
+#define YELLOW  0x8adb10db
+
+struct test_source {
+	struct video_source src;
+
+	unsigned int width;
+	unsigned int height;
+	unsigned int pixelformat;
+};
+
+#define to_test_source(s) container_of(s, struct test_source, src)
+
+static void test_source_destroy(struct video_source *s)
+{
+	struct test_source *src = to_test_source(s);
+
+	free(src);
+}
+
+static int test_source_set_format(struct video_source *s,
+				  struct v4l2_pix_format *fmt)
+{
+	struct test_source *src = to_test_source(s);
+
+	src->width = fmt->width;
+	src->height = fmt->height;
+	src->pixelformat = fmt->pixelformat;
+
+	if (src->pixelformat != v4l2_fourcc('Y', 'U', 'Y', 'V'))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int test_source_set_frame_rate(struct video_source *s __attribute__((unused)),
+				      unsigned int fps __attribute__((unused)))
+{
+	return 0;
+}
+
+static int test_source_free_buffers(struct video_source *s __attribute__((unused)))
+{
+	return 0;
+}
+
+static int test_source_stream_on(struct video_source *s __attribute__((unused)))
+{
+	return 0;
+}
+
+static int test_source_stream_off(struct video_source *s __attribute__((unused)))
+{
+	return 0;
+}
+
+static void test_source_fill_buffer(struct video_source *s,
+				    struct video_buffer *buf)
+{
+	struct test_source *src = to_test_source(s);
+	unsigned int bpl;
+	unsigned int i, j;
+	void *mem = buf->mem;
+
+	bpl = src->width * 2;
+	for (i = 0; i < src->height; ++i) {
+		for (j = 0; j < bpl; j += 4) {
+			if (j < bpl * 1 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = WHITE;
+			else if (j < bpl * 2 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = YELLOW;
+			else if (j < bpl * 3 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = CYAN;
+			else if (j < bpl * 4 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = GREEN;
+			else if (j < bpl * 5 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = MAGENTA;
+			else if (j < bpl * 6 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = RED;
+			else if (j < bpl * 7 / 8)
+				*(unsigned int *)(mem + i*bpl + j) = BLUE;
+			else
+				*(unsigned int *)(mem + i*bpl + j) = BLACK;
+		}
+	}
+
+	buf->bytesused = bpl * src->height;
+}
+
+static const struct video_source_ops test_source_ops = {
+	.destroy = test_source_destroy,
+	.set_format = test_source_set_format,
+	.set_frame_rate = test_source_set_frame_rate,
+	.free_buffers = test_source_free_buffers,
+	.stream_on = test_source_stream_on,
+	.stream_off = test_source_stream_off,
+	.queue_buffer = NULL,
+	.fill_buffer = test_source_fill_buffer,
+};
+
+struct video_source *test_video_source_create()
+{
+	struct test_source *src;
+
+	src = malloc(sizeof *src);
+	if (!src)
+		return NULL;
+
+	memset(src, 0, sizeof *src);
+	src->src.ops = &test_source_ops;
+
+	return &src->src;
+}
+
+void test_video_source_init(struct video_source *s, struct events *events)
+{
+	struct test_source *src = to_test_source(s);
+
+	src->src.events = events;
+}
-- 
cgit v1.2.3