Apollo 10.0
自动驾驶开放平台
usb_cam.cc
浏览该文件的文档.
1/*********************************************************************
2 *
3 * Software License Agreement (BSD License)
4 *
5 * Copyright (c) 2014, Robert Bosch LLC.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * * Neither the name of the Robert Bosch nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 *********************************************************************/
36
37#include <cmath>
38#include <string>
39
40#ifndef __aarch64__
41#include "adv_trigger.h"
43#endif
44
46
47#define __STDC_CONSTANT_MACROS
48
49#define CLEAR(x) memset(&(x), 0, sizeof(x))
50
51namespace apollo {
52namespace drivers {
53namespace camera {
54
56 : fd_(-1),
57 buffers_(NULL),
58 n_buffers_(0),
59 is_capturing_(false),
60 image_seq_(0),
61 device_wait_sec_(2),
62 last_nsec_(0),
63 frame_drop_interval_(0.0) {}
64
66 stop_capturing();
67 uninit_device();
68 close_device();
69}
70
71bool UsbCam::init(const std::shared_ptr<Config>& cameraconfig) {
72 config_ = cameraconfig;
73
74 if (config_->pixel_format() == "yuyv") {
75 pixel_format_ = V4L2_PIX_FMT_YUYV;
76 } else if (config_->pixel_format() == "uyvy") {
77 pixel_format_ = V4L2_PIX_FMT_UYVY;
78 } else if (config_->pixel_format() == "mjpeg") {
79 pixel_format_ = V4L2_PIX_FMT_MJPEG;
80 } else if (config_->pixel_format() == "yuvmono10") {
81 pixel_format_ = V4L2_PIX_FMT_YUYV;
82 config_->set_monochrome(true);
83 } else if (config_->pixel_format() == "rgb24") {
84 pixel_format_ = V4L2_PIX_FMT_RGB24;
85 } else {
86 pixel_format_ = V4L2_PIX_FMT_YUYV;
87 AERROR << "Wrong pixel fromat:" << config_->pixel_format()
88 << ",must be yuyv | uyvy | mjpeg | yuvmono10 | rgb24";
89 return false;
90 }
91 if (pixel_format_ == V4L2_PIX_FMT_MJPEG) {
92 init_mjpeg_decoder(config_->width(), config_->height());
93 }
94
95 // Warning when diff with last > 1.5* interval
96 frame_warning_interval_ = static_cast<float>(1.5 / config_->frame_rate());
97 // now max fps 30, we use an appox time 0.9 to drop image.
98 frame_drop_interval_ = static_cast<float>(0.9 / config_->frame_rate());
99
100
101 return true;
102}
103
104int UsbCam::init_mjpeg_decoder(int image_width, int image_height) {
105 avcodec_register_all();
106
107 avcodec_ = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
108 if (!avcodec_) {
109 AERROR << "Could not find MJPEG decoder";
110 return 0;
111 }
112
113 avcodec_context_ = avcodec_alloc_context3(avcodec_);
114
115#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
116 avframe_camera_ = av_frame_alloc();
117 avframe_rgb_ = av_frame_alloc();
118
119 avpicture_alloc(reinterpret_cast<AVPicture*>(avframe_rgb_), AV_PIX_FMT_RGB24,
120 image_width, image_height);
121#else
122 avframe_camera_ = avcodec_alloc_frame();
123 avframe_rgb_ = avcodec_alloc_frame();
124
125 avpicture_alloc(reinterpret_cast<AVPicture*>(avframe_rgb_), PIX_FMT_RGB24,
126 image_width, image_height);
127#endif
128
129 avcodec_context_->codec_id = AV_CODEC_ID_MJPEG;
130 avcodec_context_->width = image_width;
131 avcodec_context_->height = image_height;
132
133#if LIBAVCODEC_VERSION_MAJOR > 52
134#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
135 avcodec_context_->pix_fmt = AV_PIX_FMT_YUV422P;
136#else
137 avcodec_context_->pix_fmt = PIX_FMT_YUV422P;
138#endif
139 avcodec_context_->codec_type = AVMEDIA_TYPE_VIDEO;
140#endif
141
142#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
143 avframe_camera_size_ =
144 avpicture_get_size(AV_PIX_FMT_YUV422P, image_width, image_height);
145 avframe_rgb_size_ =
146 avpicture_get_size(AV_PIX_FMT_RGB24, image_width, image_height);
147#else
148 avframe_camera_size_ =
149 avpicture_get_size(PIX_FMT_YUV422P, image_width, image_height);
150 avframe_rgb_size_ =
151 avpicture_get_size(PIX_FMT_RGB24, image_width, image_height);
152#endif
153
154 /* open it */
155 if (avcodec_open2(avcodec_context_, avcodec_, &avoptions_) < 0) {
156 AERROR << "Could not open MJPEG Decoder";
157 return 0;
158 }
159 return 1;
160}
161
162void UsbCam::mjpeg2rgb(char* mjpeg_buffer, int len, char* rgb_buffer,
163 int NumPixels) {
164 (void)NumPixels;
165 int got_picture = 0;
166
167 memset(rgb_buffer, 0, avframe_rgb_size_);
168
169#if LIBAVCODEC_VERSION_MAJOR > 52
170 int decoded_len;
171 AVPacket avpkt;
172 av_init_packet(&avpkt);
173
174 avpkt.size = len;
175 avpkt.data = (unsigned char*)mjpeg_buffer;
176 decoded_len = avcodec_decode_video2(avcodec_context_, avframe_camera_,
177 &got_picture, &avpkt);
178
179 if (decoded_len < 0) {
180 AERROR << "Error while decoding frame.";
181 return;
182 }
183#else
184 avcodec_decode_video(avcodec_context_, avframe_camera_, &got_picture,
185 reinterpret_cast<uint8_t*>(mjpeg_buffer), len);
186#endif
187
188 if (!got_picture) {
189 AERROR << "Camera: expected picture but didn't get it...";
190 return;
191 }
192
193 int xsize = avcodec_context_->width;
194 int ysize = avcodec_context_->height;
195 int pic_size = avpicture_get_size(avcodec_context_->pix_fmt, xsize, ysize);
196 if (pic_size != avframe_camera_size_) {
197 AERROR << "outbuf size mismatch. pic_size:" << pic_size
198 << ",buffer_size:" << avframe_camera_size_;
199 return;
200 }
201
202#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
203 video_sws_ =
204 sws_getContext(xsize, ysize, avcodec_context_->pix_fmt, xsize, ysize,
205 AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
206#else
207 video_sws_ =
208 sws_getContext(xsize, ysize, avcodec_context_->pix_fmt, xsize, ysize,
209 PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
210#endif
211
212 sws_scale(video_sws_, avframe_camera_->data, avframe_camera_->linesize, 0,
213 ysize, avframe_rgb_->data, avframe_rgb_->linesize);
214 sws_freeContext(video_sws_);
215
216#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
217 int size = avpicture_layout(
218 reinterpret_cast<AVPicture*>(avframe_rgb_), AV_PIX_FMT_RGB24, xsize,
219 ysize, reinterpret_cast<uint8_t*>(rgb_buffer), avframe_rgb_size_);
220#else
221 int size = avpicture_layout(
222 reinterpret_cast<AVPicture*>(avframe_rgb_), PIX_FMT_RGB24, xsize, ysize,
223 reinterpret_cast<uint8_t*>(rgb_buffer), avframe_rgb_size_);
224#endif
225 if (size != avframe_rgb_size_) {
226 AERROR << "webcam: avpicture_layout error: " << size;
227 return;
228 }
229}
230
231bool UsbCam::poll(const CameraImagePtr& raw_image,
232 const CameraImagePtr& sensor_raw_image) {
233 raw_image->is_new = 0;
234 // free memory in this struct desturctor
235 memset(raw_image->image, 0, raw_image->image_size * sizeof(char));
236
237 fd_set fds;
238 struct timeval tv;
239 int r = 0;
240
241 FD_ZERO(&fds);
242 FD_SET(fd_, &fds);
243
244 /* Timeout. */
245 tv.tv_sec = 2;
246 tv.tv_usec = 0;
247
248 r = select(fd_ + 1, &fds, nullptr, nullptr, &tv);
249
250 if (-1 == r) {
251 if (EINTR == errno) {
252 return false;
253 }
254
255 // errno_exit("select");
256 reconnect();
257 }
258
259 if (0 == r) {
260 AERROR << "select timeout";
261 reconnect();
262 }
263
264 int get_new_image = read_frame(raw_image, sensor_raw_image);
265
266 if (!get_new_image) {
267 return false;
268 }
269
270 raw_image->is_new = 1;
271 return true;
272}
273
274bool UsbCam::open_device(void) {
275 struct stat st;
276
277 if (-1 == stat(config_->camera_dev().c_str(), &st)) {
278 AERROR << "Cannot identify '" << config_->camera_dev() << "': " << errno
279 << ", " << strerror(errno);
280 return false;
281 }
282
283 if (!S_ISCHR(st.st_mode)) {
284 AERROR << config_->camera_dev() << " is no device";
285 return false;
286 }
287
288 fd_ = open(config_->camera_dev().c_str(), O_RDWR /* required */ | O_NONBLOCK,
289 0);
290
291 if (-1 == fd_) {
292 AERROR << "Cannot open '" << config_->camera_dev() << "': " << errno << ", "
293 << strerror(errno);
294 return false;
295 }
296
297 return true;
298}
299
300bool UsbCam::init_device(void) {
301 struct v4l2_capability cap;
302 struct v4l2_cropcap cropcap;
303 struct v4l2_crop crop;
304 struct v4l2_format fmt;
305 unsigned int min = 0;
306
307 if (-1 == xioctl(fd_, VIDIOC_QUERYCAP, &cap)) {
308 if (EINVAL == errno) {
309 AERROR << config_->camera_dev() << " is no V4L2 device";
310 return false;
311 }
312 AERROR << "VIDIOC_QUERYCAP";
313 return false;
314 }
315
316 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
317 AERROR << config_->camera_dev() << " is no video capture device";
318 return false;
319 }
320
321 switch (config_->io_method()) {
322 case IO_METHOD_READ:
323 if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
324 AERROR << config_->camera_dev() << " does not support read i/o";
325 return false;
326 }
327
328 break;
329
330 case IO_METHOD_MMAP:
332 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
333 AERROR << config_->camera_dev() << " does not support streaming i/o";
334 return false;
335 }
336
337 break;
339 AERROR << config_->camera_dev() << " does not support unknown i/o";
340 return false;
341 break;
342 }
343
344 /* Select video input, video standard and tune here. */
345 CLEAR(cropcap);
346
347 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
348
349 if (0 == xioctl(fd_, VIDIOC_CROPCAP, &cropcap)) {
350 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
351 crop.c = cropcap.defrect; /* reset to default */
352
353 if (-1 == xioctl(fd_, VIDIOC_S_CROP, &crop)) {
354 switch (errno) {
355 case EINVAL:
356 /* Cropping not supported. */
357 break;
358 }
359 }
360 }
361
362 CLEAR(fmt);
363
364 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
365 fmt.fmt.pix.width = config_->width();
366 fmt.fmt.pix.height = config_->height();
367 fmt.fmt.pix.pixelformat = pixel_format_;
368 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
369
370 if (-1 == xioctl(fd_, VIDIOC_S_FMT, &fmt)) {
371 AERROR << "VIDIOC_S_FMT";
372 return false;
373 }
374
375 /* Note VIDIOC_S_FMT may change width and height. */
376
377 /* Buggy driver paranoia. */
378 min = fmt.fmt.pix.width * 2;
379
380 if (fmt.fmt.pix.bytesperline < min) {
381 fmt.fmt.pix.bytesperline = min;
382 }
383
384 min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
385
386 if (fmt.fmt.pix.sizeimage < min) {
387 fmt.fmt.pix.sizeimage = min;
388 }
389
390 config_->set_width(fmt.fmt.pix.width);
391 config_->set_height(fmt.fmt.pix.height);
392
393 struct v4l2_streamparm stream_params;
394 memset(&stream_params, 0, sizeof(stream_params));
395 stream_params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
396
397 // if (xioctl(fd_, VIDIOC_G_PARM, &stream_params) < 0) {
398 // // errno_exit("Couldn't query v4l fps!");
399 // AERROR << "Couldn't query v4l fps!";
400 // // reconnect();
401 // return false;
402 // }
403
404 AINFO << "Capability flag: 0x" << stream_params.parm.capture.capability;
405
406 stream_params.parm.capture.timeperframe.numerator = 1;
407 stream_params.parm.capture.timeperframe.denominator = config_->frame_rate();
408
409 if (xioctl(fd_, VIDIOC_S_PARM, &stream_params) < 0) {
410 AINFO << "Couldn't set camera framerate";
411 } else {
412 AINFO << "Set framerate to be " << config_->frame_rate();
413 }
414
415 switch (config_->io_method()) {
416 case IO_METHOD_READ:
417 init_read(fmt.fmt.pix.sizeimage);
418 break;
419
420 case IO_METHOD_MMAP:
421 init_mmap();
422 break;
423
425 init_userp(fmt.fmt.pix.sizeimage);
426 break;
427
429 AERROR << " does not support unknown i/o";
430 break;
431 }
432
433 return true;
434}
435
436#ifndef __aarch64__
437bool UsbCam::set_adv_trigger() {
438 AINFO << "Trigger enable, dev:" << config_->camera_dev()
439 << ", fps:" << config_->trigger_fps()
440 << ", internal:" << config_->trigger_internal();
441 int ret = adv_trigger_enable(
442 config_->camera_dev().c_str(),
443 static_cast<unsigned char>(config_->trigger_fps()),
444 static_cast<unsigned char>(config_->trigger_internal()));
445 if (ret != 0) {
446 AERROR << "trigger failed:" << ret;
447 return false;
448 }
449 return true;
450}
451#endif
452
453int UsbCam::xioctl(int fd, int request, void* arg) {
454 int r = 0;
455 do {
456 r = ioctl(fd, request, arg);
457 } while (-1 == r && EINTR == errno);
458
459 return r;
460}
461
462bool UsbCam::init_read(unsigned int buffer_size) {
463 buffers_ = reinterpret_cast<buffer*>(calloc(1, sizeof(*buffers_)));
464
465 if (!buffers_) {
466 AERROR << "Out of memory";
467 // exit(EXIT_FAILURE);
468 // reconnect();
469 return false;
470 }
471
472 buffers_[0].length = buffer_size;
473 buffers_[0].start = malloc(buffer_size);
474
475 if (!buffers_[0].start) {
476 AERROR << "Out of memory";
477 return false;
478 }
479
480 return true;
481}
482
483bool UsbCam::init_mmap(void) {
484 struct v4l2_requestbuffers req;
485 CLEAR(req);
486
487 req.count = 1;
488 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
489 req.memory = V4L2_MEMORY_MMAP;
490
491 if (-1 == xioctl(fd_, VIDIOC_REQBUFS, &req)) {
492 if (EINVAL == errno) {
493 AERROR << config_->camera_dev() << " does not support memory mapping";
494 return false;
495 }
496 return false;
497 }
498
499 buffers_ = reinterpret_cast<buffer*>(calloc(req.count, sizeof(*buffers_)));
500
501 if (!buffers_) {
502 AERROR << "Out of memory";
503 return false;
504 }
505
506 for (n_buffers_ = 0; n_buffers_ < req.count; ++n_buffers_) {
507 struct v4l2_buffer buf;
508 CLEAR(buf);
509
510 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
511 buf.memory = V4L2_MEMORY_MMAP;
512 buf.index = n_buffers_;
513
514 if (-1 == xioctl(fd_, VIDIOC_QUERYBUF, &buf)) {
515 AERROR << "VIDIOC_QUERYBUF";
516 return false;
517 }
518
519 buffers_[n_buffers_].length = buf.length;
520 buffers_[n_buffers_].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
521 MAP_SHARED, fd_, buf.m.offset);
522
523 if (MAP_FAILED == buffers_[n_buffers_].start) {
524 AERROR << "mmap";
525 return false;
526 }
527 }
528
529 return true;
530}
531
532bool UsbCam::init_userp(unsigned int buffer_size) {
533 struct v4l2_requestbuffers req;
534 unsigned int page_size = 0;
535
536 page_size = getpagesize();
537 buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
538
539 CLEAR(req);
540
541 req.count = 4;
542 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
543 req.memory = V4L2_MEMORY_USERPTR;
544
545 if (-1 == xioctl(fd_, VIDIOC_REQBUFS, &req)) {
546 if (EINVAL == errno) {
547 AERROR << config_->camera_dev()
548 << " does not support "
549 "user pointer i/o";
550 return false;
551 }
552 AERROR << "VIDIOC_REQBUFS";
553 return false;
554 }
555
556 buffers_ = reinterpret_cast<buffer*>(calloc(4, sizeof(*buffers_)));
557
558 if (!buffers_) {
559 AERROR << "Out of memory";
560 return false;
561 }
562
563 for (n_buffers_ = 0; n_buffers_ < 4; ++n_buffers_) {
564 buffers_[n_buffers_].length = buffer_size;
565 buffers_[n_buffers_].start =
566 memalign(/* boundary */ page_size, buffer_size);
567
568 if (!buffers_[n_buffers_].start) {
569 AERROR << "Out of memory";
570 return false;
571 }
572 }
573
574 return true;
575}
576
577bool UsbCam::start_capturing(void) {
578 if (is_capturing_) {
579 return true;
580 }
581
582 unsigned int i = 0;
583 enum v4l2_buf_type type;
584
585 switch (config_->io_method()) {
586 case IO_METHOD_READ:
587 /* Nothing to do. */
588 break;
589
590 case IO_METHOD_MMAP:
591 for (i = 0; i < n_buffers_; ++i) {
592 struct v4l2_buffer buf;
593 CLEAR(buf);
594
595 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
596 buf.memory = V4L2_MEMORY_MMAP;
597 buf.index = i;
598 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
599 AERROR << "VIDIOC_QBUF";
600 return false;
601 }
602 }
603
604 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
605
606 if (-1 == xioctl(fd_, VIDIOC_STREAMON, &type)) {
607 AERROR << "VIDIOC_STREAMON";
608 return false;
609 }
610
611 break;
612
614 for (i = 0; i < n_buffers_; ++i) {
615 struct v4l2_buffer buf;
616
617 CLEAR(buf);
618
619 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
620 buf.memory = V4L2_MEMORY_USERPTR;
621 buf.index = i;
622 buf.m.userptr = reinterpret_cast<uint64_t>(buffers_[i].start);
623 buf.length = static_cast<unsigned int>(buffers_[i].length);
624
625 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
626 AERROR << "VIDIOC_QBUF";
627 return false;
628 }
629 }
630
631 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
632
633 if (-1 == xioctl(fd_, VIDIOC_STREAMON, &type)) {
634 AERROR << "VIDIOC_STREAMON";
635 return false;
636 }
637
638 break;
639
641 AERROR << "unknown IO";
642 return false;
643 break;
644 }
645
646 is_capturing_ = true;
647 return true;
648}
649
650void UsbCam::set_device_config() {
651 if (config_->brightness() >= 0) {
652 set_v4l_parameter("brightness", config_->brightness());
653 }
654
655 if (config_->contrast() >= 0) {
656 set_v4l_parameter("contrast", config_->contrast());
657 }
658
659 if (config_->saturation() >= 0) {
660 set_v4l_parameter("saturation", config_->saturation());
661 }
662
663 if (config_->sharpness() >= 0) {
664 set_v4l_parameter("sharpness", config_->sharpness());
665 }
666
667 if (config_->gain() >= 0) {
668 set_v4l_parameter("gain", config_->gain());
669 }
670
671 // check auto white balance
672 if (config_->auto_white_balance()) {
673 set_v4l_parameter("white_balance_temperature_auto", 1);
674 } else {
675 set_v4l_parameter("white_balance_temperature_auto", 0);
676 set_v4l_parameter("white_balance_temperature", config_->white_balance());
677 }
678
679 // check auto exposure
680 if (!config_->auto_exposure()) {
681 // turn down exposure control (from max of 3)
682 set_v4l_parameter("auto_exposure", 1);
683 // change the exposure level
684 set_v4l_parameter("exposure_absolute", config_->exposure());
685 }
686
687 // check auto focus
688 if (config_->auto_focus()) {
689 set_auto_focus(1);
690 set_v4l_parameter("focus_auto", 1);
691 } else {
692 set_v4l_parameter("focus_auto", 0);
693 if (config_->focus() >= 0) {
694 set_v4l_parameter("focus_absolute", config_->focus());
695 }
696 }
697}
698
699bool UsbCam::uninit_device(void) {
700 unsigned int i = 0;
701
702 switch (config_->io_method()) {
703 case IO_METHOD_READ:
704 free(buffers_[0].start);
705 break;
706
707 case IO_METHOD_MMAP:
708 for (i = 0; i < n_buffers_; ++i) {
709 if (-1 == munmap(buffers_[i].start, buffers_[i].length)) {
710 AERROR << "munmap";
711 return false;
712 }
713 }
714
715 break;
716
718 for (i = 0; i < n_buffers_; ++i) {
719 free(buffers_[i].start);
720 }
721
722 break;
723
725 AERROR << "unknown IO";
726 break;
727 }
728
729 return true;
730}
731
732bool UsbCam::close_device(void) {
733 if (-1 == close(fd_)) {
734 AERROR << "close";
735 return false;
736 }
737
738 fd_ = -1;
739 return true;
740}
741
742bool UsbCam::stop_capturing(void) {
743 if (!is_capturing_) {
744 return true;
745 }
746
747 is_capturing_ = false;
748 enum v4l2_buf_type type;
749
750 switch (config_->io_method()) {
751 case IO_METHOD_READ:
752 /* Nothing to do. */
753 break;
754
755 case IO_METHOD_MMAP:
757 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
758
759 if (-1 == xioctl(fd_, VIDIOC_STREAMOFF, &type)) {
760 AERROR << "VIDIOC_STREAMOFF";
761 return false;
762 }
763
764 break;
766 AERROR << "unknown IO";
767 return false;
768 break;
769 }
770
771 return true;
772}
773
774bool UsbCam::read_frame(CameraImagePtr raw_image,
775 CameraImagePtr sensor_raw_image) {
776 struct v4l2_buffer buf;
777 unsigned int i = 0;
778 int len = 0;
779
780 timeval sample_ts_monotonic;
781 timespec current_ts_monotonic;
782 uint64_t sample_ts_monotonic_ns, current_ts_monotonic_ns, diff_ns, sample_in_systme_time_ns;
783
784 switch (config_->io_method()) {
785 case IO_METHOD_READ:
786 len = static_cast<int>(read(fd_, buffers_[0].start, buffers_[0].length));
787
788 if (len == -1) {
789 switch (errno) {
790 case EAGAIN:
791 AINFO << "EAGAIN";
792 return false;
793
794 case EIO:
795
796 /* Could ignore EIO, see spec. */
797
798 /* fall through */
799
800 default:
801 AERROR << "read";
802 return false;
803 }
804 }
805
806 process_image(buffers_[0].start, len, raw_image);
807 if(sensor_raw_image->image != nullptr) {
808 memcpy(sensor_raw_image->image, buffers_[0].start, len);
809 }
810 break;
811
812 case IO_METHOD_MMAP:
813 CLEAR(buf);
814
815 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
816 buf.memory = V4L2_MEMORY_MMAP;
817
818 if (-1 == xioctl(fd_, VIDIOC_DQBUF, &buf)) {
819 switch (errno) {
820 case EAGAIN:
821 return false;
822
823 case EIO:
824
825 /* Could ignore EIO, see spec. */
826
827 /* fall through */
828
829 default:
830 AERROR << "VIDIOC_DQBUF";
831 reconnect();
832 return false;
833 }
834 }
835 assert(buf.index < n_buffers_);
836 len = buf.bytesused;
837 if(!config_->hardware_trigger()){
838 sample_ts_monotonic.tv_sec = static_cast<int>(buf.timestamp.tv_sec);
839 sample_ts_monotonic.tv_usec = static_cast<int>(buf.timestamp.tv_usec);
840 clock_gettime(CLOCK_MONOTONIC,&current_ts_monotonic);
841 sample_ts_monotonic_ns = static_cast<uint64_t>(sample_ts_monotonic.tv_sec*(1000000000)) + static_cast<uint64_t>(sample_ts_monotonic.tv_usec*(1000));
842 current_ts_monotonic_ns = static_cast<uint64_t>(current_ts_monotonic.tv_sec*(1000000000)) + static_cast<uint64_t>(current_ts_monotonic.tv_nsec);
843 diff_ns = static_cast<uint64_t>(current_ts_monotonic_ns - sample_ts_monotonic_ns);
844 sample_in_systme_time_ns = static_cast<uint64_t>(cyber::Time::Now().ToNanosecond() - diff_ns);
845 raw_image->tv_sec = static_cast<int>((sample_in_systme_time_ns)/1000000000);
846 raw_image->tv_usec = static_cast<int>(((sample_in_systme_time_ns)%1000000000)/1000);
847 }
848 else{
849 raw_image->tv_sec = static_cast<int>(buf.timestamp.tv_sec);
850 raw_image->tv_usec = static_cast<int>(buf.timestamp.tv_usec);
851 }
852 {
853 cyber::Time image_time(raw_image->tv_sec, 1000 * raw_image->tv_usec);
854 uint64_t camera_timestamp = image_time.ToNanosecond();
855 if (last_nsec_ == 0) {
856 last_nsec_ = camera_timestamp;
857 } else {
858 double diff =
859 static_cast<double>(camera_timestamp - last_nsec_) / 1e9;
860 // drop image by frame_rate
861 if (diff < frame_drop_interval_) {
862 AINFO << "drop image:" << camera_timestamp;
863 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
864 AERROR << "VIDIOC_QBUF ERROR";
865 }
866 return false;
867 }
868 if (frame_warning_interval_ < diff) {
869 AWARN << "stamp jump.last stamp:" << last_nsec_
870 << " current stamp:" << camera_timestamp;
871 }
872 last_nsec_ = camera_timestamp;
873 }
874
875 double now_s = static_cast<double>(cyber::Time::Now().ToSecond());
876 double image_s = static_cast<double>(camera_timestamp) / 1e9;
877 double diff = now_s - image_s;
878 if (diff > 0.5 || diff < 0) {
879 std::stringstream warning_stream;
880 std::string warning_str;
881 warning_stream << "camera time diff exception,diff:" << diff
882 << ";dev:" << config_->camera_dev();
883 warning_stream >> warning_str;
884 AWARN << warning_str;
885 }
886 }
887 if (len < raw_image->width * raw_image->height) {
888 AERROR << "Wrong Buffer Len: " << len
889 << ", dev: " << config_->camera_dev();
890 } else {
891 process_image(buffers_[buf.index].start, len, raw_image);
892 if(sensor_raw_image->image != nullptr) {
893 memcpy(sensor_raw_image->image, buffers_[buf.index].start, len);
894 }
895 }
896
897 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
898 AERROR << "VIDIOC_QBUF";
899 return false;
900 }
901
902 break;
903
905 CLEAR(buf);
906
907 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
908 buf.memory = V4L2_MEMORY_USERPTR;
909
910 if (-1 == xioctl(fd_, VIDIOC_DQBUF, &buf)) {
911 switch (errno) {
912 case EAGAIN:
913 return false;
914
915 case EIO:
916
917 /* Could ignore EIO, see spec. */
918
919 /* fall through */
920
921 default:
922 AERROR << "VIDIOC_DQBUF";
923 return false;
924 }
925 }
926
927 for (i = 0; i < n_buffers_; ++i) {
928 if (buf.m.userptr == reinterpret_cast<uint64_t>(buffers_[i].start) &&
929 buf.length == buffers_[i].length) {
930 break;
931 }
932 }
933
934 assert(i < n_buffers_);
935 len = buf.bytesused;
936 process_image(reinterpret_cast<void*>(buf.m.userptr), len, raw_image);
937 if(sensor_raw_image->image != nullptr) {
938 memcpy(sensor_raw_image->image, reinterpret_cast<void*>(buf.m.userptr), len);
939 }
940
941 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
942 AERROR << "VIDIOC_QBUF";
943 return false;
944 }
945
946 break;
947
949 AERROR << "unknown IO";
950 return false;
951 break;
952 }
953
954 return true;
955}
956
957bool UsbCam::process_image(void* src, int len, CameraImagePtr dest) {
958 if (src == nullptr || dest == nullptr) {
959 AERROR << "process image error. src or dest is null";
960 return false;
961 }
962 if (pixel_format_ == V4L2_PIX_FMT_YUYV ||
963 pixel_format_ == V4L2_PIX_FMT_UYVY) {
964 if (pixel_format_ == V4L2_PIX_FMT_UYVY) {
965 unsigned char yuyvbuf[len];
966 unsigned char uyvybuf[len];
967 memcpy(yuyvbuf, src, len);
968 for (int index = 0; index < len; index = index + 2) {
969 uyvybuf[index] = yuyvbuf[index + 1];
970 uyvybuf[index + 1] = yuyvbuf[index];
971 }
972 memcpy(src, uyvybuf, len);
973 }
974 if (config_->output_type() == YUYV) {
975 memcpy(dest->image, src, dest->width * dest->height * 2);
976 } else if (config_->output_type() == RGB) {
977#ifndef __aarch64__
978 yuyv2rgb_avx((unsigned char*)src, (unsigned char*)dest->image,
979 dest->width * dest->height);
980#else
981 convert_yuv_to_rgb_buffer((unsigned char*)src,
982 (unsigned char*)dest->image, dest->width,
983 dest->height);
984#endif
985 } else {
986 AERROR << "unsupported output format:" << config_->output_type();
987 return false;
988 }
989 } else {
990 AERROR << "unsupported pixel format:" << pixel_format_;
991 return false;
992 }
993 return true;
994}
995
996bool UsbCam::is_capturing() { return is_capturing_; }
997
998// enables/disables auto focus
999void UsbCam::set_auto_focus(int value) {
1000 struct v4l2_queryctrl queryctrl;
1001 struct v4l2_ext_control control;
1002
1003 memset(&queryctrl, 0, sizeof(queryctrl));
1004 queryctrl.id = V4L2_CID_FOCUS_AUTO;
1005
1006 if (-1 == xioctl(fd_, VIDIOC_QUERYCTRL, &queryctrl)) {
1007 if (errno != EINVAL) {
1008 perror("VIDIOC_QUERYCTRL");
1009 return;
1010 } else {
1011 AINFO << "V4L2_CID_FOCUS_AUTO is not supported";
1012 return;
1013 }
1014 } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
1015 AINFO << "V4L2_CID_FOCUS_AUTO is not supported";
1016 return;
1017 } else {
1018 memset(&control, 0, sizeof(control));
1019 control.id = V4L2_CID_FOCUS_AUTO;
1020 control.value = value;
1021
1022 if (-1 == xioctl(fd_, VIDIOC_S_CTRL, &control)) {
1023 perror("VIDIOC_S_CTRL");
1024 return;
1025 }
1026 }
1027}
1028
1035void UsbCam::set_v4l_parameter(const std::string& param, int value) {
1036 set_v4l_parameter(param, std::to_string(value));
1037}
1044void UsbCam::set_v4l_parameter(const std::string& param,
1045 const std::string& value) {
1046 // build the command
1047 std::stringstream ss;
1048 ss << "v4l2-ctl --device=" << config_->camera_dev() << " -c " << param << "="
1049 << value << " 2>&1";
1050 std::string cmd = ss.str();
1051
1052 // capture the output
1053 std::string output;
1054 char buffer[256];
1055 FILE* stream = popen(cmd.c_str(), "r");
1056 if (stream) {
1057 while (!feof(stream)) {
1058 if (fgets(buffer, 256, stream) != nullptr) {
1059 output.append(buffer);
1060 }
1061 }
1062
1063 pclose(stream);
1064 // any output should be an error
1065 if (output.length() > 0) {
1066 AERROR << output.c_str();
1067 }
1068 } else {
1069 AERROR << "usb_cam_node could not run " << cmd.c_str();
1070 }
1071}
1072
1074 if (is_capturing_) {
1075 ADEBUG << "is capturing";
1076 return true;
1077 }
1078 if (!open_device()) {
1079 return false;
1080 }
1081 if (!init_device()) {
1082 close_device();
1083 return false;
1084 }
1085 if (!start_capturing()) {
1086 uninit_device();
1087 close_device();
1088 return false;
1089 }
1090#ifndef __aarch64__
1091 // will continue when trigger failed for self-trigger camera
1092 set_adv_trigger();
1093#endif
1094 return true;
1095}
1096
1097#ifdef __aarch64__
1098int UsbCam::convert_yuv_to_rgb_pixel(int y, int u, int v) {
1099 unsigned int pixel32 = 0;
1100 unsigned char* pixel = (unsigned char*)&pixel32;
1101 int r, g, b;
1102 r = (int)((double)y + (1.370705 * ((double)v - 128.0)));
1103 g = (int)((double)y - (0.698001 * ((double)v - 128.0)) -
1104 (0.337633 * ((double)u - 128.0)));
1105 b = (int)((double)y + (1.732446 * ((double)u - 128.0)));
1106 if (r > 255) r = 255;
1107 if (g > 255) g = 255;
1108 if (b > 255) b = 255;
1109 if (r < 0) r = 0;
1110 if (g < 0) g = 0;
1111 if (b < 0) b = 0;
1112 pixel[0] = (unsigned char)r;
1113 pixel[1] = (unsigned char)g;
1114 pixel[2] = (unsigned char)b;
1115 return pixel32;
1116}
1117
1118int UsbCam::convert_yuv_to_rgb_buffer(unsigned char* yuv, unsigned char* rgb,
1119 unsigned int width, unsigned int height) {
1120 unsigned int in, out = 0;
1121 unsigned int pixel_16;
1122 unsigned char pixel_24[3];
1123 unsigned int pixel32;
1124 int y0, u, y1, v;
1125
1126 for (in = 0; in < width * height * 2; in += 4) {
1127 pixel_16 =
1128 yuv[in + 3] << 24 | yuv[in + 2] << 16 | yuv[in + 1] << 8 | yuv[in + 0];
1129 y0 = (pixel_16 & 0x000000ff);
1130 u = (pixel_16 & 0x0000ff00) >> 8;
1131 y1 = (pixel_16 & 0x00ff0000) >> 16;
1132 v = (pixel_16 & 0xff000000) >> 24;
1133 pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
1134 pixel_24[0] = (unsigned char)(pixel32 & 0x000000ff);
1135 pixel_24[1] = (unsigned char)((pixel32 & 0x0000ff00) >> 8);
1136 pixel_24[2] = (unsigned char)((pixel32 & 0x00ff0000) >> 16);
1137 rgb[out++] = pixel_24[0];
1138 rgb[out++] = pixel_24[1];
1139 rgb[out++] = pixel_24[2];
1140 pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
1141 pixel_24[0] = (unsigned char)(pixel32 & 0x000000ff);
1142 pixel_24[1] = (unsigned char)((pixel32 & 0x0000ff00) >> 8);
1143 pixel_24[2] = (unsigned char)((pixel32 & 0x00ff0000) >> 16);
1144 rgb[out++] = pixel_24[0];
1145 rgb[out++] = pixel_24[1];
1146 rgb[out++] = pixel_24[2];
1147 }
1148 return 0;
1149}
1150#endif
1151
1152void UsbCam::reconnect() {
1153 stop_capturing();
1154 uninit_device();
1155 close_device();
1156}
1157
1158} // namespace camera
1159} // namespace drivers
1160} // namespace apollo
uint64_t ToNanosecond() const
convert time to nanosecond.
Definition time.cc:83
static Time Now()
get the current time.
Definition time.cc:57
double ToSecond() const
convert time to second.
Definition time.cc:77
virtual bool init(const std::shared_ptr< Config > &camera_config)
Definition usb_cam.cc:71
virtual bool poll(const CameraImagePtr &raw_image, const CameraImagePtr &sensor_raw_image)
Definition usb_cam.cc:231
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
std::shared_ptr< CameraImage > CameraImagePtr
Definition usb_cam.h:100
void yuyv2rgb_avx(unsigned char *YUV, unsigned char *RGB, int NumPixels)
Definition util.cc:133
class register implement
Definition arena_queue.h:37
#define CLEAR(x)
Definition usb_cam.cc:49
#define AV_CODEC_ID_MJPEG
Definition usb_cam.h:58