41#include "adv_trigger.h"
44#include <cuda_runtime.h>
46#include "boost/lexical_cast.hpp"
47#include "sys/sysinfo.h"
52#define __STDC_CONSTANT_MACROS
54#define CLEAR(x) memset(&(x), 0, sizeof(x))
71 time_compensator_fd_(-1),
79 frame_drop_interval_(0.0) {
92 config_ = cameraconfig;
94 if (config_->pixel_format() ==
"yuyv") {
95 pixel_format_ = V4L2_PIX_FMT_YUYV;
96 }
else if (config_->pixel_format() ==
"uyvy") {
97 pixel_format_ = V4L2_PIX_FMT_UYVY;
98 }
else if (config_->pixel_format() ==
"mjpeg") {
99 pixel_format_ = V4L2_PIX_FMT_MJPEG;
100 }
else if (config_->pixel_format() ==
"yuvmono10") {
101 pixel_format_ = V4L2_PIX_FMT_YUYV;
102 config_->set_monochrome(
true);
103 }
else if (config_->pixel_format() ==
"rgb24") {
104 pixel_format_ = V4L2_PIX_FMT_RGB24;
106 pixel_format_ = V4L2_PIX_FMT_YUYV;
107 AERROR <<
"Wrong pixel fromat:" << config_->pixel_format()
108 <<
",must be yuyv | uyvy | mjpeg | yuvmono10 | rgb24";
111 if (pixel_format_ == V4L2_PIX_FMT_MJPEG) {
112 init_mjpeg_decoder(config_->width(), config_->height());
116 frame_warning_interval_ =
static_cast<float>(1.5 / config_->frame_rate());
118 frame_drop_interval_ =
static_cast<float>(0.9 / config_->frame_rate());
119 frame_drop_interval_ns_ =
static_cast<uint64_t
>(frame_drop_interval_ * 1000 * 1000 * 1000);
123 if (!handler_.Init()) {
124 AERROR <<
"Init cuda convert handler error";
132int UsbCam::init_mjpeg_decoder(
int image_width,
int image_height) {
133 avcodec_register_all();
137 AERROR <<
"Could not find MJPEG decoder";
141 avcodec_context_ = avcodec_alloc_context3(avcodec_);
143#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
144 avframe_camera_ = av_frame_alloc();
145 avframe_rgb_ = av_frame_alloc();
147 avpicture_alloc(
reinterpret_cast<AVPicture*
>(avframe_rgb_), AV_PIX_FMT_RGB24, image_width, image_height);
149 avframe_camera_ = avcodec_alloc_frame();
150 avframe_rgb_ = avcodec_alloc_frame();
152 avpicture_alloc(
reinterpret_cast<AVPicture*
>(avframe_rgb_), PIX_FMT_RGB24, image_width, image_height);
156 avcodec_context_->width = image_width;
157 avcodec_context_->height = image_height;
159#if LIBAVCODEC_VERSION_MAJOR > 52
160#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
161 avcodec_context_->pix_fmt = AV_PIX_FMT_YUV422P;
163 avcodec_context_->pix_fmt = PIX_FMT_YUV422P;
165 avcodec_context_->codec_type = AVMEDIA_TYPE_VIDEO;
168#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
169 avframe_camera_size_ = avpicture_get_size(AV_PIX_FMT_YUV422P, image_width, image_height);
170 avframe_rgb_size_ = avpicture_get_size(AV_PIX_FMT_RGB24, image_width, image_height);
172 avframe_camera_size_ = avpicture_get_size(PIX_FMT_YUV422P, image_width, image_height);
173 avframe_rgb_size_ = avpicture_get_size(PIX_FMT_RGB24, image_width, image_height);
177 if (avcodec_open2(avcodec_context_, avcodec_, &avoptions_) < 0) {
178 AERROR <<
"Could not open MJPEG Decoder";
184void UsbCam::mjpeg2rgb(
char* mjpeg_buffer,
int len,
char* rgb_buffer,
int NumPixels) {
188 memset(rgb_buffer, 0, avframe_rgb_size_);
190#if LIBAVCODEC_VERSION_MAJOR > 52
193 av_init_packet(&avpkt);
196 avpkt.data = (
unsigned char*)mjpeg_buffer;
197 decoded_len = avcodec_decode_video2(avcodec_context_, avframe_camera_, &got_picture, &avpkt);
199 if (decoded_len < 0) {
200 AERROR <<
"Error while decoding frame.";
204 avcodec_decode_video(
205 avcodec_context_, avframe_camera_, &got_picture,
reinterpret_cast<uint8_t*
>(mjpeg_buffer), len);
209 AERROR <<
"Camera: expected picture but didn't get it...";
213 int xsize = avcodec_context_->width;
214 int ysize = avcodec_context_->height;
215 int pic_size = avpicture_get_size(avcodec_context_->pix_fmt, xsize, ysize);
216 if (pic_size != avframe_camera_size_) {
217 AERROR <<
"outbuf size mismatch. pic_size:" << pic_size <<
",buffer_size:" << avframe_camera_size_;
221#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
222 video_sws_ = sws_getContext(
225 avcodec_context_->pix_fmt,
234 video_sws_ = sws_getContext(
237 avcodec_context_->pix_fmt,
249 avframe_camera_->data,
250 avframe_camera_->linesize,
254 avframe_rgb_->linesize);
255 sws_freeContext(video_sws_);
257#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
258 int size = avpicture_layout(
259 reinterpret_cast<AVPicture*
>(avframe_rgb_),
263 reinterpret_cast<uint8_t*
>(rgb_buffer),
266 int size = avpicture_layout(
267 reinterpret_cast<AVPicture*
>(avframe_rgb_),
271 reinterpret_cast<uint8_t*
>(rgb_buffer),
274 if (size != avframe_rgb_size_) {
275 AERROR <<
"webcam: avpicture_layout error: " << size;
281 raw_image->is_new = 0;
294 r = select(fd_ + 1, &fds_,
nullptr,
nullptr, &tv_);
297 if (EINTR == errno) {
306 AERROR <<
"select timeout";
313 raw_image->is_new = 1;
319bool UsbCam::open_device(
void) {
322 if (-1 == stat(config_->camera_dev().c_str(), &st)) {
323 AERROR <<
"Cannot identify '" << config_->camera_dev() <<
"': " << errno <<
", " << strerror(errno);
327 if (!S_ISCHR(st.st_mode)) {
328 AERROR << config_->camera_dev() <<
" is no device";
332 fd_ = open(config_->camera_dev().c_str(), O_RDWR | O_NONBLOCK, 0);
335 AERROR <<
"Cannot open '" << config_->camera_dev() <<
"': " << errno <<
", " << strerror(errno);
340 if (config_->has_time_compensator_conf() && config_->time_compensator_conf().enable_compensator()) {
342 = open(config_->time_compensator_conf().compensator_fnode().c_str(), O_RDONLY | O_NONBLOCK);
343 if (-1 == time_compensator_fd_) {
344 AERROR <<
"Cannot open '" << config_->time_compensator_conf().compensator_fnode() <<
"': " << errno <<
", "
354bool UsbCam::init_device(
void) {
355 struct v4l2_capability cap;
356 struct v4l2_cropcap cropcap;
357 struct v4l2_crop crop;
358 struct v4l2_format fmt;
359 unsigned int min = 0;
361 if (-1 == xioctl(fd_, VIDIOC_QUERYCAP, &cap)) {
362 if (EINVAL == errno) {
363 AERROR << config_->camera_dev() <<
" is no V4L2 device";
366 AERROR <<
"VIDIOC_QUERYCAP";
370 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
371 AERROR << config_->camera_dev() <<
" is no video capture device";
375 switch (config_->io_method()) {
377 if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
378 AERROR << config_->camera_dev() <<
" does not support read i/o";
386 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
387 AERROR << config_->camera_dev() <<
" does not support streaming i/o";
393 AERROR << config_->camera_dev() <<
" does not support unknown i/o";
401 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
403 if (0 == xioctl(fd_, VIDIOC_CROPCAP, &cropcap)) {
404 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
405 crop.c = cropcap.defrect;
407 if (-1 == xioctl(fd_, VIDIOC_S_CROP, &crop)) {
418 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
419 fmt.fmt.pix.width = config_->width();
420 fmt.fmt.pix.height = config_->height();
421 fmt.fmt.pix.pixelformat = pixel_format_;
422 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
424 if (-1 == xioctl(fd_, VIDIOC_S_FMT, &fmt)) {
432 min = fmt.fmt.pix.width * 2;
434 if (fmt.fmt.pix.bytesperline < min) {
435 fmt.fmt.pix.bytesperline = min;
438 min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
440 if (fmt.fmt.pix.sizeimage < min) {
441 fmt.fmt.pix.sizeimage = min;
444 config_->set_width(fmt.fmt.pix.width);
445 config_->set_height(fmt.fmt.pix.height);
447 struct v4l2_streamparm stream_params;
448 memset(&stream_params, 0,
sizeof(stream_params));
449 stream_params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
458 AINFO <<
"Capability flag: 0x" << stream_params.parm.capture.capability;
460 stream_params.parm.capture.timeperframe.numerator = 1;
461 stream_params.parm.capture.timeperframe.denominator = config_->frame_rate();
463 if (xioctl(fd_, VIDIOC_S_PARM, &stream_params) < 0) {
464 AINFO <<
"Couldn't set camera framerate";
466 AINFO <<
"Set framerate to be " << config_->frame_rate();
469 switch (config_->io_method()) {
471 init_read(fmt.fmt.pix.sizeimage);
479 init_userp(fmt.fmt.pix.sizeimage);
483 AERROR <<
" does not support unknown i/o";
491bool UsbCam::set_adv_trigger() {
492 AINFO <<
"Trigger enable, dev:" << config_->camera_dev() <<
", fps:" << config_->trigger_fps()
493 <<
", internal:" << config_->trigger_internal();
494 int ret = adv_trigger_enable(
495 config_->camera_dev().c_str(),
496 static_cast<unsigned char>(config_->trigger_fps()),
497 static_cast<unsigned char>(config_->trigger_internal()));
499 AERROR <<
"trigger failed:" << ret;
506int UsbCam::xioctl(
int fd,
int request,
void* arg) {
509 r = ioctl(fd, request, arg);
510 }
while (-1 == r && EINTR == errno);
515bool UsbCam::init_read(
unsigned int buffer_size) {
516 buffers_ =
reinterpret_cast<buffer*
>(calloc(1,
sizeof(*buffers_)));
519 AERROR <<
"Out of memory";
525 buffers_[0].
length = buffer_size;
526 buffers_[0].
start = malloc(buffer_size);
528 if (!buffers_[0].start) {
529 AERROR <<
"Out of memory";
536bool UsbCam::init_mmap(
void) {
537 struct v4l2_requestbuffers req;
541 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
542 req.memory = V4L2_MEMORY_MMAP;
544 if (-1 == xioctl(fd_, VIDIOC_REQBUFS, &req)) {
545 if (EINVAL == errno) {
546 AERROR << config_->camera_dev() <<
" does not support memory mapping";
552 buffers_ =
reinterpret_cast<buffer*
>(calloc(req.count,
sizeof(*buffers_)));
555 AERROR <<
"Out of memory";
559 for (n_buffers_ = 0; n_buffers_ < req.count; ++n_buffers_) {
560 struct v4l2_buffer buf;
563 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
564 buf.memory = V4L2_MEMORY_MMAP;
565 buf.index = n_buffers_;
567 if (-1 == xioctl(fd_, VIDIOC_QUERYBUF, &buf)) {
568 AERROR <<
"VIDIOC_QUERYBUF";
572 buffers_[n_buffers_].
length = buf.length;
573 buffers_[n_buffers_].
start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, buf.m.offset);
575#define CUDA_ZERO_COPY
576 cudaError_t
err = cudaHostRegister(buffers_[n_buffers_].start, buf.length, cudaHostRegisterMapped);
577 if (err != cudaSuccess) {
578 AERROR <<
"Failed to register mapped memory: " << cudaGetErrorString(err);
581 err = cudaHostGetDevicePointer(&buffers_[n_buffers_].cuda_data, buffers_[n_buffers_].start, 0);
582 if (err != cudaSuccess) {
583 AERROR <<
"Failed to get device pointer: " << cudaGetErrorString(err);
584 cudaHostUnregister(buffers_[n_buffers_].start);
589 if (MAP_FAILED == buffers_[n_buffers_].start) {
598bool UsbCam::init_userp(
unsigned int buffer_size) {
599 struct v4l2_requestbuffers req;
600 unsigned int page_size = 0;
602 page_size = getpagesize();
603 buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
608 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
609 req.memory = V4L2_MEMORY_USERPTR;
611 if (-1 == xioctl(fd_, VIDIOC_REQBUFS, &req)) {
612 if (EINVAL == errno) {
613 AERROR << config_->camera_dev()
614 <<
" does not support "
618 AERROR <<
"VIDIOC_REQBUFS";
622 buffers_ =
reinterpret_cast<buffer*
>(calloc(4,
sizeof(*buffers_)));
625 AERROR <<
"Out of memory";
629 for (n_buffers_ = 0; n_buffers_ < 4; ++n_buffers_) {
630 buffers_[n_buffers_].
length = buffer_size;
631 buffers_[n_buffers_].
start = memalign( page_size, buffer_size);
633 if (!buffers_[n_buffers_].start) {
634 AERROR <<
"Out of memory";
642bool UsbCam::start_capturing(
void) {
648 enum v4l2_buf_type type;
650 switch (config_->io_method()) {
656 for (i = 0; i < n_buffers_; ++i) {
657 struct v4l2_buffer buf;
660 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
661 buf.memory = V4L2_MEMORY_MMAP;
663 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
669 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
671 if (-1 == xioctl(fd_, VIDIOC_STREAMON, &type)) {
672 AERROR <<
"VIDIOC_STREAMON";
679 for (i = 0; i < n_buffers_; ++i) {
680 struct v4l2_buffer buf;
684 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
685 buf.memory = V4L2_MEMORY_USERPTR;
687 buf.m.userptr =
reinterpret_cast<uint64_t
>(buffers_[i].
start);
688 buf.length =
static_cast<unsigned int>(buffers_[i].
length);
690 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
696 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
698 if (-1 == xioctl(fd_, VIDIOC_STREAMON, &type)) {
699 AERROR <<
"VIDIOC_STREAMON";
711 is_capturing_ =
true;
715void UsbCam::set_device_config() {
716 if (config_->brightness() >= 0) {
717 set_v4l_parameter(
"brightness", config_->brightness());
720 if (config_->contrast() >= 0) {
721 set_v4l_parameter(
"contrast", config_->contrast());
724 if (config_->saturation() >= 0) {
725 set_v4l_parameter(
"saturation", config_->saturation());
728 if (config_->sharpness() >= 0) {
729 set_v4l_parameter(
"sharpness", config_->sharpness());
732 if (config_->gain() >= 0) {
733 set_v4l_parameter(
"gain", config_->gain());
737 if (config_->auto_white_balance()) {
738 set_v4l_parameter(
"white_balance_temperature_auto", 1);
740 set_v4l_parameter(
"white_balance_temperature_auto", 0);
741 set_v4l_parameter(
"white_balance_temperature", config_->white_balance());
745 if (!config_->auto_exposure()) {
747 set_v4l_parameter(
"auto_exposure", 1);
749 set_v4l_parameter(
"exposure_absolute", config_->exposure());
753 if (config_->auto_focus()) {
755 set_v4l_parameter(
"focus_auto", 1);
757 set_v4l_parameter(
"focus_auto", 0);
758 if (config_->focus() >= 0) {
759 set_v4l_parameter(
"focus_absolute", config_->focus());
764bool UsbCam::uninit_device(
void) {
767 switch (config_->io_method()) {
769 free(buffers_[0].start);
773 for (i = 0; i < n_buffers_; ++i) {
774 if (-1 == munmap(buffers_[i].start, buffers_[i].length)) {
783 for (i = 0; i < n_buffers_; ++i) {
784 free(buffers_[i].start);
797bool UsbCam::close_device(
void) {
799 if (-1 == close(fd_) || -1 == close(time_compensator_fd_)) {
801 if (-1 == close(fd_)) {
808 time_compensator_fd_ = -1;
814bool UsbCam::stop_capturing(
void) {
815 if (!is_capturing_) {
819 is_capturing_ =
false;
820 enum v4l2_buf_type type;
822 switch (config_->io_method()) {
829 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
831 if (-1 == xioctl(fd_, VIDIOC_STREAMOFF, &type)) {
832 AERROR <<
"VIDIOC_STREAMOFF";
847 struct v4l2_buffer buf;
851 timeval sample_ts_monotonic;
852 timespec current_ts_monotonic;
853 uint64_t sample_ts_monotonic_ns, current_ts_monotonic_ns, diff_ns, sample_in_systme_time_ns;
855 if (
cyber::Time::Now().ToNanosecond() - last_error_time_ns_ < frame_drop_interval_ns_) {
856 auto d = std::chrono::microseconds(
857 (last_error_time_ns_ + frame_drop_interval_ns_) / 1000);
858 std::this_thread::sleep_until(std::chrono::system_clock::time_point(d));
861 switch (config_->io_method()) {
863 len =
static_cast<int>(read(fd_, buffers_[0].start, buffers_[0].length));
885 process_image(buffers_[0].start, len, raw_image);
886 if (sensor_raw_image->image !=
nullptr) {
887 memcpy(sensor_raw_image->image, buffers_[0].start, len);
894 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
895 buf.memory = V4L2_MEMORY_MMAP;
897 if (-1 == xioctl(fd_, VIDIOC_DQBUF, &buf)) {
916 assert(buf.index < n_buffers_);
918 if (!config_->hardware_trigger()) {
919 sample_ts_monotonic.tv_sec =
static_cast<int>(buf.timestamp.tv_sec);
920 sample_ts_monotonic.tv_usec =
static_cast<int>(buf.timestamp.tv_usec);
921 clock_gettime(CLOCK_MONOTONIC, ¤t_ts_monotonic);
922 sample_ts_monotonic_ns =
static_cast<uint64_t
>(sample_ts_monotonic.tv_sec * (1000000000))
923 +
static_cast<uint64_t
>(sample_ts_monotonic.tv_usec * (1000));
925 sample_ts_monotonic_ns = compensate_rtcpu_to_kernel_time(sample_ts_monotonic_ns);
927 current_ts_monotonic_ns =
static_cast<uint64_t
>(current_ts_monotonic.tv_sec * (1000000000))
928 +
static_cast<uint64_t
>(current_ts_monotonic.tv_nsec);
929 diff_ns =
static_cast<uint64_t
>(current_ts_monotonic_ns - sample_ts_monotonic_ns);
931 raw_image->tv_sec =
static_cast<int>((sample_in_systme_time_ns) / 1000000000);
932 raw_image->tv_usec =
static_cast<int>(((sample_in_systme_time_ns) % 1000000000) / 1000);
934 raw_image->tv_sec =
static_cast<int>(buf.timestamp.tv_sec);
935 raw_image->tv_usec =
static_cast<int>(buf.timestamp.tv_usec);
938 cyber::Time image_time(raw_image->tv_sec, 1000 * raw_image->tv_usec);
939 uint64_t camera_timestamp = image_time.ToNanosecond();
940 if (last_nsec_ == 0) {
941 last_nsec_ = camera_timestamp;
943 double diff =
static_cast<double>(camera_timestamp - last_nsec_) / 1e9;
945 if (diff < frame_drop_interval_) {
946 AINFO <<
"drop image:" << camera_timestamp;
947 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
948 AERROR <<
"VIDIOC_QBUF ERROR";
952 if (frame_warning_interval_ < diff) {
953 AWARN <<
"stamp jump.last stamp:" << last_nsec_ <<
" current stamp:" << camera_timestamp;
955 last_nsec_ = camera_timestamp;
959 double image_s =
static_cast<double>(camera_timestamp) / 1e9;
960 double diff = now_s - image_s;
961 if (diff > 0.5 || diff < 0) {
962 std::stringstream warning_stream;
963 std::string warning_str;
964 warning_stream <<
"camera time diff exception,diff:" <<
diff <<
";dev:" << config_->camera_dev();
965 warning_stream >> warning_str;
966 AWARN << warning_str;
969 if (len < raw_image->width * raw_image->height) {
970 AERROR <<
"Wrong Buffer Len: " << len <<
", dev: " << config_->camera_dev();
973 process_image(buffers_[buf.index].start, len, raw_image, buffers_[buf.index].cuda_data);
975 process_image(buffers_[buf.index].start, len, raw_image);
977 if (sensor_raw_image->image !=
nullptr) {
978 memcpy(sensor_raw_image->image, buffers_[buf.index].start, len);
982 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
991 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
992 buf.memory = V4L2_MEMORY_USERPTR;
994 if (-1 == xioctl(fd_, VIDIOC_DQBUF, &buf)) {
1007 AERROR <<
"VIDIOC_DQBUF";
1013 for (i = 0; i < n_buffers_; ++i) {
1014 if (buf.m.userptr ==
reinterpret_cast<uint64_t
>(buffers_[i].start) && buf.length == buffers_[i].length) {
1019 assert(i < n_buffers_);
1020 len = buf.bytesused;
1021 process_image(
reinterpret_cast<void*
>(buf.m.userptr), len, raw_image);
1022 if (sensor_raw_image->image !=
nullptr) {
1023 memcpy(sensor_raw_image->image,
reinterpret_cast<void*
>(buf.m.userptr), len);
1026 if (-1 == xioctl(fd_, VIDIOC_QBUF, &buf)) {
1043bool UsbCam::process_image(
void* src,
int len,
CameraImagePtr dest,
void* zero_copy_src) {
1044 if (src ==
nullptr || dest ==
nullptr) {
1045 AERROR <<
"process image error. src or dest is null";
1048 if (pixel_format_ == V4L2_PIX_FMT_YUYV || pixel_format_ == V4L2_PIX_FMT_UYVY) {
1049 if (pixel_format_ == V4L2_PIX_FMT_UYVY) {
1050 unsigned char yuyvbuf[len];
1051 unsigned char uyvybuf[len];
1052 memcpy(yuyvbuf, src, len);
1053 for (
int index = 0; index < len; index = index + 2) {
1054 uyvybuf[index] = yuyvbuf[index + 1];
1055 uyvybuf[index + 1] = yuyvbuf[index];
1057 memcpy(src, uyvybuf, len);
1059 if (config_->output_type() == YUYV) {
1060 memcpy(dest->image, src, dest->width * dest->height * 2);
1061 }
else if (config_->output_type() == RGB) {
1063 if (config_->arm_gpu_acceleration())
1066 if (zero_copy_src !=
nullptr) {
1067 handler_.Process((
unsigned char*)zero_copy_src, (
unsigned char*)dest->image,
true);
1069 handler_.Process((
unsigned char*)src, (
unsigned char*)dest->image);
1072 convert_yuv_to_rgb_buffer((
unsigned char*)src, (
unsigned char*)dest->image, dest->width, dest->height);
1074 yuyv2rgb_avx((
unsigned char*)src, (
unsigned char*)dest->image, dest->width * dest->height);
1077 AERROR <<
"unsupported output format:" << config_->output_type();
1081 AERROR <<
"unsupported pixel format:" << pixel_format_;
1088 return is_capturing_;
1092void UsbCam::set_auto_focus(
int value) {
1093 struct v4l2_queryctrl queryctrl;
1094 struct v4l2_ext_control control;
1096 memset(&queryctrl, 0,
sizeof(queryctrl));
1097 queryctrl.id = V4L2_CID_FOCUS_AUTO;
1099 if (-1 == xioctl(fd_, VIDIOC_QUERYCTRL, &queryctrl)) {
1100 if (errno != EINVAL) {
1101 perror(
"VIDIOC_QUERYCTRL");
1104 AINFO <<
"V4L2_CID_FOCUS_AUTO is not supported";
1107 }
else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
1108 AINFO <<
"V4L2_CID_FOCUS_AUTO is not supported";
1111 memset(&control, 0,
sizeof(control));
1112 control.id = V4L2_CID_FOCUS_AUTO;
1113 control.value = value;
1115 if (-1 == xioctl(fd_, VIDIOC_S_CTRL, &control)) {
1116 perror(
"VIDIOC_S_CTRL");
1128void UsbCam::set_v4l_parameter(
const std::string& param,
int value) {
1129 set_v4l_parameter(param, std::to_string(value));
1137void UsbCam::set_v4l_parameter(
const std::string& param,
const std::string& value) {
1139 std::stringstream ss;
1140 ss <<
"v4l2-ctl --device=" << config_->camera_dev() <<
" -c " << param <<
"=" << value <<
" 2>&1";
1141 std::string cmd = ss.str();
1146 FILE* stream = popen(cmd.c_str(),
"r");
1148 while (!feof(stream)) {
1149 if (fgets(buffer, 256, stream) !=
nullptr) {
1150 output.append(buffer);
1156 if (output.length() > 0) {
1157 AERROR << output.c_str();
1160 AERROR <<
"usb_cam_node could not run " << cmd.c_str();
1165 if (is_capturing_) {
1166 ADEBUG <<
"is capturing";
1169 if (!open_device()) {
1172 if (!init_device()) {
1176 if (!start_capturing()) {
1188void UsbCam::reconnect() {
1195int UsbCam::convert_yuv_to_rgb_pixel(
int y,
int u,
int v) {
1196 unsigned int pixel32 = 0;
1197 unsigned char* pixel = (
unsigned char*)&pixel32;
1206 y = std::max(y, 16);
1207 r = (75 * y + 102 * v - 14266 + 32) >> 6;
1208 g = (75 * y - 52 * v - 25 * u + 8671 + 32) >> 6;
1209 b = (75 * y + 129 * u - 17723 + 32) >> 6;
1223 pixel[0] = (
unsigned char)r;
1224 pixel[1] = (
unsigned char)g;
1225 pixel[2] = (
unsigned char)b;
1229int UsbCam::convert_yuv_to_rgb_buffer(
unsigned char* yuv,
unsigned char* rgb,
unsigned int width,
unsigned int height) {
1231 int16x8_t v_y, v_u, v_v, v_y_prod;
1232 uint8x8x3_t v_rgb_result;
1234 const int16_t factor_y = 75;
1235 const int16_t factor_v_for_r = 102;
1236 const int16_t const_for_r = -14266 + 32;
1237 const int16_t factor_v_for_g = -52;
1238 const int16_t factor_u_for_g = -25;
1239 const int16_t const_for_g = 8671 + 32;
1240 const int16_t factor_u_for_b = 129;
1241 const int16_t const_for_b = -17723 + 32;
1243 int16x8_t v_const_for_r = vdupq_n_s16(const_for_r);
1244 int16x8_t v_const_for_g = vdupq_n_s16(const_for_g);
1245 int16x8_t v_const_for_b = vdupq_n_s16(const_for_b);
1247#pragma omp parallel for num_threads(get_nprocs())
1248 for (
unsigned int in = 0; in < width * height * 2; in += 16) {
1249 unsigned char* rgb_out = rgb +
static_cast<unsigned int>(1.5 * in);
1277 v_y = vld1q_s16(y_mem);
1278 v_u = vld1q_s16(u_mem);
1279 v_v = vld1q_s16(v_mem);
1281 v_y_prod = vmulq_n_s16(v_y, factor_y);
1282 v_rgb_result.val[0] = vqshrun_n_s16(vaddq_s16(vmlaq_n_s16(v_y_prod, v_v, factor_v_for_r), v_const_for_r), 6);
1284 v_rgb_result.val[1] = vqshrun_n_s16(
1285 vaddq_s16(vmlaq_n_s16(vmlaq_n_s16(v_y_prod, v_v, factor_v_for_g), v_u, factor_u_for_g), v_const_for_g),
1288 v_rgb_result.val[2] = vqshrun_n_s16(vaddq_s16(vmlaq_n_s16(v_y_prod, v_u, factor_u_for_b), v_const_for_b), 6);
1290 vst3_u8(rgb_out, v_rgb_result);
1293 unsigned int in = 0;
1294 unsigned int out = 0;
1295 unsigned int pixel_16 = 0;
1296 unsigned char pixel_24[3];
1297 unsigned int pixel32 = 0;
1303 pixel_16 = yuv[in + 3] << 24 | yuv[in + 2] << 16 | yuv[in + 1] << 8 | yuv[in + 0];
1304 y0 = (pixel_16 & 0x000000ff);
1305 u = (pixel_16 & 0x0000ff00) >> 8;
1306 y1 = (pixel_16 & 0x00ff0000) >> 16;
1307 v = (pixel_16 & 0xff000000) >> 24;
1308 pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
1309 pixel_24[0] = (
unsigned char)(pixel32 & 0x000000ff);
1310 pixel_24[1] = (
unsigned char)((pixel32 & 0x0000ff00) >> 8);
1311 pixel_24[2] = (
unsigned char)((pixel32 & 0x00ff0000) >> 16);
1312 rgb[out++] = pixel_24[0];
1313 rgb[out++] = pixel_24[1];
1314 rgb[out++] = pixel_24[2];
1315 pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
1316 pixel_24[0] = (
unsigned char)(pixel32 & 0x000000ff);
1317 pixel_24[1] = (
unsigned char)((pixel32 & 0x0000ff00) >> 8);
1318 pixel_24[2] = (
unsigned char)((pixel32 & 0x00ff0000) >> 16);
1319 rgb[out++] = pixel_24[0];
1320 rgb[out++] = pixel_24[1];
1321 rgb[out++] = pixel_24[2];
1327uint64_t UsbCam::compensate_rtcpu_to_kernel_time(uint64_t rtcpu_time_ns) {
1329 uint64_t system_kernel_time_ns;
1331 lseek(time_compensator_fd_, 0, SEEK_SET);
1332 auto len =
static_cast<int>(read(time_compensator_fd_, buffer, 64 *
sizeof(
char)));
1334 AWARN <<
"Cannot read offset: " << config_->time_compensator_conf().compensator_fnode();
1335 return rtcpu_time_ns;
1338 buffer[len - 1] =
'\0';
1339 system_kernel_time_ns = rtcpu_time_ns - boost::lexical_cast<uint64_t>(buffer);
1340 return system_kernel_time_ns;
uint64_t ToNanosecond() const
convert time to nanosecond.
static Time Now()
get the current time.
double ToSecond() const
convert time to second.
bool wait_for_device(void)
virtual bool init(const std::shared_ptr< apollo::drivers::camera::config::Config > &camera_config)
virtual CameraDeviceState poll(const CameraImagePtr &raw_image, const CameraImagePtr &sensor_raw_image)
std::shared_ptr< CameraImage > CameraImagePtr
void yuyv2rgb_avx(unsigned char *YUV, unsigned char *RGB, int NumPixels)
uint32_t height
Height of point cloud
uint32_t width
Width of point cloud
float diff(Image< float > *I, int x1, int y1, int x2, int y2)
Dissimilarity measure between pixels
#define AV_CODEC_ID_MJPEG