summaryrefslogtreecommitdiff
path: root/src/android/camera_hal_manager.cpp
blob: 22f0323b3ff08013a63f23b9672a7aec08bf2c18 (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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * camera_hal_manager.cpp - libcamera Android Camera Manager
 */

#include "camera_hal_manager.h"

#include <libcamera/camera.h>

#include "log.h"

#include "camera_device.h"
#include "camera_proxy.h"

using namespace libcamera;

LOG_DECLARE_CATEGORY(HAL);

/*
 * \class CameraHalManager
 *
 * The HAL camera manager is initializated at camera_module_t 'hal_init()' time
 * and spawns its own thread where libcamera related events are dispatched to.
 * It wraps the libcamera CameraManager operations and provides helpers for the
 * camera_module_t operations, to retrieve the number of cameras in the system,
 * their static information and to open camera devices.
 */

CameraHalManager::~CameraHalManager()
{
	if (isRunning()) {
		exit(0);
		/* \todo Wait with a timeout, just in case. */
		wait();
	}
}

int CameraHalManager::init()
{
	/*
	 * Start the camera HAL manager thread and wait until its
	 * initialisation completes to be fully operational before
	 * receiving calls from the camera stack.
	 */
	start();

	MutexLocker locker(mutex_);
	cv_.wait(locker);

	return 0;
}

void CameraHalManager::run()
{
	/*
	 * All the libcamera components must be initialised here, in
	 * order to bind them to the camera HAL manager thread that
	 * executes the event dispatcher.
	 */
	cameraManager_ = new CameraManager();

	int ret = cameraManager_->start();
	if (ret) {
		LOG(HAL, Error) << "Failed to start camera manager: "
				<< strerror(-ret);
		return;
	}

	/*
	 * For each Camera registered in the system, a CameraProxy
	 * gets created here to wraps a camera device.
	 *
	 * \todo Support camera hotplug.
	 */
	unsigned int index = 0;
	for (auto &camera : cameraManager_->cameras()) {
		CameraProxy *proxy = new CameraProxy(index, camera);
		proxies_.emplace_back(proxy);

		++index;
	}

	/*
	 * libcamera has been initialized. Unlock the init() caller
	 * as we're now ready to handle calls from the framework.
	 */
	cv_.notify_one();

	/* Now start processing events and messages. */
	exec();

	/* Clean up the resources we have allocated. */
	proxies_.clear();

	cameraManager_->stop();
	delete cameraManager_;
	cameraManager_ = nullptr;
}

CameraProxy *CameraHalManager::open(unsigned int id,
				    const hw_module_t *hardwareModule)
{
	if (id >= numCameras()) {
		LOG(HAL, Error) << "Invalid camera id '" << id << "'";
		return nullptr;
	}

	CameraProxy *proxy = proxies_[id].get();
	if (proxy->open(hardwareModule))
		return nullptr;

	LOG(HAL, Info) << "Open camera '" << id << "'";

	return proxy;
}

unsigned int CameraHalManager::numCameras() const
{
	return cameraManager_->cameras().size();
}

int CameraHalManager::getCameraInfo(unsigned int id, struct camera_info *info)
{
	if (!info)
		return -EINVAL;

	if (id >= numCameras()) {
		LOG(HAL, Error) << "Invalid camera id '" << id << "'";
		return -EINVAL;
	}

	CameraProxy *proxy = proxies_[id].get();

	/* \todo Get these info dynamically inspecting the camera module. */
	info->facing = id ? CAMERA_FACING_FRONT : CAMERA_FACING_BACK;
	info->orientation = 0;
	info->device_version = 0;
	info->resource_cost = 0;
	info->static_camera_characteristics = proxy->getStaticMetadata();
	info->conflicting_devices = nullptr;
	info->conflicting_devices_length = 0;

	return 0;
}
pt">*statistics, Metadata *image_metadata, double &gain, double &target_Y); void computeTargetExposure(double gain); bool applyDigitalGain(double gain, double target_Y); void filterExposure(bool desaturate); void divideUpExposure(); void writeAndFinish(Metadata *image_metadata, bool desaturate); AgcMeteringMode *metering_mode_; AgcExposureMode *exposure_mode_; AgcConstraintMode *constraint_mode_; uint64_t frame_count_; AwbStatus awb_; struct ExposureValues { ExposureValues() : shutter(0), analogue_gain(0), total_exposure(0), total_exposure_no_dg(0) {} double shutter; double analogue_gain; double total_exposure; double total_exposure_no_dg; // without digital gain }; ExposureValues current_; // values for the current frame ExposureValues target_; // calculate the values we want here ExposureValues filtered_; // these values are filtered towards target AgcStatus status_; int lock_count_; DeviceStatus last_device_status_; double last_target_exposure_; // Below here the "settings" that applications can change. std::string metering_mode_name_; std::string exposure_mode_name_; std::string constraint_mode_name_; double ev_; double flicker_period_; double fixed_shutter_; double fixed_analogue_gain_; }; } // namespace RPiController