-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibcamera_comp.cpp
162 lines (134 loc) · 4.7 KB
/
libcamera_comp.cpp
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//WIP
//TAKEN FROM: https://forums.raspberrypi.com/viewtopic.php?t=347925 AND
//THE MENTIONED SIMPLECAMERA.CPP SCRIPT
#include <libcamera/libcamera.h>
#include "event_loop.h"
using namespace libcamera;
static std::shared_ptr<Camera> camera;
static EventLoop loop;
/*
* --------------------------------------------------------------------
* Handle RequestComplete
*
* For each Camera::requestCompleted Signal emitted from the Camera the
* connected Slot is invoked.
*
* The Slot is invoked in the CameraManager's thread, hence one should avoid
* any heavy processing here. The processing of the request shall be re-directed
* to the application's thread instead, so as not to block the CameraManager's
* thread for large amount of time.
*
* The Slot receives the Request as a parameter.
*/
//EN DEFINITIVA, HABRÁ QUE PASAR LA MAT CREADA AL THREAD DE PROCESAMIENTO
static void processRequest(Request *request);
static void requestComplete(Request *request)
{
if (request->status() == Request::RequestCancelled)
return;
loop.callLater(std::bind(&processRequest, request));
}
static void processRequest(Request *request)
{
const Request::BufferMap &buffers = request->buffers();
for (auto bufferPair : buffers) {
const Stream *stream = bufferPair.first;
FrameBuffer *buffer = bufferPair.second;
StreamConfiguration const &cfg = stream->configuration();
int fd = buffer->planes()[0].fd.get();
uint8_t *ptr = static_cast<uint8_t *>(mmap(NULL, buffer->planes()[0].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
cv::Mat image(cfg.size.height, cfg.size.width, CV_8UC1, ptr, cfg.stride);
}
/* Re-queue the Request to the camera. */
request->reuse(Request::ReuseBuffers);
camera->queueRequest(request);
}
//WIP: EXPECTED FUNCS
//When executed, the thread that calls this func will be the ain thread for libcamera
int StartCamera(CameraManager*& (???) cmm, Camera* cam, FrameBufferAllocator ** FBAlloc, Stream** _stream){
std::unique_ptr<CameraManager> cm = std::make_unique<CameraManager>();
cm->start();
if (cm->cameras().empty()) {
std::cout << "No cameras were identified on the system."
<< std::endl;
cm->stop();
return -1;
}
std::string cameraId = cm->cameras()[0]->id();
cam = cm->get(cameraId);
cam->acquire();
std::unique_ptr<CameraConfiguration> config =
cam->generateConfiguration( { StreamRole::Viewfinder } );
StreamConfiguration &streamConfig = config->at(0);
config->validate();
std::cout << "Validated viewfinder configuration is: "
<< streamConfig.toString() << std::endl;
cam->configure(config.get());
FrameBufferAllocator *allocator = new FrameBufferAllocator(camera);
//WIP *FBAlloc = allocator; ???
for (StreamConfiguration &cfg : *config) {
int ret = allocator->allocate(cfg.stream());
if (ret < 0) {
std::cerr << "Can't allocate buffers" << std::endl;
return -1;
}
size_t allocated = allocator->buffers(cfg.stream()).size();
std::cout << "Allocated " << allocated << " buffers for stream" << std::endl;
}
Stream *stream = streamConfig.stream();
//WIP *_stream = stream ???
const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator->buffers(stream);
std::vector<std::unique_ptr<Request>> requests;
for (unsigned int i = 0; i < buffers.size(); ++i) {
std::unique_ptr<Request> request = camera->createRequest();
if (!request)
{
std::cerr << "Can't create request" << std::endl;
return -1;
}
const std::unique_ptr<FrameBuffer> &buffer = buffers[i];
int ret = request->addBuffer(stream, buffer.get());
if (ret < 0)
{
std::cerr << "Can't set buffer for request"
<< std::endl;
return -1;
}
/*
* Controls can be added to a request on a per frame basis.
*/
//ControlList &controls = request->controls();
//controls.set(controls::Brightness, 0.5);
requests.push_back(std::move(request));
}
cam->requestCompleted.connect(requestComplete);
cam->start();
for (std::unique_ptr<Request> &request : requests)
cam->queueRequest(request.get());
cmm = cm;
return 0;
}
//WIP
int RunEventLoop(){
//WIP: ESTO ES RARO, EL EVENTLOOP TAL VEZ DEBA IR EN EL MAIN? O EN UN THREAD?
/*
* --------------------------------------------------------------------
* Run an EventLoop
*
* In order to dispatch events received from the video devices, such
* as buffer completions, an event loop has to be run.
*/
loop.timeout(3);
int ret = loop.exec();
std::cout << "Capture ran for " << 3 << " seconds and "
<< "stopped with exit status: " << ret << std::endl;
}
//WIP
void FreeLibcamResources(CameraManager*& (???) cmm, Camera* cam, FrameBufferAllocator ** FBAlloc, Stream** _stream){
cam->stop();
FBAlloc->free(_stream);
delete FBAlloc;
cam->release();
cam.reset();
cmm->stop();
}