39 #include <visp3/core/vpConfig.h>
48 #include <sys/ioctl.h>
52 #include <sys/types.h>
55 #include <visp3/core/vpDebug.h>
56 #include <visp3/core/vpFrameGrabberException.h>
57 #include <visp3/sensor/vpV4l2Grabber.h>
59 #include <visp3/core/vpImageConvert.h>
60 #include <visp3/core/vpImageTools.h>
71 #define vpCLEAR(x) memset(&(x), 0, sizeof(x))
149 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
150 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
204 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
205 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),
342 : fd(-1), device(), cap(), streamparm(), inp(nullptr), std(nullptr), fmt(nullptr), ctl(nullptr), fmt_v4l2(), fmt_me(), reqbufs(),
343 buf_v4l2(nullptr), buf_me(nullptr), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
384 if ((scale < 1) || (scale > 16)) {
387 vpERROR_TRACE(
"Wrong scale %d, scale should be between 1 and 16", scale);
409 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
410 std::cout <<
"Warning: cannot set input channel to " << m_input << std::endl;
422 std::cout <<
"Requested pixel format [" << req_pixelformat <<
"] not compatible with camera" << std::endl;
423 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
428 if (format == req_pixelformat) {
436 std::cout <<
"This format [" << m_pixelformat <<
"] is compatible with camera" << std::endl;
442 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
444 std::cout <<
"No pixel format compatible with the camera was found" << std::endl;
448 "No pixel format compatible with the camera was found"));
472 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
473 std::cout <<
"Warning: cannot set input channel to " << m_input << std::endl;
485 std::cout <<
"Requested pixel format [" << m_pixelformat <<
"] not compatible with camera" << std::endl;
486 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
491 if (format == req_pixelformat) {
499 std::cout <<
"This format [" << m_pixelformat <<
"] is compatible with camera" << std::endl;
505 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
527 struct timeval timestamp;
546 struct timeval timestamp;
582 unsigned char *bitmap;
583 bitmap = waiton(index_buffer, timestamp);
589 switch (m_pixelformat) {
634 std::cout <<
"V4L2 conversion not handled" << std::endl;
653 struct timeval timestamp;
672 struct timeval timestamp;
708 unsigned char *bitmap;
709 bitmap = waiton(index_buffer, timestamp);
719 switch (m_pixelformat) {
744 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
745 memcpy(
static_cast<void *
>(I.
bitmap),
746 static_cast<void *
>(bitmap + 1 + (
unsigned int)(roi.
getTop() *
width + roi.
getLeft())),
771 std::cout <<
"V4l2 conversion not handled" << std::endl;
822 this->m_framerate = framerate;
855 if (inp !=
nullptr) {
859 if (std !=
nullptr) {
863 if (fmt !=
nullptr) {
867 if (ctl !=
nullptr) {
871 if (buf_v4l2 !=
nullptr) {
875 if (buf_me !=
nullptr) {
892 void vpV4l2Grabber::open()
897 if (-1 == stat(device.c_str(), &st)) {
898 fprintf(stderr,
"Cannot identify '%s': %d, %s\n", device.c_str(), errno, strerror(errno));
902 if (!S_ISCHR(st.st_mode)) {
903 fprintf(stderr,
"%s is no device\n", device.c_str());
906 fd = v4l2_open(device.c_str(), O_RDWR | O_NONBLOCK, 0);
910 vpERROR_TRACE(
"No video device \"%s\"\n", device.c_str());
914 if (inp !=
nullptr) {
918 if (std !=
nullptr) {
922 if (fmt !=
nullptr) {
926 if (ctl !=
nullptr) {
930 if (buf_v4l2 !=
nullptr) {
934 if (buf_me !=
nullptr) {
947 if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
949 fprintf(stderr,
"%s is no V4L2 device\n", device.c_str());
956 " %s %d.%d.%d / %s @ %s\n",
957 device.c_str(), cap.driver, (cap.version >> 16) & 0xff, (cap.version >> 8) & 0xff, cap.version & 0xff,
958 cap.card, cap.bus_info);
959 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
960 fprintf(stdout,
" Support overlay\n");
962 fprintf(stdout,
" Does not support overlay\n");
963 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
964 fprintf(stdout,
" Support capture\n");
966 fprintf(stdout,
" Does not support capture\n");
967 if (cap.capabilities & V4L2_CAP_TUNER)
968 fprintf(stdout,
" Support tuning\n");
970 fprintf(stdout,
" Does not support tuning\n");
971 if (cap.capabilities & V4L2_CAP_STREAMING)
972 fprintf(stdout,
" Support streaming capture.\n");
974 fprintf(stdout,
" Does not support streaming capture\n");
975 if (cap.capabilities & V4L2_CAP_ASYNCIO)
976 fprintf(stdout,
" Support asynchronous I/O methods\n");
978 fprintf(stdout,
" Does not support asynchronous I/O methods\n");
979 if (cap.capabilities & V4L2_CAP_TIMEPERFRAME)
980 fprintf(stdout,
" Support time per frame field\n");
982 fprintf(stdout,
" Does not support time per frame field\n");
984 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
985 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
986 fprintf(stdout,
" Current acquisition framerate: %d fps\n", streamparm.parm.output.timeperframe.denominator);
999 void vpV4l2Grabber::getCapabilities()
1001 for (__u32 ninputs = 0; ninputs <
MAX_INPUTS; ninputs++) {
1002 inp[ninputs].index = ninputs;
1003 if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1006 for (__u32 nstds = 0; nstds <
MAX_NORM; nstds++) {
1007 std[nstds].index = nstds;
1008 if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
1011 for (__u32 nfmts = 0; nfmts <
MAX_FORMAT; nfmts++) {
1012 fmt[nfmts].index = nfmts;
1013 fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1014 if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1018 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1019 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
1039 void vpV4l2Grabber::setFormat()
1041 fmt_me.width =
width;
1047 switch (m_pixelformat) {
1049 fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1051 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1054 fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1056 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1059 fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1061 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1064 fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1066 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1069 fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1071 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1083 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1085 if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt_v4l2) == -1) {
1090 fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1091 fmt_v4l2.fmt.pix.width = fmt_me.width;
1092 fmt_v4l2.fmt.pix.height = fmt_me.height;
1096 switch (m_frameformat) {
1098 fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1100 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1104 fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1106 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1122 if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1126 if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1131 unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1132 if (fmt_v4l2.fmt.pix.bytesperline < min)
1133 fmt_v4l2.fmt.pix.bytesperline = min;
1134 min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1135 if (fmt_v4l2.fmt.pix.sizeimage < min)
1136 fmt_v4l2.fmt.pix.sizeimage = min;
1138 fmt_me.width = fmt_v4l2.fmt.pix.width;
1139 fmt_me.height = fmt_v4l2.fmt.pix.height;
1140 fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1144 "v4l2: new capture params (%ux%u, %c%c%c%c, %d byte, %d bytes "
1146 fmt_me.width, fmt_me.height, fmt_v4l2.fmt.pix.pixelformat & 0xff,
1147 (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff, (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1148 (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff, fmt_v4l2.fmt.pix.sizeimage, fmt_v4l2.fmt.pix.bytesperline);
1159 void vpV4l2Grabber::startStreaming()
1161 if (streaming ==
true) {
1167 memset(&(reqbufs), 0,
sizeof(reqbufs));
1168 reqbufs.count = m_nbuffers;
1169 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1170 reqbufs.memory = V4L2_MEMORY_MMAP;
1172 if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1) {
1173 if (EINVAL == errno) {
1175 "%s does not support "
1183 for (
unsigned i = 0; i < reqbufs.count; i++) {
1185 memset(&(buf_v4l2[i]), 0,
sizeof(buf_v4l2[i]));
1186 buf_v4l2[i].index = i;
1187 buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1188 buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1189 buf_v4l2[i].length = 0;
1190 if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1) {
1193 memcpy(&buf_me[i].fmt, &fmt_me,
sizeof(ng_video_fmt));
1194 buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1196 buf_me[i].data = (
unsigned char *)v4l2_mmap(
nullptr, buf_v4l2[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1197 (off_t)buf_v4l2[i].m.offset);
1199 if (buf_me[i].data == MAP_FAILED) {
1203 buf_me[i].refcount = 0;
1206 printBufInfo(buf_v4l2[i]);
1213 if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type) < 0) {
1226 void vpV4l2Grabber::stopStreaming()
1229 if ((fd >= 0) && (streaming ==
true)) {
1233 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1234 if (v4l2_ioctl(fd, VIDIOC_STREAMOFF, &fmt_v4l2.type)) {
1238 for (
unsigned int i = 0; i < reqbufs.count; i++) {
1240 printBufInfo(buf_v4l2[i]);
1243 if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1266 unsigned char *vpV4l2Grabber::waiton(__u32 &index,
struct timeval ×tamp)
1268 struct v4l2_buffer buf;
1278 FD_SET(
static_cast<unsigned int>(fd), &rdset);
1279 switch (select(fd + 1, &rdset,
nullptr,
nullptr, &tv)) {
1293 memset(&buf, 0,
sizeof(buf));
1294 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1295 buf.memory = V4L2_MEMORY_MMAP;
1296 if (-1 == v4l2_ioctl(fd, VIDIOC_DQBUF, &buf)) {
1316 buf_v4l2[buf.index] = buf;
1320 field = buf_v4l2[index].field;
1322 timestamp = buf_v4l2[index].timestamp;
1330 return buf_me[buf.index].data;
1338 int vpV4l2Grabber::queueBuffer()
1340 unsigned int frame = queue % reqbufs.count;
1343 if (0 != buf_me[frame].refcount) {
1344 if (0 != queue - waiton_cpt)
1346 fprintf(stderr,
"v4l2: waiting for a free buffer..............\n");
1348 std::cout <<
"Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1352 rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1379 void vpV4l2Grabber::queueAll()
1382 if (queue - waiton_cpt >= reqbufs.count) {
1385 if (0 != queueBuffer()) {
1396 void vpV4l2Grabber::printBufInfo(
struct v4l2_buffer buf)
1401 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1404 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1405 type =
"video-over";
1407 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1410 case V4L2_BUF_TYPE_VBI_CAPTURE:
1413 case V4L2_BUF_TYPE_VBI_OUTPUT:
1421 fprintf(stdout,
"v4l2: buf %d: type %d (%s) ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n", buf.index, buf.type,
1422 type.c_str(), buf.m.userptr, buf.m.offset, buf.length, buf.length, buf.bytesused);
1477 #elif !defined(VISP_BUILD_SHARED_LIBS)
1479 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 YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
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
static const unsigned int DEFAULT_INPUT
vpV4l2PixelFormatType getPixelFormat()
static const unsigned int FRAME_SIZE
static const unsigned int DEFAULT_SCALE
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)