summaryrefslogtreecommitdiff
path: root/include/libcamera/internal/pipeline_handler.h
blob: ec4f662d7399d2bc4938aefda8f4708c3d80b60c (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
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2018, Google Inc.
 *
 * pipeline_handler.h - Pipeline handler infrastructure
 */

#pragma once

#include <memory>
#include <queue>
#include <set>
#include <string>
#include <sys/types.h>
#include <vector>

#include <libcamera/base/mutex.h>
#include <libcamera/base/object.h>

#include <libcamera/controls.h>
#include <libcamera/stream.h>

#include "libcamera/internal/ipa_proxy.h"

namespace libcamera {

class Camera;
class CameraConfiguration;
class CameraManager;
class DeviceEnumerator;
class DeviceMatch;
class FrameBuffer;
class MediaDevice;
class PipelineHandler;
class Request;

class PipelineHandler : public std::enable_shared_from_this<PipelineHandler>,
			public Object
{
public:
	PipelineHandler(CameraManager *manager);
	virtual ~PipelineHandler();

	virtual bool match(DeviceEnumerator *enumerator) = 0;
	MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
					const DeviceMatch &dm);

	bool acquire();
	void release(Camera *camera);

	virtual std::unique_ptr<CameraConfiguration> generateConfiguration(Camera *camera,
		const StreamRoles &roles) = 0;
	virtual int configure(Camera *camera, CameraConfiguration *config) = 0;

	virtual int exportFrameBuffers(Camera *camera, Stream *stream,
				       std::vector<std::unique_ptr<FrameBuffer>> *buffers) = 0;

	virtual int start(Camera *camera, const ControlList *controls) = 0;
	void stop(Camera *camera);
	bool hasPendingRequests(const Camera *camera) const;

	void registerRequest(Request *request);
	void queueRequest(Request *request);

	bool completeBuffer(Request *request, FrameBuffer *buffer);
	void completeRequest(Request *request);

	const char *name() const { return name_; }

protected:
	void registerCamera(std::shared_ptr<Camera> camera);
	void hotplugMediaDevice(MediaDevice *media);

	virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
	virtual void stopDevice(Camera *camera) = 0;

	virtual void releaseDevice(Camera *camera);

	CameraManager *manager_;

private:
	void unlockMediaDevices();

	void mediaDeviceDisconnected(MediaDevice *media);
	virtual void disconnect();

	void doQueueRequest(Request *request);
	void doQueueRequests();

	std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
	std::vector<std::weak_ptr<Camera>> cameras_;

	std::queue<Request *> waitingRequests_;

	const char *name_;

	Mutex lock_;
	unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_);

	friend class PipelineHandlerFactoryBase;
};

class PipelineHandlerFactoryBase
{
public:
	PipelineHandlerFactoryBase(const char *name);
	virtual ~PipelineHandlerFactoryBase() = default;

	std::shared_ptr<PipelineHandler> create(CameraManager *manager) const;

	const std::string &name() const { return name_; }

	static std::vector<PipelineHandlerFactoryBase *> &factories();

private:
	static void registerType(PipelineHandlerFactoryBase *factory);

	virtual std::unique_ptr<PipelineHandler>
	createInstance(CameraManager *manager) const = 0;

	std::string name_;
};

template<typename _PipelineHandler>
class PipelineHandlerFactory final : public PipelineHandlerFactoryBase
{
public:
	PipelineHandlerFactory(const char *name)
		: PipelineHandlerFactoryBase(name)
	{
	}

	std::unique_ptr<PipelineHandler>
	createInstance(CameraManager *manager) const override
	{
		return std::make_unique<_PipelineHandler>(manager);
	}
};

#define REGISTER_PIPELINE_HANDLER(handler) \
static PipelineHandlerFactory<handler> global_##handler##Factory(#handler);

} /* namespace libcamera */