-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
246 lines (212 loc) · 7.07 KB
/
main.cpp
File metadata and controls
246 lines (212 loc) · 7.07 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <memory>
#include <mutex>
#include <thread>
#include <atomic>
#include <sys/mman.h>
#include <QApplication>
#include <QImage>
#include <QLabel>
#include <QMainWindow>
#include <libcamera/libcamera.h>
// flag to indicate that threads should now exit
std::atomic_bool quitThread;
// flag to indicate if requestHasCompleted
std::atomic_bool reqCompleted = true;
/* We use createReq to send 1 request,
* we don't want it
*/
std::mutex requestLock;
//Temp header brightness ctrl
float brightnessVal = 0.0;
#include "main.h"
static void requestComplete(Request *request)
{
std::cout << "Entered requestComplete \n";
std::unique_lock rlck(requestLock);
std::cout << "Entered requestComplete and locked\n";
if (request->status() == Request::RequestCancelled)
return;
// Extract the frambuffer filled with images
auto &buffers = request->buffers();
// Iterate over the buffer pairs
// [Stream,FrameBuffer] and
// print the metadata associated
for (auto bufferPair : buffers)
{
FrameBuffer *buffer = bufferPair.second;
const FrameMetadata &metadata = buffer->metadata();
std::cout << " seq: " << std::setw(6) << std::setfill('0') << metadata.sequence << '\n';
// Find the size of the buffer
const FrameBuffer::Plane &plane = buffer->planes().front();
size_t size = buffer->metadata().planes().front().bytesused;
void *mem = mmap(NULL, plane.length, PROT_READ, MAP_SHARED, plane.fd.get(), 0);
viewfinder.loadFromData((const unsigned char *)mem, int(size));
viewfinder_label->setPixmap(QPixmap::fromImage(viewfinder));
viewfinder_label->show();
munmap(mem, size);
}
requestList.pop_back();
reqCompleted = true;
// request->reuse(Request::ReuseBuffers); // No reusing as the paramters may change hence create a new request
// camera->queueRequest(request);
}
void createReq(libcamera::Stream *stream, libcamera::FrameBuffer *buffer)
{
while (true)
{
std::cout << "Entered createReq\n";
if (quitThread)
return;
std::unique_lock lck(requestLock);
std::cout << "Entered createReq and locked\n";
if (requestList.size() >= REQUEST_LIST_SIZE)
{
std::cout << "Skipping \n";
continue;
}
std::unique_ptr<Request> request = camera->createRequest();
if (!request)
{
std::cerr << "Couldn't create a request\n";
exit(-ENOMEM);
}
std::cout << "Created req\n";
int ret = request->addBuffer(stream, buffer);
if (ret < 0)
{
std::cerr << "Can't set buffer for request\n";
exit(ret);
}
std::cout << "Added buffer\n";
ControlList &controls = request->controls();
controls.set(controls::Brightness,brightnessVal);
std::cout<<"Brightness :"<<brightnessVal<<'\n';
requestList.push_back(std::move(request));
qReq();
}
}
void qReq()
{
if (quitThread)
return;
std::cout << "Entered qReq\n";
if (!reqCompleted || requestList.empty())
return;
std::cout << "Attempt to Queue request\n";
camera->queueRequest(requestList.back().get());
reqCompleted = false;
std::cout << "Queued request\n";
}
void brightnessChanges(){
std::unique_lock lck(requestLock);
brightnessVal = float(slider->value())/(float)10;
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
viewfinder_label = new QLabel;
slider = new QSlider;
slider->setMaximum(10);
slider->setSingleStep(1);
slider->setValue(0);
slider->setMinimum(-10);
QObject::connect(slider,&QSlider::valueChanged,brightnessChanges);
slider->show();
// Handles to the CameraManager
std::unique_ptr<CameraManager> cm = std::make_unique<CameraManager>();
cm->start();
// Iterate over the camera Ids
for (auto const &cam : cm->cameras())
{
std::cout << "Camera Id: " << cam->id() << '\n';
}
// If we have no camera exit
if (cm->cameras().empty())
{
std::cerr << "No cameras\n";
cm->stop();
return EXIT_FAILURE;
}
// Select a camera
camera = cm->cameras()[0];
std::string camId = camera->id();
// Get the camera lock
camera->acquire();
// Config for the camera
std::unique_ptr<CameraConfiguration> config = camera->generateConfiguration({StreamRole::Viewfinder});
// Get selected camera's StreamConfig
StreamConfiguration &streamConfig = config->at(0);
std::cout << "The default viewFinder config is: " << streamConfig.toString() << '\n';
/* At this point we don't deal with invalid configs
* as we don't make any changes to the config
* this is just a placeholder so I don't forget to check
*/
if (config->validate() == CameraConfiguration::Status::Invalid)
{
std::cerr << "Invalid camera config\n";
return EXIT_FAILURE;
}
// Set the validated or adjusted config
camera->configure(config.get());
FrameBufferAllocator *allocator = new FrameBufferAllocator(camera);
for (StreamConfiguration &cfg : *config)
{
int ret = allocator->allocate(cfg.stream());
if (ret < 0)
{
std::cerr << "Error\n";
return -ENOMEM;
}
size_t allocated_size = allocator->buffers(cfg.stream()).size();
std::cout << "Allocated " << allocated_size << " buffers for stream\n";
}
// Setup a singleStream from the first config
Stream *stream = streamConfig.stream();
const auto &buffers = allocator->buffers(stream);
// std::vector<std::unique_ptr<Request>> requests;
// Register callback function for request completed signal
camera->requestCompleted.connect(requestComplete);
// Q requests to the camera to capture
// for (unsigned int i = 0; i < buffers.size(); ++i)
// {
// std::unique_ptr<Request> request = camera->createRequest();
// if (!request)
// {
// std::cerr << "Couldn't create a request\n";
// return -ENOMEM;
// }
// 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\n";
// return ret;
// }
// requests.push_back(std::move(request));
// }
// Finaly start the camera
camera->start();
std::thread createReqThread(createReq, stream, buffers.front().get());
createReqThread.detach();
// for (std::unique_ptr<libcamera::Request> &request : requests)
// {
// camera->queueRequest(request.get());
// }
// Setup the window
std::cout << "Starting window\n";
int ret = app.exec();
std::cout << "Quiting window\n";
quitThread = true;
// Clean Up
camera->stop();
allocator->free(stream);
delete allocator;
camera->release();
camera.reset();
cm->stop();
delete viewfinder_label;
return ret;
}