JeVois  1.20
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
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 // ##############################################################################################################
34 jevois::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 // ##############################################################################################################
49 void jevois::Camera::setFormat(jevois::VideoMapping const & m)
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 
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 // ##############################################################################################################
133 void jevois::Camera::setFormat(jevois::VideoMapping const & m)
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 // ##############################################################################################################
233 void 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 // ##############################################################################################################
241 void 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 // ##############################################################################################################
249 void 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 // ##############################################################################################################
261 void 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 // ##############################################################################################################
273 void 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 // ##############################################################################################################
289 unsigned 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 
ISP_META_WIDTH
#define ISP_META_WIDTH
Definition: Camera.C:30
jevois::Camera::done
void done(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get()
Definition: Camera.C:215
LDEBUG
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
Definition: Log.H:173
RawImageOps.H
JEVOIS_TIMED_LOCK
#define JEVOIS_TIMED_LOCK(mtx)
Helper macro to create a timed_lock_guard object.
Definition: Log.H:328
jevois::Camera::JEVOIS_SENSOR_ICM20948
@ JEVOIS_SENSOR_ICM20948
Definition: Camera.H:167
jevois::Camera::JEVOIS_SENSOR_MONO
@ JEVOIS_SENSOR_MONO
Definition: Camera.H:166
jevois::sformat
std::string sformat(char const *fmt,...) __attribute__((format(__printf__
Create a string using printf style arguments.
Definition: Utils.C:439
jevois::VideoInput
Base class for video input, which will get derived into Camera and MovieInput.
Definition: VideoInput.H:31
jevois::Camera::queryMenu
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
jevois::RawImage
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
ISP_V4L2_PIX_FMT_META
#define ISP_V4L2_PIX_FMT_META
Metadata V4L2 format used by Amlogic A311D camera ISP.
Definition: Utils.H:27
jevois::Camera::done2
void done2(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get2()
Definition: Camera.C:224
JEVOIS_TRACE
#define JEVOIS_TRACE(level)
Trace object.
Definition: Log.H:296
LERROR
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
Definition: Log.H:211
jevois::Camera::~Camera
~Camera()
Close the device and free all resources.
Definition: Camera.C:151
jevois
Definition: Concepts.dox:1
F
float F
Definition: GUIhelper.C:2373
Log.H
jevois::Camera::readFlags
Flags readFlags()
Get the sensor flags.
Definition: Camera.C:324
jevois::Camera::queryControl
void queryControl(struct v4l2_queryctrl &qc) const override
Get information about a control, throw if unsupported by hardware.
Definition: Camera.C:233
jevois::sensorPrepareSetFormat
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...
jevois::Crop
() Scale() Crop(CropScale)) struct VideoMapping
Simple struct to hold video mapping definitions for the processing Engine.
Definition: VideoMapping.H:43
jevois::Camera::get
void get(RawImage &img) override
Get the next captured buffer.
Definition: Camera.C:190
jevois::warnAndIgnoreException
std::string warnAndIgnoreException(std::string const &prefix="")
Convenience function to catch an exception, issue some LERROR (depending on type),...
Definition: Log.C:236
LFATAL
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
VideoMapping.H
jevois::Camera::readRegister
unsigned short readRegister(unsigned short reg)
Read a value from one of the camera's registers.
Definition: Camera.C:289
jevois::Camera::streamOn
void streamOn() override
Start streaming.
Definition: Camera.C:163
Camera.H
jevois::Camera::lock
int lock()
Lock the camera and return its file descriptor.
Definition: Camera.C:310
jevois::Camera::getControl
void getControl(struct v4l2_control &ctrl) const
Get a control's current value, throw if unsupported by hardware.
Definition: Camera.C:249
jevois::to_string
std::string to_string(T const &val)
Convert from type to string.
jevois::Camera::setFormat
void setFormat(VideoMapping const &m) override
Set the video format and frame rate.
Definition: Camera.C:49
jevois::Camera::unlock
void unlock()
Unlock the camera that was previously locked by lock()
Definition: Camera.C:318
jevois::Camera::Flags
Flags
Sensor flags.
Definition: Camera.H:163
jevois::Camera::streamOff
void streamOff() override
Stop streaming.
Definition: Camera.C:181
jevois::Camera::Camera
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
Utils.H
jevois::Camera::hasScaledImage
bool hasScaledImage() const override
Check whether a second input image scaled by the JeVoisPro Platform ISP is available.
Definition: Camera.C:199
jevois::Camera::setControl
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
jevois::Camera::get2
void get2(RawImage &img) override
Get the next captured buffer, for second ISP-scaled image.
Definition: Camera.C:205
LINFO
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:194
jevois::Camera::abortStream
void abortStream() override
Abort streaming.
Definition: Camera.C:172
jevois::Camera::JEVOIS_SENSOR_COLOR
@ JEVOIS_SENSOR_COLOR
Definition: Camera.H:165
jevois::Camera::writeRegister
void writeRegister(unsigned short reg, unsigned short val)
Write a value to one of the camera's registers.
Definition: Camera.C:273
ISP_META_HEIGHT
#define ISP_META_HEIGHT
Definition: Camera.C:31