45 #include <visp3/core/vpConfig.h>
54 #include <sys/ioctl.h>
58 #include <sys/types.h>
61 #include <visp3/core/vpFrameGrabberException.h>
62 #include <visp3/sensor/vpV4l2Grabber.h>
64 #include <visp3/core/vpImageConvert.h>
65 #include <visp3/core/vpImageTools.h>
75 #define vpCLEAR(x) memset(&(x), 0, sizeof(x))
150 : fd(-1), device(), cap(), streamparm(), inp(NULL),
std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
151 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
206 : fd(-1), device(), cap(), streamparm(), inp(NULL),
std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
207 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(verbose), m_nbuffers(3), field(0),
252 : fd(-1), device(), cap(), streamparm(), inp(NULL),
std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
253 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
298 : fd(-1), device(), cap(), streamparm(), inp(NULL),
std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
299 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
347 : fd(-1), device(), cap(), streamparm(), inp(NULL),
std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
348 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
389 if ((scale < 1) || (scale > 16)) {
392 vpERROR_TRACE(
"Wrong scale %d, scale should be between 1 and 16", scale);
414 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
415 std::cout <<
"Warning: cannot set input channel to " << m_input << std::endl;
426 std::cout <<
"Requested pixel format [" << req_pixelformat <<
"] not compatible with camera" << std::endl;
427 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
432 if (format == req_pixelformat) {
440 std::cout <<
"This format [" << m_pixelformat <<
"] is compatible with camera" << std::endl;
445 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
447 std::cout <<
"No pixel format compatible with the camera was found" << std::endl;
451 "No pixel format compatible with the camera was found"));
475 if (v4l2_ioctl(fd, VIDIOC_S_INPUT, &m_input) == -1) {
476 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;
506 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
528 struct timeval timestamp;
547 struct timeval timestamp;
583 unsigned char *bitmap;
584 bitmap = waiton(index_buffer, timestamp);
590 switch (m_pixelformat) {
635 std::cout <<
"V4L2 conversion not handled" << std::endl;
654 struct timeval timestamp;
673 struct timeval timestamp;
709 unsigned char *bitmap;
710 bitmap = waiton(index_buffer, timestamp);
720 switch (m_pixelformat) {
743 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
744 memcpy(
static_cast<void*
>(I.
bitmap),
static_cast<void*
>(bitmap + 1 + (
unsigned int)(roi.
getTop() *
width + roi.
getLeft())),
769 std::cout <<
"V4l2 conversion not handled" << std::endl;
820 this->m_framerate = framerate;
869 if (buf_v4l2 != NULL) {
873 if (buf_me != NULL) {
890 void vpV4l2Grabber::open()
895 if (-1 == stat(device, &st)) {
896 fprintf(stderr,
"Cannot identify '%s': %d, %s\n", device, errno, strerror(errno));
900 if (!S_ISCHR(st.st_mode)) {
901 fprintf(stderr,
"%s is no device\n", device);
904 fd = v4l2_open(device, O_RDWR | O_NONBLOCK, 0);
928 if (buf_v4l2 != NULL) {
932 if (buf_me != NULL) {
945 if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
947 fprintf(stderr,
"%s is no V4L2 device\n", device);
954 " %s %d.%d.%d / %s @ %s\n",
955 device, cap.driver, (cap.version >> 16) & 0xff, (cap.version >> 8) & 0xff, cap.version & 0xff, cap.card,
957 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
958 fprintf(stdout,
" Support overlay\n");
960 fprintf(stdout,
" Does not support overlay\n");
961 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
962 fprintf(stdout,
" Support capture\n");
964 fprintf(stdout,
" Does not support capture\n");
965 if (cap.capabilities & V4L2_CAP_TUNER)
966 fprintf(stdout,
" Support tuning\n");
968 fprintf(stdout,
" Does not support tuning\n");
969 if (cap.capabilities & V4L2_CAP_STREAMING)
970 fprintf(stdout,
" Support streaming capture.\n");
972 fprintf(stdout,
" Does not support streaming capture\n");
973 if (cap.capabilities & V4L2_CAP_ASYNCIO)
974 fprintf(stdout,
" Support asynchronous I/O methods\n");
976 fprintf(stdout,
" Does not support asynchronous I/O methods\n");
977 if (cap.capabilities & V4L2_CAP_TIMEPERFRAME)
978 fprintf(stdout,
" Support time per frame field\n");
980 fprintf(stdout,
" Does not support time per frame field\n");
982 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
983 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
984 fprintf(stdout,
" Current acquisition framerate: %d fps\n", streamparm.parm.output.timeperframe.denominator);
997 void vpV4l2Grabber::getCapabilities()
999 for (__u32 ninputs = 0; ninputs <
MAX_INPUTS; ninputs++) {
1000 inp[ninputs].index = ninputs;
1001 if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1004 for (__u32 nstds = 0; nstds <
MAX_NORM; nstds++) {
1005 std[nstds].index = nstds;
1006 if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &
std[nstds]))
1009 for (__u32 nfmts = 0; nfmts <
MAX_FORMAT; nfmts++) {
1010 fmt[nfmts].index = nfmts;
1011 fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1012 if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1016 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1017 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
1037 void vpV4l2Grabber::setFormat()
1039 fmt_me.width =
width;
1045 switch (m_pixelformat) {
1047 fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1049 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1052 fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1054 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1057 fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1059 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1062 fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1064 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1067 fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1069 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1081 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1083 if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt_v4l2) == -1) {
1088 fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1089 fmt_v4l2.fmt.pix.width = fmt_me.width;
1090 fmt_v4l2.fmt.pix.height = fmt_me.height;
1094 switch (m_frameformat) {
1096 fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1098 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1102 fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1104 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1120 if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1124 if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1129 unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1130 if (fmt_v4l2.fmt.pix.bytesperline < min)
1131 fmt_v4l2.fmt.pix.bytesperline = min;
1132 min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1133 if (fmt_v4l2.fmt.pix.sizeimage < min)
1134 fmt_v4l2.fmt.pix.sizeimage = min;
1136 fmt_me.width = fmt_v4l2.fmt.pix.width;
1137 fmt_me.height = fmt_v4l2.fmt.pix.height;
1138 fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1142 "v4l2: new capture params (%ux%u, %c%c%c%c, %d byte, %d bytes "
1144 fmt_me.width, fmt_me.height, fmt_v4l2.fmt.pix.pixelformat & 0xff,
1145 (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff, (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1146 (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff, fmt_v4l2.fmt.pix.sizeimage, fmt_v4l2.fmt.pix.bytesperline);
1157 void vpV4l2Grabber::startStreaming()
1159 if (streaming ==
true) {
1165 memset(&(reqbufs), 0,
sizeof(reqbufs));
1166 reqbufs.count = m_nbuffers;
1167 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1168 reqbufs.memory = V4L2_MEMORY_MMAP;
1170 if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1) {
1171 if (EINVAL == errno) {
1173 "%s does not support "
1181 for (
unsigned i = 0; i < reqbufs.count; i++) {
1183 memset(&(buf_v4l2[i]), 0,
sizeof(buf_v4l2[i]));
1184 buf_v4l2[i].index = i;
1185 buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1186 buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1187 buf_v4l2[i].length = 0;
1188 if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1) {
1191 memcpy(&buf_me[i].fmt, &fmt_me,
sizeof(ng_video_fmt));
1192 buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1200 buf_me[i].data = (
unsigned char *)v4l2_mmap(NULL, buf_v4l2[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1201 (off_t)buf_v4l2[i].m.offset);
1203 if (buf_me[i].data == MAP_FAILED) {
1207 buf_me[i].refcount = 0;
1220 printBufInfo(buf_v4l2[i]);
1227 if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type) < 0) {
1240 void vpV4l2Grabber::stopStreaming()
1243 if ((fd >= 0) && (streaming ==
true)) {
1247 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1248 if (v4l2_ioctl(fd, VIDIOC_STREAMOFF, &fmt_v4l2.type)) {
1252 for (
unsigned int i = 0; i < reqbufs.count; i++) {
1254 printBufInfo(buf_v4l2[i]);
1257 if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1280 unsigned char *vpV4l2Grabber::waiton(__u32 &index,
struct timeval ×tamp)
1282 struct v4l2_buffer buf;
1292 FD_SET(
static_cast<unsigned int>(fd), &rdset);
1293 switch (select(fd + 1, &rdset, NULL, NULL, &tv)) {
1307 memset(&buf, 0,
sizeof(buf));
1308 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1309 buf.memory = V4L2_MEMORY_MMAP;
1310 if (-1 == v4l2_ioctl(fd, VIDIOC_DQBUF, &buf)) {
1330 buf_v4l2[buf.index] = buf;
1334 field = buf_v4l2[index].field;
1336 timestamp = buf_v4l2[index].timestamp;
1344 return buf_me[buf.index].data;
1352 int vpV4l2Grabber::queueBuffer()
1354 unsigned int frame = queue % reqbufs.count;
1357 if (0 != buf_me[frame].refcount) {
1358 if (0 != queue - waiton_cpt)
1360 fprintf(stderr,
"v4l2: waiting for a free buffer..............\n");
1362 std::cout <<
"Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1366 rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1393 void vpV4l2Grabber::queueAll()
1396 if (queue - waiton_cpt >= reqbufs.count) {
1399 if (0 != queueBuffer()) {
1410 void vpV4l2Grabber::printBufInfo(
struct v4l2_buffer buf)
1415 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1416 sprintf(type,
"video-cap");
1418 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1419 sprintf(type,
"video-over");
1421 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1422 sprintf(type,
"video-out");
1424 case V4L2_BUF_TYPE_VBI_CAPTURE:
1425 sprintf(type,
"vbi-cap");
1427 case V4L2_BUF_TYPE_VBI_OUTPUT:
1428 sprintf(type,
"vbi-out");
1431 sprintf(type,
"unknown");
1435 fprintf(stdout,
"v4l2: buf %d: %d ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n", buf.index, buf.type, buf.m.userptr,
1436 buf.m.offset, buf.length, buf.length, buf.bytesused);
1483 #elif !defined(VISP_BUILD_SHARED_LIBS)
1486 void dummy_vpV4l2Grabber(){};
Error that can be emited by the vpFrameGrabber class and its derivates.
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)