77 itsDevName(devname), itsNbufs(nbufs), itsBuffers(nullptr), itsStreaming(false), itsFormatOk(false),
83 itsFd = open(devname.c_str(), O_RDWR | O_NONBLOCK, 0);
84 if (itsFd == -1)
LFATAL(
"Camera device open failed on " << devname);
88 struct v4l2_input inp = { };
91 try {
XIOCTL_QUIET(itsFd, VIDIOC_ENUMINPUT, &inp); }
catch (...) {
break; }
92 if (inp.type == V4L2_INPUT_TYPE_CAMERA)
94 if (camidx == -1) camidx = inp.index;
95 FDLDEBUG(devname <<
": Input " << inp.index <<
" [" << inp.name <<
"] is a camera sensor");
96 }
else FDLDEBUG(devname <<
": Input " << inp.index <<
" [" << inp.name <<
"] is a NOT camera sensor");
100 if (camidx == -1)
FDLFATAL(
"No valid camera input");
103 XIOCTL(itsFd, VIDIOC_S_INPUT, &camidx);
106 struct v4l2_capability cap = { };
107 XIOCTL(itsFd, VIDIOC_QUERYCAP, &cap);
109 FDLINFO(
"V4L2 camera " << devname <<
" card " << cap.card <<
" bus " << cap.bus_info);
112 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) itsMplane =
true;
114 if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0 && itsMplane ==
false)
115 FDLFATAL(devname <<
" is not a video capture device");
117 if ((cap.capabilities & V4L2_CAP_STREAMING) == 0)
118 FDLFATAL(devname <<
" does not support streaming");
121 static bool showfmts =
true;
122 if (dummy ==
false && showfmts)
124 struct v4l2_fmtdesc fmtdesc { };
125 if (itsMplane) fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
else fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
128 try {
XIOCTL_QUIET(itsFd, VIDIOC_ENUM_FMT, &fmtdesc); }
catch (...) {
break; }
129 FDLINFO(
"Video format " << fmtdesc.index <<
" is [" << fmtdesc.description <<
"] fcc " << std::showbase <<
130 std::hex << fmtdesc.pixelformat <<
" [" <<
jevois::fccstr(fmtdesc.pixelformat) <<
']');
132 std::string res =
" - Supports";
133 struct v4l2_frmsizeenum frsiz { };
134 frsiz.pixel_format = fmtdesc.pixelformat;
135 bool keepgoing =
true;
138 try {
XIOCTL_QUIET(itsFd, VIDIOC_ENUM_FRAMESIZES, &frsiz); }
catch (...) {
break; }
142 case V4L2_FRMSIZE_TYPE_DISCRETE:
143 res +=
' ' + std::to_string(frsiz.discrete.width) +
'x' + std::to_string(frsiz.discrete.height);
145 case V4L2_FRMSIZE_TYPE_STEPWISE:
146 res +=
" stepwize frame sizes";
149 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
150 res +=
" continuous frame sizes";
167 while (itsRunning.load() ==
false) std::this_thread::sleep_for(std::chrono::milliseconds(1));
432 if (itsConvertedOutputImage.valid())
435 std::unique_lock ulck(itsOutputMtx, std::chrono::seconds(5));
436 if (ulck.owns_lock() ==
false)
FDLFATAL(
"Timeout trying to acquire output lock");
438 if (itsOutputImage.valid() ==
false)
440 if (itsOutputCondVar.wait_for(ulck, std::chrono::milliseconds(2500),
441 [&]() { return itsOutputImage.valid() || itsStreaming.load() == false; }) ==
false)
442 throw std::runtime_error(
"Timeout waiting for camera frame or camera not streaming");
445 if (itsStreaming.load() ==
false)
throw std::runtime_error(
"Camera not streaming");
447 switch (itsFormat.fmt.pix.pixelformat)
451 default:
FDLFATAL(
"Oops, cannot convert captured image");
454 img = itsConvertedOutputImage;
455 img.
bufindex = itsOutputImage.bufindex;
456 itsOutputImage.invalidate();
461 std::unique_lock ulck(itsOutputMtx, std::chrono::seconds(5));
462 if (ulck.owns_lock() ==
false)
FDLFATAL(
"Timeout trying to acquire output lock");
464 if (itsOutputImage.valid() ==
false)
466 if (itsOutputCondVar.wait_for(ulck, std::chrono::milliseconds(2500),
467 [&]() { return itsOutputImage.valid() || itsStreaming.load() == false; }) ==
false)
468 throw std::runtime_error(
"Timeout waiting for camera frame or camera not streaming");
471 if (itsStreaming.load() ==
false)
throw std::runtime_error(
"Camera not streaming");
473 img = itsOutputImage;
477 LDEBUG(
"Camera image " << img.
bufindex <<
" handed over to processing");
497 float const fps,
unsigned int const cropw,
unsigned int const croph,
504 if (itsStreaming.load()) streamOff();
515 itsFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
516 XIOCTL(itsFd, VIDIOC_G_FMT, &itsFormat);
520 itsFormat.fmt.pix_mp.width = capw;
521 itsFormat.fmt.pix_mp.height = caph;
522 itsFormat.fmt.pix_mp.pixelformat = fmt;
523 itsFormat.fmt.pix_mp.num_planes = 1;
525 itsFormat.fmt.pix_mp.field = V4L2_FIELD_NONE;
527 FDLDEBUG(
"Requesting multiplane video format " << itsFormat.fmt.pix.width <<
'x' << itsFormat.fmt.pix.height
531 itsFormat.fmt.pix.width = capw;
532 itsFormat.fmt.pix.height = caph;
533 itsFormat.fmt.pix.pixelformat = fmt;
535 itsFormat.fmt.pix.field = V4L2_FIELD_NONE;
540 itsFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
541 XIOCTL(itsFd, VIDIOC_G_FMT, &itsFormat);
544 itsFormat.fmt.pix.width = capw;
545 itsFormat.fmt.pix.height = caph;
546 itsFormat.fmt.pix.pixelformat = fmt;
548 itsFormat.fmt.pix.field = V4L2_FIELD_NONE;
550 FDLDEBUG(
"Requesting video format " << itsFormat.fmt.pix.width <<
'x' << itsFormat.fmt.pix.height <<
' ' <<
563 ". Maybe the sensor does not support requested pixel type or resolution.");
569 itsFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
577 itsFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
583 ". Maybe the sensor does not support requested pixel type or resolution.");
590 XIOCTL(itsFd, VIDIOC_G_FMT, &itsFormat);
593#ifdef JEVOIS_PLATFORM_A33
594 itsFormat.fmt.pix.pixelformat = v4l2sunxiFix(itsFormat.fmt.pix.pixelformat);
597 FDLINFO(
"Camera set video format to " << itsFormat.fmt.pix.width <<
'x' << itsFormat.fmt.pix.height <<
' ' <<
603 if (itsFormat.fmt.pix_mp.width != capw ||
604 itsFormat.fmt.pix_mp.height != caph ||
605 itsFormat.fmt.pix_mp.pixelformat != fmt)
606 FDLFATAL(
"Camera did not accept the requested video format as specified");
610 if (itsFormat.fmt.pix.width != capw ||
611 itsFormat.fmt.pix.height != caph ||
612 (itsFormat.fmt.pix.pixelformat != fmt &&
613 (fmt != V4L2_PIX_FMT_YUYV ||
614 (itsFormat.fmt.pix.pixelformat != V4L2_PIX_FMT_SRGGB8 &&
615 itsFormat.fmt.pix.pixelformat != V4L2_PIX_FMT_GREY))))
616 FDLFATAL(
"Camera did not accept the requested video format as specified");
625 struct v4l2_cropcap cropcap = { };
626 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
629 FDLDEBUG(
"Cropcap bounds " << cropcap.bounds.width <<
'x' << cropcap.bounds.height <<
630 " @ (" << cropcap.bounds.left <<
", " << cropcap.bounds.top <<
')');
631 FDLDEBUG(
"Cropcap defrect " << cropcap.defrect.width <<
'x' << cropcap.defrect.height <<
632 " @ (" << cropcap.defrect.left <<
", " << cropcap.defrect.top <<
')');
634 struct v4l2_crop crop = { };
635 crop.type = itsFormat.type;
636 if (capw == cropw && caph == croph)
637 crop.c = cropcap.defrect;
640 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
641 crop.c.top = ((caph - croph) >> 1) & 0xfffc;
642 crop.c.left = ((capw - cropw) >> 1) & 0xfffc;
643 crop.c.width = cropw; crop.c.height = croph;
646 itsFormat.fmt.pix.width = cropw;
647 itsFormat.fmt.pix.height = croph;
652 FDLINFO(
"Set cropping rectangle to " << crop.c.width <<
'x' << crop.c.height <<
653 " @ (" << crop.c.left <<
", " << crop.c.top <<
')');
655 catch (...) {
FDLERROR(
"Querying/setting crop rectangle not supported"); }
658 itsFormat.fmt.pix.width = cropw;
659 itsFormat.fmt.pix.height = croph;
662 itsConvertedOutputImage.invalidate();
663 if (itsMplane ==
false && fmt == V4L2_PIX_FMT_YUYV &&
664 (itsFormat.fmt.pix.pixelformat == V4L2_PIX_FMT_SRGGB8 || itsFormat.fmt.pix.pixelformat == V4L2_PIX_FMT_GREY))
667 itsConvertedOutputImage.width = itsFormat.fmt.pix.width;
668 itsConvertedOutputImage.height = itsFormat.fmt.pix.height;
669 itsConvertedOutputImage.fmt = V4L2_PIX_FMT_YUYV;
670 itsConvertedOutputImage.fps = itsFps;
671 itsConvertedOutputImage.buf = std::make_shared<jevois::VideoBuf>(-1, itsConvertedOutputImage.bytesize(), 0, -1);
679 struct v4l2_streamparm parms = { };
680 parms.type = itsFormat.type;
683 XIOCTL(itsFd, VIDIOC_S_PARM, &parms);
685 FDLDEBUG(
"Set framerate to " << fps <<
" fps");
687 catch (...) {
FDLERROR(
"Setting frame rate to " << fps <<
" fps failed -- IGNORED"); }
693 FDLINFO(
"Loading sensor preset " << preset);
696 if (preset == 0) {
struct v4l2_control ctrl { 0xf0f003, 1 };
XIOCTL(itsFd, VIDIOC_S_CTRL, &ctrl); }
698 struct v4l2_control ctrl { 0xf0f003, preset };
699 XIOCTL(itsFd, VIDIOC_S_CTRL, &ctrl);