JeVois  1.18
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 
29 #define ISP_META_WIDTH 272
30 #define ISP_META_HEIGHT 1
31 
32 // ##############################################################################################################
33 jevois::Camera::Camera(std::string const & devname, jevois::CameraSensor s, unsigned int const nbufs) :
34  jevois::VideoInput(devname, nbufs), itsSensor(s)
35 {
36  JEVOIS_TRACE(1);
37 
38  JEVOIS_TIMED_LOCK(itsMtx);
39  /*
40 #ifdef JEVOIS_PLATFORM_A33
41  // Get the sensor flags (if supported, currently only JeVois-A33 platform):
42  itsFlags = readFlags();
43  LDEBUG("Sensor " << s << (itsFlags & JEVOIS_SENSOR_MONO) ? " Monochrome" : " Color" <<
44  (itsFlags & JEVOIS_SENSOR_ICM20948) ? " with ICM20948 IMU" : " ");
45 #endif
46  */
47 }
48 
49 #ifdef JEVOIS_PLATFORM_PRO
50 // ##############################################################################################################
51 void jevois::Camera::setFormat(jevois::VideoMapping const & m)
52 {
53  JEVOIS_TRACE(2);
54 
55  JEVOIS_TIMED_LOCK(itsMtx);
56 
57  // Destroy our devices, if any, in reverse order of creation:
58  while (itsDev.empty() == false) itsDev.pop_back();
59 
60  // The IMX290 sensor only works well at native 1920x1080 with the JeVoisPro A311D ISP. So we always capture at 1080p
61  // and use crop/rescale in the ISP for other resolutions:
62  unsigned int capw = m.cw, caph = m.ch;
63  if (itsSensor == jevois::CameraSensor::imx290)
64  {
65  capw = 1920; caph = 1080;
66  LINFO("imx290: using native video capture size " << capw << 'x' << caph << " + crop/resize as needed");
67  }
68 
69  // Check desired capture size, compute crop and scaling:
70  if (m.cw > capw || m.ch > caph)
71  LFATAL("Sensor cannot capture desired " << m.cw << 'x' << m.ch << ": max is " << capw << 'x' << caph);
72 
73  // Crop or scale or both:
74  switch (m.crop)
75  {
77  {
78  if (capw == m.cw && caph == m.ch) LINFO("Capture: " << capw << 'x' << caph);
79  else LINFO("Capture: " << capw << 'x' << caph << ", crop to " << m.cw << 'x' << m.ch);
80 
81  // Open one device: raw frame
82  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false));
83  itsDev.back()->setFormat(m.cfmt, capw, caph, m.cfps, m.cw, m.ch);
84 
85  itsFd = itsDev.back()->getFd(); itsDevIdx = itsDev.size() - 1;
86  itsFd2 = -1; itsDev2Idx = -1;
87  }
88  break;
89 
90  case jevois::CropType::Scale:
91  {
92  LINFO("Capture: " << capw << 'x' << caph << ", rescale to " << m.cw << 'x' << m.ch);
93 
94  // Open 3 devices: raw frame, meta data, scaled frame, and set their formats:
95  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, true)); // raw frame
96  itsDev.back()->setFormat(m.cfmt, capw, caph, m.cfps, m.cw, m.ch);
97 
98  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, true)); // metadata
99  itsDev.back()->setFormat(ISP_V4L2_PIX_FMT_META, ISP_META_WIDTH, ISP_META_HEIGHT,
101 
102  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false)); // DS1 frame
103  itsDev.back()->setFormat(m.cfmt, m.cw, m.ch, 0.0F, m.cw, m.ch);
104 
105  itsFd = itsDev.back()->getFd(); itsDevIdx = itsDev.size() - 1;
106  itsFd2 = -1; itsDev2Idx = -1;
107  }
108  break;
109 
110  case jevois::CropType::CropScale:
111  {
112  LINFO("Capture: " << capw << 'x' << caph << ", plus ISP scaled to " << m.c2w << 'x' << m.c2h);
113 
114  // Open 3 devices: raw frame, meta data, scaled frame, and set their formats:
115  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, false)); // raw frame
116  itsDev.back()->setFormat(m.cfmt, capw, caph, m.cfps, m.cw, m.ch);
117 
118  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, 2, true)); // metadata
119  itsDev.back()->setFormat(ISP_V4L2_PIX_FMT_META, ISP_META_WIDTH, ISP_META_HEIGHT,
121 
122  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false)); // DS1 frame
123  itsDev.back()->setFormat(m.c2fmt, m.c2w, m.c2h, m.cfps, m.c2w, m.c2h);
124 
125  itsFd = itsDev.front()->getFd(); itsDevIdx = 0;
126  itsFd2 = itsDev.back()->getFd(); itsDev2Idx = itsDev.size() - 1;
127  }
128  break;
129 
130  default: LFATAL("Invalid crop type: " << int(m.crop));
131  }
132 }
133 
134 #else // JEVOIS_PLATFORM_PRO
135 // ##############################################################################################################
136 void jevois::Camera::setFormat(jevois::VideoMapping const & m)
137 {
138  JEVOIS_TRACE(2);
139 
140  JEVOIS_TIMED_LOCK(itsMtx);
141 
142  // Destroy our devices, if any, in reverse order of creation:
143  while (itsDev.empty() == false) itsDev.pop_back();
144 
145  // Open one device: raw frame, no cropping or scaling supported:
146  itsDev.push_back(std::make_shared<jevois::CameraDevice>(itsDevName, itsNbufs, false));
147  itsDev.back()->setFormat(m.cfmt, m.cw, m.ch, m.cfps, m.cw, m.ch);
148  itsFd = itsDev.back()->getFd(); itsDevIdx = itsDev.size() - 1;
149  itsFd2 = -1; itsDev2Idx = -1;
150 }
151 #endif // JEVOIS_PLATFORM_PRO
152 
153 // ##############################################################################################################
155 {
156  JEVOIS_TRACE(1);
157 
158  // Turn off streaming if it was on:
159  try { streamOff(); } catch (...) { jevois::warnAndIgnoreException(); }
160 
161  // Close all devices:
162  itsDev.clear();
163 }
164 
165 // ##############################################################################################################
167 {
168  JEVOIS_TRACE(2);
169  JEVOIS_TIMED_LOCK(itsMtx);
170 
171  for (auto & dev : itsDev) try { dev->streamOn(); } catch (...) { jevois::warnAndIgnoreException(); }
172 }
173 
174 // ##############################################################################################################
176 {
177  JEVOIS_TRACE(2);
178  JEVOIS_TIMED_LOCK(itsMtx);
179 
180  for (auto & dev : itsDev) try { dev->abortStream(); } catch (...) { jevois::warnAndIgnoreException(); }
181 }
182 
183 // ##############################################################################################################
185 {
186  JEVOIS_TRACE(2);
187  JEVOIS_TIMED_LOCK(itsMtx);
188 
189  for (auto & dev : itsDev) try { dev->streamOff(); } catch (...) { jevois::warnAndIgnoreException(); }
190 }
191 
192 // ##############################################################################################################
194 {
195  JEVOIS_TRACE(4);
196  JEVOIS_TIMED_LOCK(itsMtx);
197  if (itsDevIdx == -1) LFATAL("Need to call setFormat() first");
198  itsDev[itsDevIdx]->get(img);
199 }
200 
201 // ##############################################################################################################
203 {
204  return (itsDev2Idx != -1);
205 }
206 
207 // ##############################################################################################################
209 {
210  JEVOIS_TRACE(4);
211  JEVOIS_TIMED_LOCK(itsMtx);
212 
213  if (itsDev2Idx == -1) LFATAL("No JeVois Pro Platform ISP-scaled image available");
214  itsDev[itsDev2Idx]->get(img);
215 }
216 
217 // ##############################################################################################################
219 {
220  JEVOIS_TRACE(4);
221  JEVOIS_TIMED_LOCK(itsMtx);
222  if (itsDevIdx == -1) LFATAL("Need to call setFormat() first");
223  itsDev[itsDevIdx]->done(img);
224 }
225 
226 // ##############################################################################################################
228 {
229  JEVOIS_TRACE(4);
230  JEVOIS_TIMED_LOCK(itsMtx);
231  if (itsDev2Idx == -1) LFATAL("No JeVois Pro Platform ISP-scaled image available");
232  itsDev[itsDev2Idx]->done(img);
233 }
234 
235 // ##############################################################################################################
236 void jevois::Camera::queryControl(struct v4l2_queryctrl & qc) const
237 {
238  JEVOIS_TIMED_LOCK(itsMtx);
239  if (itsFd == -1) LFATAL("Not initialized");
240  XIOCTL_QUIET(itsFd, VIDIOC_QUERYCTRL, &qc);
241 }
242 
243 // ##############################################################################################################
244 void jevois::Camera::queryMenu(struct v4l2_querymenu & qm) const
245 {
246  JEVOIS_TIMED_LOCK(itsMtx);
247  if (itsFd == -1) LFATAL("Not initialized");
248  XIOCTL_QUIET(itsFd, VIDIOC_QUERYMENU, &qm);
249 }
250 
251 // ##############################################################################################################
252 void jevois::Camera::getControl(struct v4l2_control & ctrl) const
253 {
254  JEVOIS_TIMED_LOCK(itsMtx);
255  if (itsFd == -1) LFATAL("Not initialized");
256 #ifdef JEVOIS_PLATFORM_A33
257  XIOCTL_QUIET(itsFd, 0xc00c561b /* should be VIDIOC_G_CTRL, bug in kernel headers? */, &ctrl);
258 #else
259  XIOCTL_QUIET(itsFd, VIDIOC_G_CTRL, &ctrl);
260 #endif
261 }
262 
263 // ##############################################################################################################
264 void jevois::Camera::setControl(struct v4l2_control const & ctrl)
265 {
266  JEVOIS_TIMED_LOCK(itsMtx);
267  if (itsFd == -1) LFATAL("Not initialized");
268 #ifdef JEVOIS_PLATFORM_A33
269  XIOCTL_QUIET(itsFd, 0xc00c561c /* should be VIDIOC_S_CTRL, bug in kernel headers? */, &ctrl);
270 #else
271  XIOCTL_QUIET(itsFd, VIDIOC_S_CTRL, &ctrl);
272 #endif
273 }
274 
275 // ##############################################################################################################
276 void jevois::Camera::writeRegister(unsigned short reg, unsigned short val)
277 {
278  JEVOIS_TIMED_LOCK(itsMtx);
279  if (itsFd == -1) LFATAL("Not initialized");
280  unsigned short data[2] = { reg, val };
281 
282  LDEBUG("Writing 0x" << std::hex << val << " to 0x" << reg);
283  XIOCTL(itsFd, _IOW('V', 192, int), data);
284 }
285 
286 // ##############################################################################################################
287 unsigned short jevois::Camera::readRegister(unsigned short reg)
288 {
289  JEVOIS_TIMED_LOCK(itsMtx);
290  if (itsFd == -1) LFATAL("Not initialized");
291  unsigned short data[2] = { reg, 0 };
292 
293  XIOCTL(itsFd, _IOWR('V', 193, int), data);
294  LDEBUG("Register 0x" << std::hex << reg << " has value 0x" << data[1]);
295  return data[1];
296 }
297 
298 // ##############################################################################################################
300 {
301  itsMtx.lock();
302  if (itsFd == -1) LFATAL("Not initialized");
303  return itsFd;
304 }
305 
306 // ##############################################################################################################
308 {
309  itsMtx.unlock();
310 }
311 
312 // ##############################################################################################################
314 {
315  JEVOIS_TIMED_LOCK(itsMtx);
316  if (itsFd == -1) LFATAL("Not initialized");
317 
318  int data;
319  try { XIOCTL(itsFd, _IOWR('V', 198, int), &data); } catch (...) { return jevois::Camera::JEVOIS_SENSOR_COLOR; }
320  return Flags(data);
321 }
322 
ISP_META_WIDTH
#define ISP_META_WIDTH
Definition: Camera.C:29
jevois::Camera::done
void done(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get()
Definition: Camera.C:218
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::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:244
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:227
JEVOIS_TRACE
#define JEVOIS_TRACE(level)
Trace object.
Definition: Log.H:296
jevois::Camera::~Camera
~Camera()
Close the device and free all resources.
Definition: Camera.C:154
jevois
Definition: Concepts.dox:1
F
float F
Definition: GUIhelper.C:1968
Log.H
jevois::Camera::readFlags
Flags readFlags()
Get the sensor flags.
Definition: Camera.C:313
jevois::Camera::queryControl
void queryControl(struct v4l2_queryctrl &qc) const override
Get information about a control, throw if unsupported by hardware.
Definition: Camera.C:236
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:193
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:287
jevois::Camera::streamOn
void streamOn() override
Start streaming.
Definition: Camera.C:166
Camera.H
jevois::Camera::lock
int lock()
Lock the camera and return its file descriptor.
Definition: Camera.C:299
jevois::Camera::getControl
void getControl(struct v4l2_control &ctrl) const
Get a control's current value, throw if unsupported by hardware.
Definition: Camera.C:252
jevois::Camera::setFormat
void setFormat(VideoMapping const &m) override
Set the video format and frame rate.
Definition: Camera.C:51
jevois::Camera::unlock
void unlock()
Unlock the camera that was previously locked by lock()
Definition: Camera.C:307
jevois::Camera::Flags
Flags
Sensor flags.
Definition: Camera.H:163
jevois::Camera::streamOff
void streamOff() override
Stop streaming.
Definition: Camera.C:184
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:33
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:202
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:264
jevois::Camera::get2
void get2(RawImage &img) override
Get the next captured buffer, for second ISP-scaled image.
Definition: Camera.C:208
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:175
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:276
ISP_META_HEIGHT
#define ISP_META_HEIGHT
Definition: Camera.C:30