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),
745 static_cast<void *
>(bitmap + 1 + (
unsigned int)(roi.
getTop() *
width + roi.
getLeft())),
770 std::cout <<
"V4l2 conversion not handled" << std::endl;
821 this->m_framerate = framerate;
870 if (buf_v4l2 != NULL) {
874 if (buf_me != NULL) {
891 void vpV4l2Grabber::open()
896 if (-1 == stat(device, &st)) {
897 fprintf(stderr,
"Cannot identify '%s': %d, %s\n", device, errno, strerror(errno));
901 if (!S_ISCHR(st.st_mode)) {
902 fprintf(stderr,
"%s is no device\n", device);
905 fd = v4l2_open(device, O_RDWR | O_NONBLOCK, 0);
929 if (buf_v4l2 != NULL) {
933 if (buf_me != NULL) {
946 if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
948 fprintf(stderr,
"%s is no V4L2 device\n", device);
955 " %s %d.%d.%d / %s @ %s\n",
956 device, cap.driver, (cap.version >> 16) & 0xff, (cap.version >> 8) & 0xff, cap.version & 0xff, cap.card,
958 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
959 fprintf(stdout,
" Support overlay\n");
961 fprintf(stdout,
" Does not support overlay\n");
962 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
963 fprintf(stdout,
" Support capture\n");
965 fprintf(stdout,
" Does not support capture\n");
966 if (cap.capabilities & V4L2_CAP_TUNER)
967 fprintf(stdout,
" Support tuning\n");
969 fprintf(stdout,
" Does not support tuning\n");
970 if (cap.capabilities & V4L2_CAP_STREAMING)
971 fprintf(stdout,
" Support streaming capture.\n");
973 fprintf(stdout,
" Does not support streaming capture\n");
974 if (cap.capabilities & V4L2_CAP_ASYNCIO)
975 fprintf(stdout,
" Support asynchronous I/O methods\n");
977 fprintf(stdout,
" Does not support asynchronous I/O methods\n");
978 if (cap.capabilities & V4L2_CAP_TIMEPERFRAME)
979 fprintf(stdout,
" Support time per frame field\n");
981 fprintf(stdout,
" Does not support time per frame field\n");
983 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
984 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
985 fprintf(stdout,
" Current acquisition framerate: %d fps\n", streamparm.parm.output.timeperframe.denominator);
998 void vpV4l2Grabber::getCapabilities()
1000 for (__u32 ninputs = 0; ninputs <
MAX_INPUTS; ninputs++) {
1001 inp[ninputs].index = ninputs;
1002 if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1005 for (__u32 nstds = 0; nstds <
MAX_NORM; nstds++) {
1006 std[nstds].index = nstds;
1007 if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
1010 for (__u32 nfmts = 0; nfmts <
MAX_FORMAT; nfmts++) {
1011 fmt[nfmts].index = nfmts;
1012 fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1013 if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1017 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1018 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
1038 void vpV4l2Grabber::setFormat()
1040 fmt_me.width =
width;
1046 switch (m_pixelformat) {
1048 fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1050 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1053 fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1055 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1058 fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1060 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1063 fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1065 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1068 fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1070 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1082 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1084 if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt_v4l2) == -1) {
1089 fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1090 fmt_v4l2.fmt.pix.width = fmt_me.width;
1091 fmt_v4l2.fmt.pix.height = fmt_me.height;
1095 switch (m_frameformat) {
1097 fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1099 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1103 fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1105 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1121 if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1125 if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1130 unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1131 if (fmt_v4l2.fmt.pix.bytesperline < min)
1132 fmt_v4l2.fmt.pix.bytesperline = min;
1133 min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1134 if (fmt_v4l2.fmt.pix.sizeimage < min)
1135 fmt_v4l2.fmt.pix.sizeimage = min;
1137 fmt_me.width = fmt_v4l2.fmt.pix.width;
1138 fmt_me.height = fmt_v4l2.fmt.pix.height;
1139 fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1143 "v4l2: new capture params (%ux%u, %c%c%c%c, %d byte, %d bytes "
1145 fmt_me.width, fmt_me.height, fmt_v4l2.fmt.pix.pixelformat & 0xff,
1146 (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff, (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1147 (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff, fmt_v4l2.fmt.pix.sizeimage, fmt_v4l2.fmt.pix.bytesperline);
1158 void vpV4l2Grabber::startStreaming()
1160 if (streaming ==
true) {
1166 memset(&(reqbufs), 0,
sizeof(reqbufs));
1167 reqbufs.count = m_nbuffers;
1168 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1169 reqbufs.memory = V4L2_MEMORY_MMAP;
1171 if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1) {
1172 if (EINVAL == errno) {
1174 "%s does not support "
1182 for (
unsigned i = 0; i < reqbufs.count; i++) {
1184 memset(&(buf_v4l2[i]), 0,
sizeof(buf_v4l2[i]));
1185 buf_v4l2[i].index = i;
1186 buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1187 buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1188 buf_v4l2[i].length = 0;
1189 if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1) {
1192 memcpy(&buf_me[i].fmt, &fmt_me,
sizeof(ng_video_fmt));
1193 buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1201 buf_me[i].data = (
unsigned char *)v4l2_mmap(NULL, buf_v4l2[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1202 (off_t)buf_v4l2[i].m.offset);
1204 if (buf_me[i].data == MAP_FAILED) {
1208 buf_me[i].refcount = 0;
1221 printBufInfo(buf_v4l2[i]);
1228 if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type) < 0) {
1241 void vpV4l2Grabber::stopStreaming()
1244 if ((fd >= 0) && (streaming ==
true)) {
1248 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1249 if (v4l2_ioctl(fd, VIDIOC_STREAMOFF, &fmt_v4l2.type)) {
1253 for (
unsigned int i = 0; i < reqbufs.count; i++) {
1255 printBufInfo(buf_v4l2[i]);
1258 if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1281 unsigned char *vpV4l2Grabber::waiton(__u32 &index,
struct timeval ×tamp)
1283 struct v4l2_buffer buf;
1293 FD_SET(
static_cast<unsigned int>(fd), &rdset);
1294 switch (select(fd + 1, &rdset, NULL, NULL, &tv)) {
1308 memset(&buf, 0,
sizeof(buf));
1309 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1310 buf.memory = V4L2_MEMORY_MMAP;
1311 if (-1 == v4l2_ioctl(fd, VIDIOC_DQBUF, &buf)) {
1331 buf_v4l2[buf.index] = buf;
1335 field = buf_v4l2[index].field;
1337 timestamp = buf_v4l2[index].timestamp;
1345 return buf_me[buf.index].data;
1353 int vpV4l2Grabber::queueBuffer()
1355 unsigned int frame = queue % reqbufs.count;
1358 if (0 != buf_me[frame].refcount) {
1359 if (0 != queue - waiton_cpt)
1361 fprintf(stderr,
"v4l2: waiting for a free buffer..............\n");
1363 std::cout <<
"Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1367 rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1394 void vpV4l2Grabber::queueAll()
1397 if (queue - waiton_cpt >= reqbufs.count) {
1400 if (0 != queueBuffer()) {
1411 void vpV4l2Grabber::printBufInfo(
struct v4l2_buffer buf)
1416 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1417 sprintf(type,
"video-cap");
1419 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1420 sprintf(type,
"video-over");
1422 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1423 sprintf(type,
"video-out");
1425 case V4L2_BUF_TYPE_VBI_CAPTURE:
1426 sprintf(type,
"vbi-cap");
1428 case V4L2_BUF_TYPE_VBI_OUTPUT:
1429 sprintf(type,
"vbi-out");
1432 sprintf(type,
"unknown");
1436 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,
1437 buf.m.offset, buf.length, buf.length, buf.bytesused);
1484 #elif !defined(VISP_BUILD_SHARED_LIBS)
1487 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)