JeVois  1.21
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Loading...
Searching...
No Matches
Camera.C
Go to the documentation of this file.
1// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2//
3// JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4// California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5//
6// This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7// redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8// Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10// License for more details. You should have received a copy of the GNU General Public License along with this program;
11// if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12//
13// Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14// Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16/*! \file */
17
18#include <jevois/Core/Camera.H>
19#include <jevois/Debug/Log.H>
20#include <jevois/Util/Utils.H>
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <fstream>
29
30#define ISP_META_WIDTH 272
31#define ISP_META_HEIGHT 1
32
33// ##############################################################################################################
34jevois::Camera::Camera(std::string const & devname, jevois::CameraSensor s, unsigned int const nbufs) :
35 jevois::VideoInput(devname, nbufs), itsSensor(s)
36{
37 JEVOIS_TRACE(1);
38
39#ifdef JEVOIS_PLATFORM_A33
40 // Get the sensor flags (if supported, currently only JeVois-A33 platform):
41 itsFlags = readFlags();
42 LDEBUG("Sensor " << s << (itsFlags & JEVOIS_SENSOR_MONO) ? " Monochrome" : " Color" <<
43 (itsFlags & JEVOIS_SENSOR_ICM20948) ? " with ICM20948 IMU" : " ");
44#endif
45}
46
47#ifdef JEVOIS_PLATFORM_PRO
48// ##############################################################################################################
50{
51 JEVOIS_TRACE(2);
52
53 JEVOIS_TIMED_LOCK(itsMtx);
54
55 // Destroy our devices, if any, in reverse order of creation:
56 while (itsDev.empty() == false) itsDev.pop_back();
57
58 // Load sensor preset sequence if needed, get the native sensor capture dims for requested format:
59 unsigned int capw = m.cw, caph = m.ch; int preset = -1;
60 jevois::sensorPrepareSetFormat(itsSensor, m, capw, caph, preset);
61 std::string pstr; if (preset != -1) pstr = " [preset " + std::to_string(preset) + ']';
62 LINFO(itsSensor << ": using native video capture size " << capw << 'x' << caph << pstr << " + crop/resize as needed");
63
64 // Crop or scale or both:
65 switch (m.crop)
66 {
67 case jevois::CropType::Scale:
68 {
69 // Start 3 streams to get the scaled image in the third one. If desired capture size is the same as native sensor
70 // size, revert to single-stream crop mode instead of scale:
71 if (capw != m.cw || caph != m.ch)
72 {
73 LINFO("Capture: " << capw << 'x' << caph << ", rescale to " << m.cw << 'x' << m.ch);
74
75 // Open 3 devices: raw frame, meta data, scaled frame, and set their formats:
76 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, true)); // raw frame
77 itsDev.back()->setFormat(m.cfmt, capw, caph, m.cfps, m.cw, m.ch, preset);
78
79 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, true)); // metadata
80 itsDev.back()->setFormat(ISP_V4L2_PIX_FMT_META, ISP_META_WIDTH, ISP_META_HEIGHT,
82
83 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false)); // DS1 frame
84 itsDev.back()->setFormat(m.cfmt, m.cw, m.ch, 0.0F, m.cw, m.ch);
85
86 itsFd = itsDev.back()->getFd(); itsDevIdx = itsDev.size() - 1;
87 itsFd2 = -1; itsDev2Idx = -1;
88 break;
89 }
90 }
91 // fall-through ...
92
93 case jevois::CropType::Crop:
94 {
95 if (capw == m.cw && caph == m.ch) LINFO("Capture: " << capw << 'x' << caph);
96 else LINFO("Capture: " << capw << 'x' << caph << ", crop to " << m.cw << 'x' << m.ch);
97
98 // Open one device: raw frame
99 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false));
100 itsDev.back()->setFormat(m.cfmt, capw, caph, m.cfps, m.cw, m.ch, preset);
101
102 itsFd = itsDev.back()->getFd(); itsDevIdx = itsDev.size() - 1;
103 itsFd2 = -1; itsDev2Idx = -1;
104 }
105 break;
106
107 case jevois::CropType::CropScale:
108 {
109 LINFO("Capture: " << capw << 'x' << caph << ", plus ISP scaled to " << m.c2w << 'x' << m.c2h);
110
111 // Open 3 devices: raw frame, meta data, scaled frame, and set their formats:
112 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, false)); // raw frame
113 itsDev.back()->setFormat(m.cfmt, capw, caph, m.cfps, m.cw, m.ch, preset);
114
115 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, true)); // metadata
116 itsDev.back()->setFormat(ISP_V4L2_PIX_FMT_META, ISP_META_WIDTH, ISP_META_HEIGHT,
118
119 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false)); // DS1 frame
120 itsDev.back()->setFormat(m.c2fmt, m.c2w, m.c2h, m.cfps, m.c2w, m.c2h);
121
122 itsFd = itsDev.front()->getFd(); itsDevIdx = 0;
123 itsFd2 = itsDev.back()->getFd(); itsDev2Idx = itsDev.size() - 1;
124 }
125 break;
126
127 default: LFATAL("Invalid crop type: " << int(m.crop));
128 }
129}
130
131#else // JEVOIS_PLATFORM_PRO
132// ##############################################################################################################
134{
135 JEVOIS_TRACE(2);
136
137 JEVOIS_TIMED_LOCK(itsMtx);
138
139 // Destroy our devices, if any, in reverse order of creation:
140 while (itsDev.empty() == false) itsDev.pop_back();
141
142 // Open one device: raw frame, no cropping or scaling supported:
143 itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false));
144 itsDev.back()->setFormat(m.cfmt, m.cw, m.ch, m.cfps, m.cw, m.ch);
145 itsFd = itsDev.back()->getFd(); itsDevIdx = itsDev.size() - 1;
146 itsFd2 = -1; itsDev2Idx = -1;
147}
148#endif // JEVOIS_PLATFORM_PRO
149
150// ##############################################################################################################
152{
153 JEVOIS_TRACE(1);
154
155 // Turn off streaming if it was on:
156 try { streamOff(); } catch (...) { jevois::warnAndIgnoreException(); }
157
158 // Close all devices:
159 itsDev.clear();
160}
161
162// ##############################################################################################################
164{
165 JEVOIS_TRACE(2);
166 JEVOIS_TIMED_LOCK(itsMtx);
167
168 for (auto & dev : itsDev) try { dev->streamOn(); } catch (...) { jevois::warnAndIgnoreException(); }
169}
170
171// ##############################################################################################################
173{
174 JEVOIS_TRACE(2);
175 JEVOIS_TIMED_LOCK(itsMtx);
176
177 for (auto & dev : itsDev) try { dev->abortStream(); } catch (...) { jevois::warnAndIgnoreException(); }
178}
179
180// ##############################################################################################################
182{
183 JEVOIS_TRACE(2);
184 JEVOIS_TIMED_LOCK(itsMtx);
185
186 for (auto & dev : itsDev) try { dev->streamOff(); } catch (...) { jevois::warnAndIgnoreException(); }
187}
188
189// ##############################################################################################################
191{
192 JEVOIS_TRACE(4);
193 JEVOIS_TIMED_LOCK(itsMtx);
194 if (itsDevIdx == -1) LFATAL("Need to call setFormat() first");
195 itsDev[itsDevIdx]->get(img);
196}
197
198// ##############################################################################################################
200{
201 return (itsDev2Idx != -1);
202}
203
204// ##############################################################################################################
206{
207 JEVOIS_TRACE(4);
208 JEVOIS_TIMED_LOCK(itsMtx);
209
210 if (itsDev2Idx == -1) LFATAL("No JeVois Pro Platform ISP-scaled image available");
211 itsDev[itsDev2Idx]->get(img);
212}
213
214// ##############################################################################################################
216{
217 JEVOIS_TRACE(4);
218 JEVOIS_TIMED_LOCK(itsMtx);
219 if (itsDevIdx == -1) LFATAL("Need to call setFormat() first");
220 itsDev[itsDevIdx]->done(img);
221}
222
223// ##############################################################################################################
225{
226 JEVOIS_TRACE(4);
227 JEVOIS_TIMED_LOCK(itsMtx);
228 if (itsDev2Idx == -1) LFATAL("No JeVois Pro Platform ISP-scaled image available");
229 itsDev[itsDev2Idx]->done(img);
230}
231
232// ##############################################################################################################
233void jevois::Camera::queryControl(struct v4l2_queryctrl & qc) const
234{
235 JEVOIS_TIMED_LOCK(itsMtx);
236 if (itsFd == -1) LFATAL("Not initialized");
237 XIOCTL_QUIET(itsFd, VIDIOC_QUERYCTRL, &qc);
238}
239
240// ##############################################################################################################
241void jevois::Camera::queryMenu(struct v4l2_querymenu & qm) const
242{
243 JEVOIS_TIMED_LOCK(itsMtx);
244 if (itsFd == -1) LFATAL("Not initialized");
245 XIOCTL_QUIET(itsFd, VIDIOC_QUERYMENU, &qm);
246}
247
248// ##############################################################################################################
249void jevois::Camera::getControl(struct v4l2_control & ctrl) const
250{
251 JEVOIS_TIMED_LOCK(itsMtx);
252 if (itsFd == -1) LFATAL("Not initialized");
253#ifdef JEVOIS_PLATFORM_A33
254 XIOCTL_QUIET(itsFd, 0xc00c561b /* should be VIDIOC_G_CTRL, bug in kernel headers? */, &ctrl);
255#else
256 XIOCTL_QUIET(itsFd, VIDIOC_G_CTRL, &ctrl);
257#endif
258}
259
260// ##############################################################################################################
261void jevois::Camera::setControl(struct v4l2_control const & ctrl)
262{
263 JEVOIS_TIMED_LOCK(itsMtx);
264 if (itsFd == -1) LFATAL("Not initialized");
265#ifdef JEVOIS_PLATFORM_A33
266 XIOCTL_QUIET(itsFd, 0xc00c561c /* should be VIDIOC_S_CTRL, bug in kernel headers? */, &ctrl);
267#else
268 XIOCTL_QUIET(itsFd, VIDIOC_S_CTRL, &ctrl);
269#endif
270}
271
272// ##############################################################################################################
273void jevois::Camera::writeRegister(unsigned short reg, unsigned short val)
274{
275 JEVOIS_TIMED_LOCK(itsMtx);
276 if (itsFd == -1) LFATAL("Not initialized");
277
278#ifdef JEVOIS_PRO
279 std::ofstream ofs("/sys/devices/platform/sensor/sreg");
280 ofs << jevois::sformat("w %x %x\n", reg, val);
281#else
282 unsigned short data[2] = { reg, val };
283 LDEBUG("Writing 0x" << std::hex << val << " to 0x" << reg);
284 XIOCTL(itsFd, _IOW('V', 192, int), data);
285#endif
286}
287
288// ##############################################################################################################
289unsigned short jevois::Camera::readRegister(unsigned short reg)
290{
291 JEVOIS_TIMED_LOCK(itsMtx);
292 if (itsFd == -1) LFATAL("Not initialized");
293#ifdef JEVOIS_PRO
294 {
295 std::ofstream ofs("/sys/devices/platform/sensor/sreg");
296 ofs << jevois::sformat("r %x\n", reg);
297 }
298 std::ifstream ifs("/sys/devices/platform/sensor/sreg");
299 unsigned short val; ifs >> std::hex >> val;
300 return val;
301#else
302 unsigned short data[2] = { reg, 0 };
303 XIOCTL(itsFd, _IOWR('V', 193, int), data);
304 LDEBUG("Register 0x" << std::hex << reg << " has value 0x" << data[1]);
305 return data[1];
306#endif
307}
308
309// ##############################################################################################################
311{
312 itsMtx.lock();
313 if (itsFd == -1) LFATAL("Not initialized");
314 return itsFd;
315}
316
317// ##############################################################################################################
319{
320 itsMtx.unlock();
321}
322
323// ##############################################################################################################
325{
326 int fd = open(itsDevName.c_str(), O_RDWR | O_NONBLOCK, 0);
327 if (fd == -1) { LERROR("Camera device open fail on " << itsDevName); return jevois::Camera::JEVOIS_SENSOR_COLOR; }
328
329 int data;
330 try { XIOCTL(fd, _IOWR('V', 198, int), &data); }
331 catch (...) { close(fd); return jevois::Camera::JEVOIS_SENSOR_COLOR; }
332 close(fd);
333
334 return Flags(data);
335}
336
#define ISP_META_HEIGHT
Definition Camera.C:31
#define ISP_META_WIDTH
Definition Camera.C:30
#define ISP_V4L2_PIX_FMT_META
Metadata V4L2 format used by Amlogic A311D camera ISP.
Definition Utils.H:27
void abortStream() override
Abort streaming.
Definition Camera.C:172
unsigned short readRegister(unsigned short reg)
Read a value from one of the camera's registers.
Definition Camera.C:289
void getControl(struct v4l2_control &ctrl) const
Get a control's current value, throw if unsupported by hardware.
Definition Camera.C:249
~Camera()
Close the device and free all resources.
Definition Camera.C:151
void setFormat(VideoMapping const &m) override
Set the video format and frame rate.
Definition Camera.C:49
void get(RawImage &img) override
Get the next captured buffer.
Definition Camera.C:190
Camera(std::string const &devname, jevois::CameraSensor s=jevois::CameraSensor::any, unsigned int const nbufs=0)
Construct and open the device.
Definition Camera.C:34
void done2(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get2()
Definition Camera.C:224
bool hasScaledImage() const override
Check whether a second input image scaled by the JeVoisPro Platform ISP is available.
Definition Camera.C:199
void get2(RawImage &img) override
Get the next captured buffer, for second ISP-scaled image.
Definition Camera.C:205
void unlock()
Unlock the camera that was previously locked by lock()
Definition Camera.C:318
void streamOn() override
Start streaming.
Definition Camera.C:163
void setControl(struct v4l2_control const &ctrl) override
Set a control, throw if control not supported or the hardware rejects the value.
Definition Camera.C:261
Flags
Sensor flags.
Definition Camera.H:165
@ JEVOIS_SENSOR_COLOR
Definition Camera.H:166
@ JEVOIS_SENSOR_MONO
Definition Camera.H:167
@ JEVOIS_SENSOR_ICM20948
Definition Camera.H:168
Flags readFlags()
Get the sensor flags.
Definition Camera.C:324
void queryMenu(struct v4l2_querymenu &qm) const override
Get the available menu entry names for a menu-type control, throw if unsupported by hardware.
Definition Camera.C:241
int lock()
Lock the camera and return its file descriptor.
Definition Camera.C:310
void queryControl(struct v4l2_queryctrl &qc) const override
Get information about a control, throw if unsupported by hardware.
Definition Camera.C:233
void streamOff() override
Stop streaming.
Definition Camera.C:181
void done(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get()
Definition Camera.C:215
void writeRegister(unsigned short reg, unsigned short val)
Write a value to one of the camera's registers.
Definition Camera.C:273
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition RawImage.H:111
Base class for video input, which will get derived into Camera and MovieInput.
Definition VideoInput.H:32
void sensorPrepareSetFormat(CameraSensor s, VideoMapping const &m, unsigned int &capw, unsigned int &caph, int &preset)
Load a sensor preset (JeVois-Pro only) and return native sensor grab dims (when cropping and/or scali...
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
Definition Log.H:230
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
Definition Log.H:173
#define JEVOIS_TIMED_LOCK(mtx)
Helper macro to create a timed_lock_guard object.
Definition Log.H:328
std::string warnAndIgnoreException(std::string const &prefix="")
Convenience function to catch an exception, issue some LERROR (depending on type),...
Definition Log.C:236
#define JEVOIS_TRACE(level)
Trace object.
Definition Log.H:296
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
Definition Log.H:211
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition Log.H:194
#define XIOCTL_QUIET(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error throw quietly.
Definition Utils.H:216
std::string sformat(char const *fmt,...) __attribute__((format(__printf__
Create a string using printf style arguments.
Definition Utils.C:439
#define XIOCTL(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error, issue a fatal message and thro...
Definition Utils.H:205
Main namespace for all JeVois classes and functions.
Definition Concepts.dox:2
Simple struct to hold video mapping definitions for the processing Engine.
unsigned int cfmt
camera pixel format
unsigned int c2fmt
When crop is CropScale, pixel format of the scaled images, otherwise 0.
unsigned int c2w
When crop is CropScale, width of the scaled images, otherwise 0.
CropType crop
Type of crop/scale to apply if camera size does not match sensor native.
float cfps
camera frame rate in frames/sec
unsigned int cw
camera width
unsigned int c2h
When crop is CropScale, height of the scaled images, otherwise 0.
unsigned int ch
camera height