summaryrefslogtreecommitdiff
path: root/src/android/camera3_hal.cpp
blob: 716e36c72b833b6efb560f0ff4d4da6355348922 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * camera3_hal.cpp - Android Camera HALv3 module
 */

#include <hardware/camera_common.h>

#include "libcamera/internal/log.h"

#include "camera_device.h"
#include "camera_hal_manager.h"

using namespace libcamera;

LOG_DEFINE_CATEGORY(HAL)

static CameraHalManager cameraManager;

/*------------------------------------------------------------------------------
 * Android Camera HAL callbacks
 */

static int hal_get_number_of_cameras(void)
{
	return cameraManager.numCameras();
}

static int hal_get_camera_info(int id, struct camera_info *info)
{
	return cameraManager.getCameraInfo(id, info);
}

static int hal_set_callbacks(const camera_module_callbacks_t *callbacks)
{
	return 0;
}

static int hal_open_legacy(const struct hw_module_t *module, const char *id,
			   uint32_t halVersion, struct hw_device_t **device)
{
	return -ENOSYS;
}

static int hal_set_torch_mode(const char *camera_id, bool enabled)
{
	return -ENOSYS;
}

/*
 * First entry point of the camera HAL module.
 *
 * Initialize the HAL but does not open any camera device yet (see hal_dev_open)
 */
static int hal_init()
{
	LOG(HAL, Info) << "Initialising Android camera HAL";

	cameraManager.init();

	return 0;
}

/*------------------------------------------------------------------------------
 * Android Camera Device
 */

static int hal_dev_open(const hw_module_t *module, const char *name,
			hw_device_t **device)
{
	LOG(HAL, Debug) << "Open camera " << name;

	int id = atoi(name);
	CameraDevice *camera = cameraManager.open(id, module);
	if (!camera) {
		LOG(HAL, Error)
			<< "Failed to open camera module '" << id << "'";
		return -ENODEV;
	}

	*device = &camera->camera3Device()->common;

	return 0;
}

static struct hw_module_methods_t hal_module_methods = {
	.open = hal_dev_open,
};

camera_module_t HAL_MODULE_INFO_SYM = {
	.common = {
		.tag = HARDWARE_MODULE_TAG,
		.module_api_version = CAMERA_MODULE_API_VERSION_2_4,
		.hal_api_version = HARDWARE_HAL_API_VERSION,
		.id = CAMERA_HARDWARE_MODULE_ID,
		.name = "libcamera camera HALv3 module",
		.author = "libcamera",
		.methods = &hal_module_methods,
		.dso = nullptr,
		.reserved = {},
	},

	.get_number_of_cameras = hal_get_number_of_cameras,
	.get_camera_info = hal_get_camera_info,
	.set_callbacks = hal_set_callbacks,
	.get_vendor_tag_ops = nullptr,
	.open_legacy = hal_open_legacy,
	.set_torch_mode = hal_set_torch_mode,
	.init = hal_init,
	.reserved = {},
};
this * sensor's R/G) */ double sensitivityR; /* * blue sensitivity ratio (set to canonical sensor's B/G divided by this * sensor's B/G) */ double sensitivityB; /* The whitepoint (which we normally "aim" for) can be moved. */ double whitepointR; double whitepointB; bool bayes; /* use Bayesian algorithm */ }; class Awb : public AwbAlgorithm { public: Awb(Controller *controller = NULL); ~Awb(); char const *name() const override; void initialise() override; int read(const libcamera::YamlObject &params) override; unsigned int getConvergenceFrames() const override; void setMode(std::string const &name) override; void setManualGains(double manualR, double manualB) override; void enableAuto() override; void disableAuto() override; void switchMode(CameraMode const &cameraMode, Metadata *metadata) override; void prepare(Metadata *imageMetadata) override; void process(StatisticsPtr &stats, Metadata *imageMetadata) override; struct RGB { RGB(double r = 0, double g = 0, double b = 0) : R(r), G(g), B(b) { } double R, G, B; RGB &operator+=(RGB const &other) { R += other.R, G += other.G, B += other.B; return *this; } }; private: bool isAutoEnabled() const; /* configuration is read-only, and available to both threads */ AwbConfig config_; std::thread asyncThread_; void asyncFunc(); /* asynchronous thread function */ std::mutex mutex_; /* condvar for async thread to wait on */ std::condition_variable asyncSignal_; /* condvar for synchronous thread to wait on */ std::condition_variable syncSignal_; /* for sync thread to check if async thread finished (requires mutex) */ bool asyncFinished_; /* for async thread to check if it's been told to run (requires mutex) */ bool asyncStart_; /* for async thread to check if it's been told to quit (requires mutex) */ bool asyncAbort_; /* * The following are only for the synchronous thread to use: * for sync thread to note its has asked async thread to run */ bool asyncStarted_; /* counts up to framePeriod before restarting the async thread */ int framePhase_; int frameCount_; /* counts up to startup_frames */ AwbStatus syncResults_; AwbStatus prevSyncResults_; std::string modeName_; /* * The following are for the asynchronous thread to use, though the main * thread can set/reset them if the async thread is known to be idle: */ void restartAsync(StatisticsPtr &stats, double lux); /* copy out the results from the async thread so that it can be restarted */ void fetchAsyncResults(); StatisticsPtr statistics_; AwbMode *mode_; double lux_; AwbStatus asyncResults_; void doAwb(); void awbBayes(); void awbGrey(); void prepareStats(); double computeDelta2Sum(double gainR, double gainB); Pwl interpolatePrior(); double coarseSearch(Pwl const &prior); void fineSearch(double &t, double &r, double &b, Pwl const &prior); std::vector<RGB> zones_; std::vector<Pwl::Point> points_; /* manual r setting */ double manualR_; /* manual b setting */ double manualB_; }; static inline Awb::RGB operator+(Awb::RGB const &a, Awb::RGB const &b) { return Awb::RGB(a.R + b.R, a.G + b.G, a.B + b.B); } static inline Awb::RGB operator-(Awb::RGB const &a, Awb::RGB const &b) { return Awb::RGB(a.R - b.R, a.G - b.G, a.B - b.B); } static inline Awb::RGB operator*(double d, Awb::RGB const &rgb)