42 #include <visp3/core/vpConfig.h>
51 #include <sys/ioctl.h>
55 #include <sys/types.h>
58 #include <visp3/core/vpFrameGrabberException.h>
59 #include <visp3/sensor/vpV4l2Grabber.h>
61 #include <visp3/core/vpImageConvert.h>
62 #include <visp3/core/vpImageTools.h>
72 #define vpCLEAR(x) memset(&(x), 0, sizeof(x))
147 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
148 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
203 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
204 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(verbose), m_nbuffers(3), field(0),
249 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
250 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
295 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
296 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
344 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
345 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
386 if ((scale < 1) || (scale > 16)) {
389 vpERROR_TRACE(
"Wrong scale %d, scale should be between 1 and 16", scale);
411 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
412 std::cout <<
"Warning: cannot set input channel to " << m_input << std::endl;
424 std::cout <<
"Requested pixel format [" << req_pixelformat <<
"] not compatible with camera" << std::endl;
425 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
430 if (format == req_pixelformat) {
438 std::cout <<
"This format [" << m_pixelformat <<
"] is compatible with camera" << std::endl;
444 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
446 std::cout <<
"No pixel format compatible with the camera was found" << std::endl;
450 "No pixel format compatible with the camera was found"));
474 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
475 std::cout <<
"Warning: cannot set input channel to " << m_input << std::endl;
487 std::cout <<
"Requested pixel format [" << m_pixelformat <<
"] not compatible with camera" << std::endl;
488 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
493 if (format == req_pixelformat) {
501 std::cout <<
"This format [" << m_pixelformat <<
"] is compatible with camera" << std::endl;
507 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
529 struct timeval timestamp;
548 struct timeval timestamp;
584 unsigned char *bitmap;
585 bitmap = waiton(index_buffer, timestamp);
591 switch (m_pixelformat) {
636 std::cout <<
"V4L2 conversion not handled" << std::endl;
655 struct timeval timestamp;
674 struct timeval timestamp;
710 unsigned char *bitmap;
711 bitmap = waiton(index_buffer, timestamp);
721 switch (m_pixelformat) {
745 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
746 memcpy(
static_cast<void *
>(I.
bitmap),
747 static_cast<void *
>(bitmap + 1 + (
unsigned int)(roi.
getTop() *
width + roi.
getLeft())),
772 std::cout <<
"V4l2 conversion not handled" << std::endl;
823 this->m_framerate = framerate;
856 if (inp !=
nullptr) {
860 if (std !=
nullptr) {
864 if (fmt !=
nullptr) {
868 if (ctl !=
nullptr) {
872 if (buf_v4l2 !=
nullptr) {
876 if (buf_me !=
nullptr) {
893 void vpV4l2Grabber::open()
898 if (-1 == stat(device.c_str(), &st)) {
899 fprintf(stderr,
"Cannot identify '%s': %d, %s\n", device.c_str(), errno, strerror(errno));
903 if (!S_ISCHR(st.st_mode)) {
904 fprintf(stderr,
"%s is no device\n", device.c_str());
907 fd = v4l2_open(device.c_str(), O_RDWR | O_NONBLOCK, 0);
915 if (inp !=
nullptr) {
919 if (std !=
nullptr) {
923 if (fmt !=
nullptr) {
927 if (ctl !=
nullptr) {
931 if (buf_v4l2 !=
nullptr) {
935 if (buf_me !=
nullptr) {
948 if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
950 fprintf(stderr,
"%s is no V4L2 device\n", device.c_str());
957 " %s %d.%d.%d / %s @ %s\n",
958 device.c_str(), cap.driver, (cap.version >> 16) & 0xff, (cap.version >> 8) & 0xff, cap.version & 0xff,
959 cap.card, cap.bus_info);
960 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
961 fprintf(stdout,
" Support overlay\n");
963 fprintf(stdout,
" Does not support overlay\n");
964 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
965 fprintf(stdout,
" Support capture\n");
967 fprintf(stdout,
" Does not support capture\n");
968 if (cap.capabilities & V4L2_CAP_TUNER)
969 fprintf(stdout,
" Support tuning\n");
971 fprintf(stdout,
" Does not support tuning\n");
972 if (cap.capabilities & V4L2_CAP_STREAMING)
973 fprintf(stdout,
" Support streaming capture.\n");
975 fprintf(stdout,
" Does not support streaming capture\n");
976 if (cap.capabilities & V4L2_CAP_ASYNCIO)
977 fprintf(stdout,
" Support asynchronous I/O methods\n");
979 fprintf(stdout,
" Does not support asynchronous I/O methods\n");
980 if (cap.capabilities & V4L2_CAP_TIMEPERFRAME)
981 fprintf(stdout,
" Support time per frame field\n");
983 fprintf(stdout,
" Does not support time per frame field\n");
985 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
986 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
987 fprintf(stdout,
" Current acquisition framerate: %d fps\n", streamparm.parm.output.timeperframe.denominator);
1000 void vpV4l2Grabber::getCapabilities()
1002 for (__u32 ninputs = 0; ninputs <
MAX_INPUTS; ninputs++) {
1003 inp[ninputs].index = ninputs;
1004 if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1007 for (__u32 nstds = 0; nstds <
MAX_NORM; nstds++) {
1008 std[nstds].index = nstds;
1009 if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
1012 for (__u32 nfmts = 0; nfmts <
MAX_FORMAT; nfmts++) {
1013 fmt[nfmts].index = nfmts;
1014 fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1015 if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1019 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1020 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
1040 void vpV4l2Grabber::setFormat()
1042 fmt_me.width =
width;
1048 switch (m_pixelformat) {
1050 fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1052 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1055 fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1057 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1060 fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1062 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1065 fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1067 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1070 fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1072 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1084 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1086 if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt_v4l2) == -1) {
1091 fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1092 fmt_v4l2.fmt.pix.width = fmt_me.width;
1093 fmt_v4l2.fmt.pix.height = fmt_me.height;
1097 switch (m_frameformat) {
1099 fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1101 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1105 fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1107 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1123 if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1127 if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1132 unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1133 if (fmt_v4l2.fmt.pix.bytesperline < min)
1134 fmt_v4l2.fmt.pix.bytesperline = min;
1135 min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1136 if (fmt_v4l2.fmt.pix.sizeimage < min)
1137 fmt_v4l2.fmt.pix.sizeimage = min;
1139 fmt_me.width = fmt_v4l2.fmt.pix.width;
1140 fmt_me.height = fmt_v4l2.fmt.pix.height;
1141 fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1145 "v4l2: new capture params (%ux%u, %c%c%c%c, %d byte, %d bytes "
1147 fmt_me.width, fmt_me.height, fmt_v4l2.fmt.pix.pixelformat & 0xff,
1148 (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff, (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1149 (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff, fmt_v4l2.fmt.pix.sizeimage, fmt_v4l2.fmt.pix.bytesperline);
1160 void vpV4l2Grabber::startStreaming()
1162 if (streaming ==
true) {
1168 memset(&(reqbufs), 0,
sizeof(reqbufs));
1169 reqbufs.count = m_nbuffers;
1170 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1171 reqbufs.memory = V4L2_MEMORY_MMAP;
1173 if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1) {
1174 if (EINVAL == errno) {
1176 "%s does not support "
1184 for (
unsigned i = 0; i < reqbufs.count; i++) {
1186 memset(&(buf_v4l2[i]), 0,
sizeof(buf_v4l2[i]));
1187 buf_v4l2[i].index = i;
1188 buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1189 buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1190 buf_v4l2[i].length = 0;
1191 if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1) {
1194 memcpy(&buf_me[i].fmt, &fmt_me,
sizeof(ng_video_fmt));
1195 buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1197 buf_me[i].data = (
unsigned char *)v4l2_mmap(
nullptr, buf_v4l2[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1198 (off_t)buf_v4l2[i].m.offset);
1200 if (buf_me[i].data == MAP_FAILED) {
1204 buf_me[i].refcount = 0;
1207 printBufInfo(buf_v4l2[i]);
1214 if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type) < 0) {
1227 void vpV4l2Grabber::stopStreaming()
1230 if ((fd >= 0) && (streaming ==
true)) {
1234 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1235 if (v4l2_ioctl(fd, VIDIOC_STREAMOFF, &fmt_v4l2.type)) {
1239 for (
unsigned int i = 0; i < reqbufs.count; i++) {
1241 printBufInfo(buf_v4l2[i]);
1244 if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1267 unsigned char *vpV4l2Grabber::waiton(__u32 &index,
struct timeval ×tamp)
1269 struct v4l2_buffer buf;
1279 FD_SET(
static_cast<unsigned int>(fd), &rdset);
1280 switch (select(fd + 1, &rdset,
nullptr,
nullptr, &tv)) {
1294 memset(&buf, 0,
sizeof(buf));
1295 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1296 buf.memory = V4L2_MEMORY_MMAP;
1297 if (-1 == v4l2_ioctl(fd, VIDIOC_DQBUF, &buf)) {
1317 buf_v4l2[buf.index] = buf;
1321 field = buf_v4l2[index].field;
1323 timestamp = buf_v4l2[index].timestamp;
1331 return buf_me[buf.index].data;
1339 int vpV4l2Grabber::queueBuffer()
1341 unsigned int frame = queue % reqbufs.count;
1344 if (0 != buf_me[frame].refcount) {
1345 if (0 != queue - waiton_cpt)
1347 fprintf(stderr,
"v4l2: waiting for a free buffer..............\n");
1349 std::cout <<
"Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1353 rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1380 void vpV4l2Grabber::queueAll()
1383 if (queue - waiton_cpt >= reqbufs.count) {
1386 if (0 != queueBuffer()) {
1397 void vpV4l2Grabber::printBufInfo(
struct v4l2_buffer buf)
1402 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1405 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1406 type =
"video-over";
1408 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1411 case V4L2_BUF_TYPE_VBI_CAPTURE:
1414 case V4L2_BUF_TYPE_VBI_OUTPUT:
1422 fprintf(stdout,
"v4l2: buf %d: type %d (%s) ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n", buf.index, buf.type,
1423 type.c_str(), buf.m.userptr, buf.m.offset, buf.length, buf.length, buf.bytesused);
1470 #elif !defined(VISP_BUILD_SHARED_LIBS)
1473 void dummy_vpV4l2Grabber() { };
Error that can be emitted by the vpFrameGrabber class and its derivates.
@ settingError
Grabber settings error.
@ initializationError
Grabber initialization error.
@ otherError
Grabber returned an other error.
unsigned int height
Number of rows in the image.
bool init
Set to true if the frame grabber has been initialized.
unsigned int width
Number of columns in the image.
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void GreyToRGBa(unsigned char *grey, unsigned char *rgba, unsigned int width, unsigned int height)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Type * bitmap
points toward the bitmap
unsigned int getHeight() const
Defines a rectangle in the plane.
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
@ framerate_25fps
25 frames per second
void setWidth(unsigned w)
static const __u32 MAX_NORM
void setFramerate(vpV4l2FramerateType framerate)
vpV4l2Grabber & operator>>(vpImage< unsigned char > &I)
static const unsigned int MAX_CTRL
static const unsigned int MAX_BUFFERS
static const __u32 MAX_INPUTS
vpV4l2PixelFormatType getPixelFormat()
static const unsigned int FRAME_SIZE
static const unsigned int DEFAULT_SCALE
static const unsigned int DEFAULT_INPUT
void setInput(unsigned input=vpV4l2Grabber::DEFAULT_INPUT)
static const __u32 MAX_FORMAT
void open(vpImage< unsigned char > &I)
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setHeight(unsigned h)
void setPixelFormat(vpV4l2PixelFormatType pixelformat)
void setNBuffers(unsigned nbuffers)
vpV4l2FramerateType getFramerate()
void setDevice(const std::string &devname)
void acquire(vpImage< unsigned char > &I)