summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-11-08 01:14:38 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-11-15 22:21:28 +0200
commitd767c84022559e55708f24a3a264853c0142135e (patch)
tree9b104f71819804d002039fab9be25340e90bc210
parent7d35c771c0480e1ca5942ba3c9cf09c1fde22f85 (diff)
libcamera: Move EventDispatcher to internal API
There's no user of the EventDispatcher (and the related EventNotifier and Timer classes) outside of libcamera. Move those classes to the internal API. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
-rw-r--r--include/libcamera/camera_manager.h4
-rw-r--r--include/libcamera/internal/event_dispatcher.h (renamed from include/libcamera/event_dispatcher.h)0
-rw-r--r--include/libcamera/internal/event_dispatcher_poll.h2
-rw-r--r--include/libcamera/internal/event_notifier.h (renamed from include/libcamera/event_notifier.h)0
-rw-r--r--include/libcamera/internal/meson.build3
-rw-r--r--include/libcamera/internal/timer.h (renamed from include/libcamera/timer.h)0
-rw-r--r--include/libcamera/meson.build3
-rw-r--r--src/libcamera/camera_manager.cpp44
-rw-r--r--src/libcamera/device_enumerator_udev.cpp3
-rw-r--r--src/libcamera/event_dispatcher.cpp2
-rw-r--r--src/libcamera/event_dispatcher_poll.cpp5
-rw-r--r--src/libcamera/event_notifier.cpp4
-rw-r--r--src/libcamera/ipc_unixsocket.cpp3
-rw-r--r--src/libcamera/pipeline/rkisp1/timeline.h3
-rw-r--r--src/libcamera/process.cpp3
-rw-r--r--src/libcamera/proxy/worker/ipa_proxy_linux_worker.cpp2
-rw-r--r--src/libcamera/thread.cpp3
-rw-r--r--src/libcamera/timer.cpp4
-rw-r--r--src/libcamera/v4l2_device.cpp3
-rw-r--r--src/libcamera/v4l2_videodevice.cpp2
-rw-r--r--test/camera/buffer_import.cpp5
-rw-r--r--test/camera/capture.cpp4
-rw-r--r--test/event-dispatcher.cpp5
-rw-r--r--test/event-thread.cpp5
-rw-r--r--test/event.cpp7
-rw-r--r--test/hotplug-cameras.cpp4
-rw-r--r--test/ipa/ipa_interface_test.cpp6
-rw-r--r--test/ipc/unixsocket.cpp5
-rw-r--r--test/log/log_process.cpp4
-rw-r--r--test/object-invoke.cpp2
-rw-r--r--test/process/process_test.cpp5
-rw-r--r--test/timer-thread.cpp5
-rw-r--r--test/timer.cpp5
-rw-r--r--test/v4l2_videodevice/buffer_sharing.cpp4
-rw-r--r--test/v4l2_videodevice/capture_async.cpp4
-rw-r--r--test/v4l2_videodevice/v4l2_m2mdevice.cpp4
36 files changed, 54 insertions, 113 deletions
diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h
index 6d5341c7..8c8830e7 100644
--- a/include/libcamera/camera_manager.h
+++ b/include/libcamera/camera_manager.h
@@ -19,7 +19,6 @@
namespace libcamera {
class Camera;
-class EventDispatcher;
class CameraManager : public Object, public Extensible
{
@@ -43,9 +42,6 @@ public:
static const std::string &version() { return version_; }
- void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
- EventDispatcher *eventDispatcher();
-
Signal<std::shared_ptr<Camera>> cameraAdded;
Signal<std::shared_ptr<Camera>> cameraRemoved;
diff --git a/include/libcamera/event_dispatcher.h b/include/libcamera/internal/event_dispatcher.h
index cb06bf20..cb06bf20 100644
--- a/include/libcamera/event_dispatcher.h
+++ b/include/libcamera/internal/event_dispatcher.h
diff --git a/include/libcamera/internal/event_dispatcher_poll.h b/include/libcamera/internal/event_dispatcher_poll.h
index 39d9be52..33de051d 100644
--- a/include/libcamera/internal/event_dispatcher_poll.h
+++ b/include/libcamera/internal/event_dispatcher_poll.h
@@ -11,7 +11,7 @@
#include <map>
#include <vector>
-#include <libcamera/event_dispatcher.h>
+#include "libcamera/internal/event_dispatcher.h"
struct pollfd;
diff --git a/include/libcamera/event_notifier.h b/include/libcamera/internal/event_notifier.h
index a37b02ee..a37b02ee 100644
--- a/include/libcamera/event_notifier.h
+++ b/include/libcamera/internal/event_notifier.h
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index 6500fe2a..7cde023f 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -18,7 +18,9 @@ libcamera_internal_headers = files([
'device_enumerator.h',
'device_enumerator_sysfs.h',
'device_enumerator_udev.h',
+ 'event_dispatcher.h',
'event_dispatcher_poll.h',
+ 'event_notifier.h',
'file.h',
'formats.h',
'ipa_context_wrapper.h',
@@ -36,6 +38,7 @@ libcamera_internal_headers = files([
'semaphore.h',
'sysfs.h',
'thread.h',
+ 'timer.h',
'utils.h',
'v4l2_controls.h',
'v4l2_device.h',
diff --git a/include/libcamera/timer.h b/include/libcamera/internal/timer.h
index f55fe3c0..f55fe3c0 100644
--- a/include/libcamera/timer.h
+++ b/include/libcamera/internal/timer.h
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index 0b891a8f..cf2935f1 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -6,8 +6,6 @@ libcamera_public_headers = files([
'camera.h',
'camera_manager.h',
'controls.h',
- 'event_dispatcher.h',
- 'event_notifier.h',
'extensible.h',
'file_descriptor.h',
'framebuffer_allocator.h',
@@ -19,7 +17,6 @@ libcamera_public_headers = files([
'signal.h',
'span.h',
'stream.h',
- 'timer.h',
'transform.h',
])
diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
index 427ea5da..67641a55 100644
--- a/src/libcamera/camera_manager.cpp
+++ b/src/libcamera/camera_manager.cpp
@@ -11,10 +11,8 @@
#include <map>
#include <libcamera/camera.h>
-#include <libcamera/event_dispatcher.h>
#include "libcamera/internal/device_enumerator.h"
-#include "libcamera/internal/event_dispatcher_poll.h"
#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/pipeline_handler.h"
@@ -244,12 +242,8 @@ void CameraManager::Private::removeCamera(Camera *camera)
* a time. Attempting to create a second instance without first deleting the
* existing instance results in undefined behaviour.
*
- * The manager is initially stopped, and shall be configured before being
- * started. In particular a custom event dispatcher shall be installed if
- * needed with CameraManager::setEventDispatcher().
- *
- * Once the camera manager is configured, it shall be started with start().
- * This will enumerate all the cameras present in the system, which can then be
+ * The manager is initially stopped, and shall be started with start(). This
+ * will enumerate all the cameras present in the system, which can then be
* listed with list() and retrieved with get().
*
* Cameras are shared through std::shared_ptr<>, ensuring that a camera will
@@ -477,38 +471,4 @@ void CameraManager::removeCamera(std::shared_ptr<Camera> camera)
* \return The libcamera version string
*/
-/**
- * \brief Set the event dispatcher
- * \param[in] dispatcher Pointer to the event dispatcher
- *
- * libcamera requires an event dispatcher to integrate event notification and
- * timers with the application event loop. Applications that want to provide
- * their own event dispatcher shall call this function once and only once before
- * the camera manager is started with start(). If no event dispatcher is
- * provided, a default poll-based implementation will be used.
- *
- * The CameraManager takes ownership of the event dispatcher and will delete it
- * when the application terminates.
- */
-void CameraManager::setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher)
-{
- thread()->setEventDispatcher(std::move(dispatcher));
-}
-
-/**
- * \brief Retrieve the event dispatcher
- *
- * This function retrieves the event dispatcher set with setEventDispatcher().
- * If no dispatcher has been set, a default poll-based implementation is created
- * and returned, and no custom event dispatcher may be installed anymore.
- *
- * The returned event dispatcher is valid until the camera manager is destroyed.
- *
- * \return Pointer to the event dispatcher
- */
-EventDispatcher *CameraManager::eventDispatcher()
-{
- return thread()->eventDispatcher();
-}
-
} /* namespace libcamera */
diff --git a/src/libcamera/device_enumerator_udev.cpp b/src/libcamera/device_enumerator_udev.cpp
index c6e23a1a..d26fcf10 100644
--- a/src/libcamera/device_enumerator_udev.cpp
+++ b/src/libcamera/device_enumerator_udev.cpp
@@ -17,8 +17,7 @@
#include <sys/sysmacros.h>
#include <unistd.h>
-#include <libcamera/event_notifier.h>
-
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/media_device.h"
diff --git a/src/libcamera/event_dispatcher.cpp b/src/libcamera/event_dispatcher.cpp
index 90bd5daf..e0ce1eb3 100644
--- a/src/libcamera/event_dispatcher.cpp
+++ b/src/libcamera/event_dispatcher.cpp
@@ -5,7 +5,7 @@
* event_dispatcher.cpp - Event dispatcher
*/
-#include <libcamera/event_dispatcher.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/log.h"
diff --git a/src/libcamera/event_dispatcher_poll.cpp b/src/libcamera/event_dispatcher_poll.cpp
index 9ab85da7..456c6def 100644
--- a/src/libcamera/event_dispatcher_poll.cpp
+++ b/src/libcamera/event_dispatcher_poll.cpp
@@ -16,11 +16,10 @@
#include <sys/eventfd.h>
#include <unistd.h>
-#include <libcamera/event_notifier.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/utils.h"
/**
diff --git a/src/libcamera/event_notifier.cpp b/src/libcamera/event_notifier.cpp
index 21c07faf..6b0575c0 100644
--- a/src/libcamera/event_notifier.cpp
+++ b/src/libcamera/event_notifier.cpp
@@ -5,11 +5,11 @@
* event_notifier.cpp - File descriptor event notifier
*/
-#include <libcamera/event_notifier.h>
+#include "libcamera/internal/event_notifier.h"
#include <libcamera/camera_manager.h>
-#include <libcamera/event_dispatcher.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/message.h"
#include "libcamera/internal/thread.h"
diff --git a/src/libcamera/ipc_unixsocket.cpp b/src/libcamera/ipc_unixsocket.cpp
index 5c8cce16..fdb359f7 100644
--- a/src/libcamera/ipc_unixsocket.cpp
+++ b/src/libcamera/ipc_unixsocket.cpp
@@ -12,8 +12,7 @@
#include <sys/socket.h>
#include <unistd.h>
-#include <libcamera/event_notifier.h>
-
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/log.h"
/**
diff --git a/src/libcamera/pipeline/rkisp1/timeline.h b/src/libcamera/pipeline/rkisp1/timeline.h
index 0c37b06f..35a08515 100644
--- a/src/libcamera/pipeline/rkisp1/timeline.h
+++ b/src/libcamera/pipeline/rkisp1/timeline.h
@@ -10,8 +10,7 @@
#include <list>
#include <map>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/utils.h"
namespace libcamera {
diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp
index 72b5afe2..40a434a6 100644
--- a/src/libcamera/process.cpp
+++ b/src/libcamera/process.cpp
@@ -20,8 +20,7 @@
#include <unistd.h>
#include <vector>
-#include <libcamera/event_notifier.h>
-
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/utils.h"
diff --git a/src/libcamera/proxy/worker/ipa_proxy_linux_worker.cpp b/src/libcamera/proxy/worker/ipa_proxy_linux_worker.cpp
index 0c4687f7..bdbac988 100644
--- a/src/libcamera/proxy/worker/ipa_proxy_linux_worker.cpp
+++ b/src/libcamera/proxy/worker/ipa_proxy_linux_worker.cpp
@@ -9,10 +9,10 @@
#include <sys/types.h>
#include <unistd.h>
-#include <libcamera/event_dispatcher.h>
#include <libcamera/ipa/ipa_interface.h>
#include <libcamera/logging.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/ipa_module.h"
#include "libcamera/internal/ipc_unixsocket.h"
#include "libcamera/internal/log.h"
diff --git a/src/libcamera/thread.cpp b/src/libcamera/thread.cpp
index b5d7103a..f339dab1 100644
--- a/src/libcamera/thread.cpp
+++ b/src/libcamera/thread.cpp
@@ -14,8 +14,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include <libcamera/event_dispatcher.h>
-
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/event_dispatcher_poll.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/message.h"
diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp
index 24e452ed..c242113a 100644
--- a/src/libcamera/timer.cpp
+++ b/src/libcamera/timer.cpp
@@ -5,13 +5,13 @@
* timer.cpp - Generic timer
*/
-#include <libcamera/timer.h>
+#include "libcamera/internal/timer.h"
#include <chrono>
#include <libcamera/camera_manager.h>
-#include <libcamera/event_dispatcher.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/message.h"
#include "libcamera/internal/thread.h"
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index fd0b140f..decd19ef 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -16,8 +16,7 @@
#include <sys/syscall.h>
#include <unistd.h>
-#include <libcamera/event_notifier.h>
-
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/sysfs.h"
#include "libcamera/internal/utils.h"
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 5ee1b479..e76fe2dd 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -20,9 +20,9 @@
#include <linux/version.h>
-#include <libcamera/event_notifier.h>
#include <libcamera/file_descriptor.h>
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/media_object.h"
diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp
index ccf532d7..7ff62826 100644
--- a/test/camera/buffer_import.cpp
+++ b/test/camera/buffer_import.cpp
@@ -12,12 +12,11 @@
#include <numeric>
#include <vector>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
-
#include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/v4l2_videodevice.h"
#include "buffer_source.h"
diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
index fd5292b7..6d564fe4 100644
--- a/test/camera/capture.cpp
+++ b/test/camera/capture.cpp
@@ -7,11 +7,11 @@
#include <iostream>
-#include <libcamera/event_dispatcher.h>
#include <libcamera/framebuffer_allocator.h>
-#include <libcamera/timer.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "camera_test.h"
#include "test.h"
diff --git a/test/event-dispatcher.cpp b/test/event-dispatcher.cpp
index 1b617786..8ae05ac6 100644
--- a/test/event-dispatcher.cpp
+++ b/test/event-dispatcher.cpp
@@ -10,10 +10,9 @@
#include <signal.h>
#include <sys/time.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/event-thread.cpp b/test/event-thread.cpp
index c90e6ac0..aeb8b3bf 100644
--- a/test/event-thread.cpp
+++ b/test/event-thread.cpp
@@ -10,10 +10,9 @@
#include <string.h>
#include <unistd.h>
-#include <libcamera/event_notifier.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/event.cpp b/test/event.cpp
index c865092c..1f16c97b 100644
--- a/test/event.cpp
+++ b/test/event.cpp
@@ -9,11 +9,10 @@
#include <string.h>
#include <unistd.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/event_notifier.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_dispatcher.h"
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/hotplug-cameras.cpp b/test/hotplug-cameras.cpp
index 7d551eeb..94cb8593 100644
--- a/test/hotplug-cameras.cpp
+++ b/test/hotplug-cameras.cpp
@@ -13,11 +13,11 @@
#include <libcamera/camera.h>
#include <libcamera/camera_manager.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/file.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/ipa/ipa_interface_test.cpp b/test/ipa/ipa_interface_test.cpp
index 67488409..9f575f93 100644
--- a/test/ipa/ipa_interface_test.cpp
+++ b/test/ipa/ipa_interface_test.cpp
@@ -12,16 +12,16 @@
#include <sys/types.h>
#include <unistd.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/event_notifier.h>
#include <libcamera/ipa/vimc.h>
-#include <libcamera/timer.h>
#include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/event_dispatcher.h"
+#include "libcamera/internal/event_notifier.h"
#include "libcamera/internal/ipa_manager.h"
#include "libcamera/internal/ipa_module.h"
#include "libcamera/internal/pipeline_handler.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp
index 9cd07ce8..19a1d7dd 100644
--- a/test/ipc/unixsocket.cpp
+++ b/test/ipc/unixsocket.cpp
@@ -15,11 +15,10 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/ipc_unixsocket.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/utils.h"
#include "test.h"
diff --git a/test/log/log_process.cpp b/test/log/log_process.cpp
index 2a826222..c0a1a012 100644
--- a/test/log/log_process.cpp
+++ b/test/log/log_process.cpp
@@ -14,13 +14,13 @@
#include <unistd.h>
#include <vector>
-#include <libcamera/event_dispatcher.h>
#include <libcamera/logging.h>
-#include <libcamera/timer.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/process.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/utils.h"
#include "test.h"
diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp
index f3fd2328..a6f816f3 100644
--- a/test/object-invoke.cpp
+++ b/test/object-invoke.cpp
@@ -8,9 +8,9 @@
#include <iostream>
#include <thread>
-#include <libcamera/event_dispatcher.h>
#include <libcamera/object.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
#include "test.h"
diff --git a/test/process/process_test.cpp b/test/process/process_test.cpp
index a3eaef80..1279d8c1 100644
--- a/test/process/process_test.cpp
+++ b/test/process/process_test.cpp
@@ -9,11 +9,10 @@
#include <unistd.h>
#include <vector>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/process.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/utils.h"
#include "test.h"
diff --git a/test/timer-thread.cpp b/test/timer-thread.cpp
index f794d8e7..be29eee1 100644
--- a/test/timer-thread.cpp
+++ b/test/timer-thread.cpp
@@ -8,10 +8,9 @@
#include <chrono>
#include <iostream>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/timer.cpp b/test/timer.cpp
index 537489d7..fc90b110 100644
--- a/test/timer.cpp
+++ b/test/timer.cpp
@@ -8,10 +8,9 @@
#include <chrono>
#include <iostream>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
-
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "test.h"
diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp
index 5e7e2d97..c75259be 100644
--- a/test/v4l2_videodevice/buffer_sharing.cpp
+++ b/test/v4l2_videodevice/buffer_sharing.cpp
@@ -13,10 +13,10 @@
#include <iostream>
#include <libcamera/buffer.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "v4l2_videodevice_test.h"
diff --git a/test/v4l2_videodevice/capture_async.cpp b/test/v4l2_videodevice/capture_async.cpp
index 2b38102e..accdb34a 100644
--- a/test/v4l2_videodevice/capture_async.cpp
+++ b/test/v4l2_videodevice/capture_async.cpp
@@ -8,10 +8,10 @@
#include <iostream>
#include <libcamera/buffer.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "v4l2_videodevice_test.h"
diff --git a/test/v4l2_videodevice/v4l2_m2mdevice.cpp b/test/v4l2_videodevice/v4l2_m2mdevice.cpp
index 616261e1..e0f06808 100644
--- a/test/v4l2_videodevice/v4l2_m2mdevice.cpp
+++ b/test/v4l2_videodevice/v4l2_m2mdevice.cpp
@@ -8,12 +8,12 @@
#include <iostream>
#include <libcamera/buffer.h>
-#include <libcamera/event_dispatcher.h>
-#include <libcamera/timer.h>
#include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/event_dispatcher.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/thread.h"
+#include "libcamera/internal/timer.h"
#include "libcamera/internal/v4l2_videodevice.h"
#include "test.h"
opt">); bool validateSensorControls(); bool validateIspControls(); void queueRequest(const ControlList &controls); void returnEmbeddedBuffer(unsigned int bufferId); void prepareISP(const ipa::RPi::ISPConfig &data); void reportMetadata(); void fillDeviceStatus(const ControlList &sensorControls); void processStats(unsigned int bufferId); void applyFrameDurations(double minFrameDuration, double maxFrameDuration); void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls); void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls); void applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls); void applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls); void applyBlackLevel(const struct BlackLevelStatus *blackLevelStatus, ControlList &ctrls); void applyGamma(const struct ContrastStatus *contrastStatus, ControlList &ctrls); void applyGEQ(const struct GeqStatus *geqStatus, ControlList &ctrls); void applyDenoise(const struct DenoiseStatus *denoiseStatus, ControlList &ctrls); void applySharpen(const struct SharpenStatus *sharpenStatus, ControlList &ctrls); void applyDPC(const struct DpcStatus *dpcStatus, ControlList &ctrls); void applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls); void resampleTable(uint16_t dest[], double const src[12][16], int destW, int destH); std::map<unsigned int, MappedFrameBuffer> buffers_; ControlInfoMap sensorCtrls_; ControlInfoMap ispCtrls_; ControlList libcameraMetadata_; /* Camera sensor params. */ CameraMode mode_; /* Raspberry Pi controller specific defines. */ std::unique_ptr<RPiController::CamHelper> helper_; RPiController::Controller controller_; RPiController::Metadata rpiMetadata_; /* * We count frames to decide if the frame must be hidden (e.g. from * display) or mistrusted (i.e. not given to the control algos). */ uint64_t frameCount_; /* For checking the sequencing of Prepare/Process calls. */ uint64_t checkCount_; /* How many frames we should avoid running control algos on. */ unsigned int mistrustCount_; /* Number of frames that need to be dropped on startup. */ unsigned int dropFrameCount_; /* Frame timestamp for the last run of the controller. */ uint64_t lastRunTimestamp_; /* Do we run a Controller::process() for this frame? */ bool processPending_; /* LS table allocation passed in from the pipeline handler. */ FileDescriptor lsTableHandle_; void *lsTable_; /* Distinguish the first camera start from others. */ bool firstStart_; /* Frame duration (1/fps) limits, given in microseconds. */ double minFrameDuration_; double maxFrameDuration_; }; int IPARPi::init(const IPASettings &settings, ipa::RPi::SensorConfig *sensorConfig) { /* * Load the "helper" for this sensor. This tells us all the device specific stuff * that the kernel driver doesn't. We only do this the first time; we don't need * to re-parse the metadata after a simple mode-switch for no reason. */ helper_ = std::unique_ptr<RPiController::CamHelper>(RPiController::CamHelper::Create(settings.sensorModel)); if (!helper_) { LOG(IPARPI, Error) << "Could not create camera helper for " << settings.sensorModel; return -EINVAL; } /* * Pass out the sensor config to the pipeline handler in order * to setup the staggered writer class. */ int gainDelay, exposureDelay, vblankDelay, sensorMetadata; helper_->GetDelays(exposureDelay, gainDelay, vblankDelay); sensorMetadata = helper_->SensorEmbeddedDataPresent(); sensorConfig->gainDelay = gainDelay; sensorConfig->exposureDelay = exposureDelay; sensorConfig->vblankDelay = vblankDelay; sensorConfig->sensorMetadata = sensorMetadata; /* Load the tuning file for this sensor. */ controller_.Read(settings.configurationFile.c_str()); controller_.Initialise(); return 0; } void IPARPi::start(const ControlList &controls, ipa::RPi::StartConfig *startConfig) { RPiController::Metadata metadata; ASSERT(startConfig); if (!controls.empty()) { /* We have been given some controls to action before start. */ queueRequest(controls); } controller_.SwitchMode(mode_, &metadata); /* SwitchMode may supply updated exposure/gain values to use. */ AgcStatus agcStatus; agcStatus.shutter_time = 0.0; agcStatus.analogue_gain = 0.0; metadata.Get("agc.status", agcStatus); if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) { ControlList ctrls(sensorCtrls_); applyAGC(&agcStatus, ctrls); startConfig->controls = std::move(ctrls); } /* * Initialise frame counts, and decide how many frames must be hidden or * "mistrusted", which depends on whether this is a startup from cold, * or merely a mode switch in a running system. */ frameCount_ = 0; checkCount_ = 0; if (firstStart_) { dropFrameCount_ = helper_->HideFramesStartup(); mistrustCount_ = helper_->MistrustFramesStartup(); /* * Query the AGC/AWB for how many frames they may take to * converge sufficiently. Where these numbers are non-zero * we must allow for the frames with bad statistics * (mistrustCount_) that they won't see. But if zero (i.e. * no convergence necessary), no frames need to be dropped. */ unsigned int agcConvergenceFrames = 0; RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (agc) { agcConvergenceFrames = agc->GetConvergenceFrames(); if (agcConvergenceFrames) agcConvergenceFrames += mistrustCount_; } unsigned int awbConvergenceFrames = 0; RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>( controller_.GetAlgorithm("awb")); if (awb) { awbConvergenceFrames = awb->GetConvergenceFrames(); if (awbConvergenceFrames) awbConvergenceFrames += mistrustCount_; } dropFrameCount_ = std::max({ dropFrameCount_, agcConvergenceFrames, awbConvergenceFrames }); LOG(IPARPI, Debug) << "Drop " << dropFrameCount_ << " frames on startup"; } else { dropFrameCount_ = helper_->HideFramesModeSwitch(); mistrustCount_ = helper_->MistrustFramesModeSwitch(); } startConfig->dropFrameCount = dropFrameCount_; firstStart_ = false; lastRunTimestamp_ = 0; } void IPARPi::setMode(const IPACameraSensorInfo &sensorInfo) { mode_.bitdepth = sensorInfo.bitsPerPixel; mode_.width = sensorInfo.outputSize.width; mode_.height = sensorInfo.outputSize.height; mode_.sensor_width = sensorInfo.activeAreaSize.width; mode_.sensor_height = sensorInfo.activeAreaSize.height; mode_.crop_x = sensorInfo.analogCrop.x; mode_.crop_y = sensorInfo.analogCrop.y; /* * Calculate scaling parameters. The scale_[xy] factors are determined * by the ratio between the crop rectangle size and the output size. */ mode_.scale_x = sensorInfo.analogCrop.width / sensorInfo.outputSize.width; mode_.scale_y = sensorInfo.analogCrop.height / sensorInfo.outputSize.height; /* * We're not told by the pipeline handler how scaling is split between * binning and digital scaling. For now, as a heuristic, assume that * downscaling up to 2 is achieved through binning, and that any * additional scaling is achieved through digital scaling. * * \todo Get the pipeline handle to provide the full data */ mode_.bin_x = std::min(2, static_cast<int>(mode_.scale_x)); mode_.bin_y = std::min(2, static_cast<int>(mode_.scale_y)); /* The noise factor is the square root of the total binning factor. */ mode_.noise_factor = sqrt(mode_.bin_x * mode_.bin_y); /* * Calculate the line length in nanoseconds as the ratio between * the line length in pixels and the pixel rate. */ mode_.line_length = 1e9 * sensorInfo.lineLength / sensorInfo.pixelRate; /* * Set the frame length limits for the mode to ensure exposure and * framerate calculations are clipped appropriately. */ mode_.min_frame_length = sensorInfo.minFrameLength; mode_.max_frame_length = sensorInfo.maxFrameLength; } int IPARPi::configure(const IPACameraSensorInfo &sensorInfo, [[maybe_unused]] const std::map<unsigned int, IPAStream> &streamConfig, const std::map<unsigned int, ControlInfoMap> &entityControls, const ipa::RPi::IPAConfig &ipaConfig, ControlList *controls) { if (entityControls.size() != 2) { LOG(IPARPI, Error) << "No ISP or sensor controls found."; return -1; } sensorCtrls_ = entityControls.at(0); ispCtrls_ = entityControls.at(1); if (!validateSensorControls()) { LOG(IPARPI, Error) << "Sensor control validation failed."; return -1; } if (!validateIspControls()) { LOG(IPARPI, Error) << "ISP control validation failed."; return -1; } /* Setup a metadata ControlList to output metadata. */ libcameraMetadata_ = ControlList(controls::controls); /* Re-assemble camera mode using the sensor info. */ setMode(sensorInfo); mode_.transform = static_cast<libcamera::Transform>(ipaConfig.transform); /* Store the lens shading table pointer and handle if available. */ if (ipaConfig.lsTableHandle.isValid()) { /* Remove any previous table, if there was one. */ if (lsTable_) { munmap(lsTable_, ipa::RPi::MaxLsGridSize); lsTable_ = nullptr; } /* Map the LS table buffer into user space. */ lsTableHandle_ = std::move(ipaConfig.lsTableHandle); if (lsTableHandle_.isValid()) { lsTable_ = mmap(nullptr, ipa::RPi::MaxLsGridSize, PROT_READ | PROT_WRITE, MAP_SHARED, lsTableHandle_.fd(), 0); if (lsTable_ == MAP_FAILED) { LOG(IPARPI, Error) << "dmaHeap mmap failure for LS table."; lsTable_ = nullptr; } } } /* Pass the camera mode to the CamHelper to setup algorithms. */ helper_->SetCameraMode(mode_); if (firstStart_) { /* Supply initial values for frame durations. */ applyFrameDurations(defaultMinFrameDuration, defaultMaxFrameDuration); /* Supply initial values for gain and exposure. */ ControlList ctrls(sensorCtrls_); AgcStatus agcStatus; agcStatus.shutter_time = DefaultExposureTime; agcStatus.analogue_gain = DefaultAnalogueGain; applyAGC(&agcStatus, ctrls); ASSERT(controls); *controls = std::move(ctrls); } return 0; } void IPARPi::mapBuffers(const std::vector<IPABuffer> &buffers) { for (const IPABuffer &buffer : buffers) { const FrameBuffer fb(buffer.planes); buffers_.emplace(buffer.id, MappedFrameBuffer(&fb, PROT_READ | PROT_WRITE)); } } void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids) { for (unsigned int id : ids) { auto it = buffers_.find(id); if (it == buffers_.end()) continue; buffers_.erase(id); } } void IPARPi::signalStatReady(uint32_t bufferId) { if (++checkCount_ != frameCount_) /* assert here? */ LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!"; if (processPending_ && frameCount_ > mistrustCount_) processStats(bufferId); reportMetadata(); statsMetadataComplete.emit(bufferId & ipa::RPi::MaskID, libcameraMetadata_); } void IPARPi::signalQueueRequest(const ControlList &controls) { queueRequest(controls); } void IPARPi::signalIspPrepare(const ipa::RPi::ISPConfig &data) { /* * At start-up, or after a mode-switch, we may want to * avoid running the control algos for a few frames in case * they are "unreliable". */ prepareISP(data); frameCount_++; /* Ready to push the input buffer into the ISP. */ runIsp.emit(data.bayerBufferId & ipa::RPi::MaskID); } void IPARPi::reportMetadata() { std::unique_lock<RPiController::Metadata> lock(rpiMetadata_); /* * Certain information about the current frame and how it will be * processed can be extracted and placed into the libcamera metadata * buffer, where an application could query it. */ DeviceStatus *deviceStatus = rpiMetadata_.GetLocked<DeviceStatus>("device.status"); if (deviceStatus) { libcameraMetadata_.set(controls::ExposureTime, deviceStatus->shutter_speed); libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogue_gain); } AgcStatus *agcStatus = rpiMetadata_.GetLocked<AgcStatus>("agc.status"); if (agcStatus) { libcameraMetadata_.set(controls::AeLocked, agcStatus->locked); libcameraMetadata_.set(controls::DigitalGain, agcStatus->digital_gain); } LuxStatus *luxStatus = rpiMetadata_.GetLocked<LuxStatus>("lux.status"); if (luxStatus) libcameraMetadata_.set(controls::Lux, luxStatus->lux); AwbStatus *awbStatus = rpiMetadata_.GetLocked<AwbStatus>("awb.status"); if (awbStatus) { libcameraMetadata_.set(controls::ColourGains, { static_cast<float>(awbStatus->gain_r), static_cast<float>(awbStatus->gain_b) }); libcameraMetadata_.set(controls::ColourTemperature, awbStatus->temperature_K); } BlackLevelStatus *blackLevelStatus = rpiMetadata_.GetLocked<BlackLevelStatus>("black_level.status"); if (blackLevelStatus) libcameraMetadata_.set(controls::SensorBlackLevels, { static_cast<int32_t>(blackLevelStatus->black_level_r), static_cast<int32_t>(blackLevelStatus->black_level_g), static_cast<int32_t>(blackLevelStatus->black_level_g), static_cast<int32_t>(blackLevelStatus->black_level_b) }); FocusStatus *focusStatus = rpiMetadata_.GetLocked<FocusStatus>("focus.status"); if (focusStatus && focusStatus->num == 12) { /* * We get a 4x3 grid of regions by default. Calculate the average * FoM over the central two positions to give an overall scene FoM. * This can change later if it is not deemed suitable. */ int32_t focusFoM = (focusStatus->focus_measures[5] + focusStatus->focus_measures[6]) / 2; libcameraMetadata_.set(controls::FocusFoM, focusFoM); } CcmStatus *ccmStatus = rpiMetadata_.GetLocked<CcmStatus>("ccm.status"); if (ccmStatus) { float m[9]; for (unsigned int i = 0; i < 9; i++) m[i] = ccmStatus->matrix[i]; libcameraMetadata_.set(controls::ColourCorrectionMatrix, m); } } bool IPARPi::validateSensorControls() { static const uint32_t ctrls[] = { V4L2_CID_ANALOGUE_GAIN, V4L2_CID_EXPOSURE, V4L2_CID_VBLANK, }; for (auto c : ctrls) { if (sensorCtrls_.find(c) == sensorCtrls_.end()) { LOG(IPARPI, Error) << "Unable to find sensor control " << utils::hex(c); return false; } } return true; } bool IPARPi::validateIspControls() { static const uint32_t ctrls[] = { V4L2_CID_RED_BALANCE, V4L2_CID_BLUE_BALANCE, V4L2_CID_DIGITAL_GAIN, V4L2_CID_USER_BCM2835_ISP_CC_MATRIX, V4L2_CID_USER_BCM2835_ISP_GAMMA, V4L2_CID_USER_BCM2835_ISP_BLACK_LEVEL, V4L2_CID_USER_BCM2835_ISP_GEQ, V4L2_CID_USER_BCM2835_ISP_DENOISE, V4L2_CID_USER_BCM2835_ISP_SHARPEN, V4L2_CID_USER_BCM2835_ISP_DPC, V4L2_CID_USER_BCM2835_ISP_LENS_SHADING, V4L2_CID_USER_BCM2835_ISP_CDN, }; for (auto c : ctrls) { if (ispCtrls_.find(c) == ispCtrls_.end()) { LOG(IPARPI, Error) << "Unable to find ISP control " << utils::hex(c); return false; } } return true; } /* * Converting between enums (used in the libcamera API) and the names that * we use to identify different modes. Unfortunately, the conversion tables * must be kept up-to-date by hand. */ static const std::map<int32_t, std::string> MeteringModeTable = { { controls::MeteringCentreWeighted, "centre-weighted" }, { controls::MeteringSpot, "spot" }, { controls::MeteringMatrix, "matrix" }, { controls::MeteringCustom, "custom" }, }; static const std::map<int32_t, std::string> ConstraintModeTable = { { controls::ConstraintNormal, "normal" }, { controls::ConstraintHighlight, "highlight" }, { controls::ConstraintCustom, "custom" }, }; static const std::map<int32_t, std::string> ExposureModeTable = { { controls::ExposureNormal, "normal" }, { controls::ExposureShort, "short" }, { controls::ExposureLong, "long" }, { controls::ExposureCustom, "custom" }, }; static const std::map<int32_t, std::string> AwbModeTable = { { controls::AwbAuto, "normal" }, { controls::AwbIncandescent, "incandescent" }, { controls::AwbTungsten, "tungsten" }, { controls::AwbFluorescent, "fluorescent" }, { controls::AwbIndoor, "indoor" }, { controls::AwbDaylight, "daylight" }, { controls::AwbCloudy, "cloudy" }, { controls::AwbCustom, "custom" }, }; static const std::map<int32_t, RPiController::DenoiseMode> DenoiseModeTable = { { controls::draft::NoiseReductionModeOff, RPiController::DenoiseMode::Off }, { controls::draft::NoiseReductionModeFast, RPiController::DenoiseMode::ColourFast }, { controls::draft::NoiseReductionModeHighQuality, RPiController::DenoiseMode::ColourHighQuality }, { controls::draft::NoiseReductionModeMinimal, RPiController::DenoiseMode::ColourOff }, { controls::draft::NoiseReductionModeZSL, RPiController::DenoiseMode::ColourHighQuality }, }; void IPARPi::queueRequest(const ControlList &controls) { /* Clear the return metadata buffer. */ libcameraMetadata_.clear(); for (auto const &ctrl : controls) { LOG(IPARPI, Info) << "Request ctrl: " << controls::controls.at(ctrl.first)->name() << " = " << ctrl.second.toString(); switch (ctrl.first) { case controls::AE_ENABLE: { RPiController::Algorithm *agc = controller_.GetAlgorithm("agc"); if (!agc) { LOG(IPARPI, Warning) << "Could not set AE_ENABLE - no AGC algorithm"; break; } if (ctrl.second.get<bool>() == false) agc->Pause(); else agc->Resume(); libcameraMetadata_.set(controls::AeEnable, ctrl.second.get<bool>()); break; } case controls::EXPOSURE_TIME: { RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (!agc) { LOG(IPARPI, Warning) << "Could not set EXPOSURE_TIME - no AGC algorithm"; break; } /* This expects units of micro-seconds. */ agc->SetFixedShutter(ctrl.second.get<int32_t>()); libcameraMetadata_.set(controls::ExposureTime, ctrl.second.get<int32_t>()); break; } case controls::ANALOGUE_GAIN: { RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (!agc) { LOG(IPARPI, Warning) << "Could not set ANALOGUE_GAIN - no AGC algorithm"; break; } agc->SetFixedAnalogueGain(ctrl.second.get<float>()); libcameraMetadata_.set(controls::AnalogueGain, ctrl.second.get<float>()); break; } case controls::AE_METERING_MODE: { RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (!agc) { LOG(IPARPI, Warning) << "Could not set AE_METERING_MODE - no AGC algorithm"; break; } int32_t idx = ctrl.second.get<int32_t>(); if (MeteringModeTable.count(idx)) { agc->SetMeteringMode(MeteringModeTable.at(idx)); libcameraMetadata_.set(controls::AeMeteringMode, idx); } else { LOG(IPARPI, Error) << "Metering mode " << idx << " not recognised"; } break; } case controls::AE_CONSTRAINT_MODE: { RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (!agc) { LOG(IPARPI, Warning) << "Could not set AE_CONSTRAINT_MODE - no AGC algorithm"; break; } int32_t idx = ctrl.second.get<int32_t>(); if (ConstraintModeTable.count(idx)) { agc->SetConstraintMode(ConstraintModeTable.at(idx)); libcameraMetadata_.set(controls::AeConstraintMode, idx); } else { LOG(IPARPI, Error) << "Constraint mode " << idx << " not recognised"; } break; } case controls::AE_EXPOSURE_MODE: { RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (!agc) { LOG(IPARPI, Warning) << "Could not set AE_EXPOSURE_MODE - no AGC algorithm"; break; } int32_t idx = ctrl.second.get<int32_t>(); if (ExposureModeTable.count(idx)) { agc->SetExposureMode(ExposureModeTable.at(idx)); libcameraMetadata_.set(controls::AeExposureMode, idx); } else { LOG(IPARPI, Error) << "Exposure mode " << idx << " not recognised"; } break; } case controls::EXPOSURE_VALUE: { RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>( controller_.GetAlgorithm("agc")); if (!agc) { LOG(IPARPI, Warning) << "Could not set EXPOSURE_VALUE - no AGC algorithm"; break; } /* * The SetEv() method takes in a direct exposure multiplier. * So convert to 2^EV */ double ev = pow(2.0, ctrl.second.get<float>()); agc->SetEv(ev); libcameraMetadata_.set(controls::ExposureValue, ctrl.second.get<float>()); break; } case controls::AWB_ENABLE: { RPiController::Algorithm *awb = controller_.GetAlgorithm("awb"); if (!awb) { LOG(IPARPI, Warning) << "Could not set AWB_ENABLE - no AWB algorithm"; break; } if (ctrl.second.get<bool>() == false) awb->Pause(); else awb->Resume(); libcameraMetadata_.set(controls::AwbEnable, ctrl.second.get<bool>()); break; } case controls::AWB_MODE: { RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>( controller_.GetAlgorithm("awb")); if (!awb) { LOG(IPARPI, Warning) << "Could not set AWB_MODE - no AWB algorithm"; break; } int32_t idx = ctrl.second.get<int32_t>(); if (AwbModeTable.count(idx)) { awb->SetMode(AwbModeTable.at(idx)); libcameraMetadata_.set(controls::AwbMode, idx); } else { LOG(IPARPI, Error) << "AWB mode " << idx << " not recognised"; } break; } case controls::COLOUR_GAINS: { auto gains = ctrl.second.get<Span<const float>>(); RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>( controller_.GetAlgorithm("awb")); if (!awb) { LOG(IPARPI, Warning) << "Could not set COLOUR_GAINS - no AWB algorithm"; break; } awb->SetManualGains(gains[0], gains[1]); if (gains[0] != 0.0f && gains[1] != 0.0f) /* A gain of 0.0f will switch back to auto mode. */ libcameraMetadata_.set(controls::ColourGains, { gains[0], gains[1] }); break; } case controls::BRIGHTNESS: { RPiController::ContrastAlgorithm *contrast = dynamic_cast<RPiController::ContrastAlgorithm *>( controller_.GetAlgorithm("contrast")); if (!contrast) { LOG(IPARPI, Warning) << "Could not set BRIGHTNESS - no contrast algorithm"; break; } contrast->SetBrightness(ctrl.second.get<float>() * 65536); libcameraMetadata_.set(controls::Brightness, ctrl.second.get<float>()); break; } case controls::CONTRAST: { RPiController::ContrastAlgorithm *contrast = dynamic_cast<RPiController::ContrastAlgorithm *>( controller_.GetAlgorithm("contrast")); if (!contrast) { LOG(IPARPI, Warning) << "Could not set CONTRAST - no contrast algorithm"; break; } contrast->SetContrast(ctrl.second.get<float>()); libcameraMetadata_.set(controls::Contrast, ctrl.second.get<float>()); break; } case controls::SATURATION: { RPiController::CcmAlgorithm *ccm = dynamic_cast<RPiController::CcmAlgorithm *>( controller_.GetAlgorithm("ccm")); if (!ccm) { LOG(IPARPI, Warning) << "Could not set SATURATION - no ccm algorithm"; break; } ccm->SetSaturation(ctrl.second.get<float>()); libcameraMetadata_.set(controls::Saturation, ctrl.second.get<float>()); break; } case controls::SHARPNESS: { RPiController::SharpenAlgorithm *sharpen = dynamic_cast<RPiController::SharpenAlgorithm *>( controller_.GetAlgorithm("sharpen")); if (!sharpen) { LOG(IPARPI, Warning) << "Could not set SHARPNESS - no sharpen algorithm"; break; } sharpen->SetStrength(ctrl.second.get<float>()); libcameraMetadata_.set(controls::Sharpness, ctrl.second.get<float>()); break; } case controls::SCALER_CROP: { /* We do nothing with this, but should avoid the warning below. */ break; } case controls::FRAME_DURATION_LIMITS: { auto frameDurations = ctrl.second.get<Span<const int64_t>>(); applyFrameDurations(frameDurations[0], frameDurations[1]); break; } case controls::NOISE_REDUCTION_MODE: { RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>( controller_.GetAlgorithm("SDN")); if (!sdn) { LOG(IPARPI, Warning) << "Could not set NOISE_REDUCTION_MODE - no SDN algorithm"; break; } int32_t idx = ctrl.second.get<int32_t>(); auto mode = DenoiseModeTable.find(idx); if (mode != DenoiseModeTable.end()) { sdn->SetMode(mode->second); /* * \todo If the colour denoise is not going to run due to an * analysis image resolution or format mismatch, we should * report the status correctly in the metadata. */ libcameraMetadata_.set(controls::draft::NoiseReductionMode, idx); } else { LOG(IPARPI, Error) << "Noise reduction mode " << idx << " not recognised"; } break; } default: LOG(IPARPI, Warning) << "Ctrl " << controls::controls.at(ctrl.first)->name() << " is not handled."; break; } } } void IPARPi::returnEmbeddedBuffer(unsigned int bufferId) { embeddedComplete.emit(bufferId & ipa::RPi::MaskID); } void IPARPi::prepareISP(const ipa::RPi::ISPConfig &data) { int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp); RPiController::Metadata lastMetadata; Span<uint8_t> embeddedBuffer; lastMetadata = std::move(rpiMetadata_); fillDeviceStatus(data.controls); if (data.embeddedBufferPresent) { /* * Pipeline handler has supplied us with an embedded data buffer, * we must pass it to the CamHelper for parsing. */ auto it = buffers_.find(data.embeddedBufferId); ASSERT(it != buffers_.end()); embeddedBuffer = it->second.maps()[0]; } /* * This may overwrite the DeviceStatus using values from the sensor * metadata, and may also do additional custom processing. */ helper_->Prepare(embeddedBuffer, rpiMetadata_); /* Done with embedded data now, return to pipeline handler asap. */ if (data.embeddedBufferPresent) returnEmbeddedBuffer(data.embeddedBufferId); /* Allow a 10% margin on the comparison below. */ constexpr double eps = controllerMinFrameDuration * 1e3 * 0.1; if (lastRunTimestamp_ && frameCount_ > dropFrameCount_ && frameTimestamp - lastRunTimestamp_ + eps < controllerMinFrameDuration * 1e3) { /* * Ensure we merge the previous frame's metadata with the current * frame. This will not overwrite exposure/gain values for the * current frame, or any other bits of metadata that were added * in helper_->Prepare(). */ rpiMetadata_.Merge(lastMetadata); processPending_ = false; return; } lastRunTimestamp_ = frameTimestamp; processPending_ = true; ControlList ctrls(ispCtrls_); controller_.Prepare(&rpiMetadata_); /* Lock the metadata buffer to avoid constant locks/unlocks. */ std::unique_lock<RPiController::Metadata> lock(rpiMetadata_); AwbStatus *awbStatus = rpiMetadata_.GetLocked<AwbStatus>("awb.status"); if (awbStatus) applyAWB(awbStatus, ctrls); CcmStatus *ccmStatus = rpiMetadata_.GetLocked<CcmStatus>("ccm.status"); if (ccmStatus) applyCCM(ccmStatus, ctrls);