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(NULL), std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
148 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
203 : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
204 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(verbose), m_nbuffers(3), field(0),
249 : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
250 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
295 : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
296 buf_v4l2(NULL), buf_me(NULL), queue(0), waiton_cpt(0), index_buffer(0), m_verbose(false), m_nbuffers(3), field(0),
344 : fd(-1), device(), cap(), streamparm(), inp(NULL), std(NULL), fmt(NULL), ctl(NULL), fmt_v4l2(), fmt_me(), reqbufs(),
345 buf_v4l2(NULL), buf_me(NULL), 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;
423 std::cout <<
"Requested pixel format [" << req_pixelformat <<
"] not compatible with camera" << std::endl;
424 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
429 if (format == req_pixelformat) {
437 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;
484 std::cout <<
"Requested pixel format [" << m_pixelformat <<
"] not compatible with camera" << std::endl;
485 std::cout <<
"Try to found a compatible pixel format..." << std::endl;
490 if (format == req_pixelformat) {
498 std::cout <<
"This format [" << m_pixelformat <<
"] is compatible with camera" << std::endl;
503 std::cout <<
"This format [" << m_pixelformat <<
"] is not compatible with camera" << std::endl;
525 struct timeval timestamp;
544 struct timeval timestamp;
580 unsigned char *bitmap;
581 bitmap = waiton(index_buffer, timestamp);
587 switch (m_pixelformat) {
632 std::cout <<
"V4L2 conversion not handled" << std::endl;
651 struct timeval timestamp;
670 struct timeval timestamp;
706 unsigned char *bitmap;
707 bitmap = waiton(index_buffer, timestamp);
717 switch (m_pixelformat) {
740 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
741 memcpy(
static_cast<void *
>(I.
bitmap),
742 static_cast<void *
>(bitmap + 1 + (
unsigned int)(roi.
getTop() *
width + roi.
getLeft())),
767 std::cout <<
"V4l2 conversion not handled" << std::endl;
818 this->m_framerate = framerate;
867 if (buf_v4l2 != NULL) {
871 if (buf_me != NULL) {
888 void vpV4l2Grabber::open()
893 if (-1 == stat(device.c_str(), &st)) {
894 fprintf(stderr,
"Cannot identify '%s': %d, %s\n", device.c_str(), errno, strerror(errno));
898 if (!S_ISCHR(st.st_mode)) {
899 fprintf(stderr,
"%s is no device\n", device.c_str());
902 fd = v4l2_open(device.c_str(), O_RDWR | O_NONBLOCK, 0);
926 if (buf_v4l2 != NULL) {
930 if (buf_me != NULL) {
943 if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
945 fprintf(stderr,
"%s is no V4L2 device\n", device.c_str());
952 " %s %d.%d.%d / %s @ %s\n",
953 device.c_str(), cap.driver, (cap.version >> 16) & 0xff, (cap.version >> 8) & 0xff, cap.version & 0xff,
954 cap.card, cap.bus_info);
955 if (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
956 fprintf(stdout,
" Support overlay\n");
958 fprintf(stdout,
" Does not support overlay\n");
959 if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
960 fprintf(stdout,
" Support capture\n");
962 fprintf(stdout,
" Does not support capture\n");
963 if (cap.capabilities & V4L2_CAP_TUNER)
964 fprintf(stdout,
" Support tuning\n");
966 fprintf(stdout,
" Does not support tuning\n");
967 if (cap.capabilities & V4L2_CAP_STREAMING)
968 fprintf(stdout,
" Support streaming capture.\n");
970 fprintf(stdout,
" Does not support streaming capture\n");
971 if (cap.capabilities & V4L2_CAP_ASYNCIO)
972 fprintf(stdout,
" Support asynchronous I/O methods\n");
974 fprintf(stdout,
" Does not support asynchronous I/O methods\n");
975 if (cap.capabilities & V4L2_CAP_TIMEPERFRAME)
976 fprintf(stdout,
" Support time per frame field\n");
978 fprintf(stdout,
" Does not support time per frame field\n");
980 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
981 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) != -1) {
982 fprintf(stdout,
" Current acquisition framerate: %d fps\n", streamparm.parm.output.timeperframe.denominator);
995 void vpV4l2Grabber::getCapabilities()
997 for (__u32 ninputs = 0; ninputs <
MAX_INPUTS; ninputs++) {
998 inp[ninputs].index = ninputs;
999 if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &inp[ninputs]))
1002 for (__u32 nstds = 0; nstds <
MAX_NORM; nstds++) {
1003 std[nstds].index = nstds;
1004 if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &std[nstds]))
1007 for (__u32 nfmts = 0; nfmts <
MAX_FORMAT; nfmts++) {
1008 fmt[nfmts].index = nfmts;
1009 fmt[nfmts].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1010 if (v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &fmt[nfmts]))
1014 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1015 if (v4l2_ioctl(fd, VIDIOC_G_PARM, &streamparm) == -1) {
1035 void vpV4l2Grabber::setFormat()
1037 fmt_me.width =
width;
1043 switch (m_pixelformat) {
1045 fmt_me.pixelformat = V4L2_PIX_FMT_GREY;
1047 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_GREY)\n");
1050 fmt_me.pixelformat = V4L2_PIX_FMT_RGB24;
1052 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB24)\n");
1055 fmt_me.pixelformat = V4L2_PIX_FMT_RGB32;
1057 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_RGB32)\n");
1060 fmt_me.pixelformat = V4L2_PIX_FMT_BGR24;
1062 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_BGR24)\n");
1065 fmt_me.pixelformat = V4L2_PIX_FMT_YUYV;
1067 fprintf(stdout,
"v4l2: new capture params (V4L2_PIX_FMT_YUYV)\n");
1079 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1081 if (v4l2_ioctl(fd, VIDIOC_G_FMT, &fmt_v4l2) == -1) {
1086 fmt_v4l2.fmt.pix.pixelformat = fmt_me.pixelformat;
1087 fmt_v4l2.fmt.pix.width = fmt_me.width;
1088 fmt_v4l2.fmt.pix.height = fmt_me.height;
1092 switch (m_frameformat) {
1094 fmt_v4l2.fmt.pix.field = V4L2_FIELD_ALTERNATE;
1096 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_ALTERNATE)\n");
1100 fmt_v4l2.fmt.pix.field = V4L2_FIELD_INTERLACED;
1102 fprintf(stdout,
"v4l2: new capture params (V4L2_FIELD_INTERLACED)\n");
1118 if (v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt_v4l2) == -1) {
1122 if (fmt_v4l2.fmt.pix.pixelformat != fmt_me.pixelformat) {
1127 unsigned int min = fmt_v4l2.fmt.pix.width * 2;
1128 if (fmt_v4l2.fmt.pix.bytesperline < min)
1129 fmt_v4l2.fmt.pix.bytesperline = min;
1130 min = fmt_v4l2.fmt.pix.bytesperline * fmt_v4l2.fmt.pix.height;
1131 if (fmt_v4l2.fmt.pix.sizeimage < min)
1132 fmt_v4l2.fmt.pix.sizeimage = min;
1134 fmt_me.width = fmt_v4l2.fmt.pix.width;
1135 fmt_me.height = fmt_v4l2.fmt.pix.height;
1136 fmt_me.bytesperline = fmt_v4l2.fmt.pix.bytesperline;
1140 "v4l2: new capture params (%ux%u, %c%c%c%c, %d byte, %d bytes "
1142 fmt_me.width, fmt_me.height, fmt_v4l2.fmt.pix.pixelformat & 0xff,
1143 (fmt_v4l2.fmt.pix.pixelformat >> 8) & 0xff, (fmt_v4l2.fmt.pix.pixelformat >> 16) & 0xff,
1144 (fmt_v4l2.fmt.pix.pixelformat >> 24) & 0xff, fmt_v4l2.fmt.pix.sizeimage, fmt_v4l2.fmt.pix.bytesperline);
1155 void vpV4l2Grabber::startStreaming()
1157 if (streaming ==
true) {
1163 memset(&(reqbufs), 0,
sizeof(reqbufs));
1164 reqbufs.count = m_nbuffers;
1165 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1166 reqbufs.memory = V4L2_MEMORY_MMAP;
1168 if (v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs) == -1) {
1169 if (EINVAL == errno) {
1171 "%s does not support "
1179 for (
unsigned i = 0; i < reqbufs.count; i++) {
1181 memset(&(buf_v4l2[i]), 0,
sizeof(buf_v4l2[i]));
1182 buf_v4l2[i].index = i;
1183 buf_v4l2[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1184 buf_v4l2[i].memory = V4L2_MEMORY_MMAP;
1185 buf_v4l2[i].length = 0;
1186 if (v4l2_ioctl(fd, VIDIOC_QUERYBUF, &buf_v4l2[i]) == -1) {
1189 memcpy(&buf_me[i].fmt, &fmt_me,
sizeof(ng_video_fmt));
1190 buf_me[i].size = buf_me[i].fmt.bytesperline * buf_me[i].fmt.height;
1198 buf_me[i].data = (
unsigned char *)v4l2_mmap(NULL, buf_v4l2[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
1199 (off_t)buf_v4l2[i].m.offset);
1201 if (buf_me[i].data == MAP_FAILED) {
1205 buf_me[i].refcount = 0;
1218 printBufInfo(buf_v4l2[i]);
1225 if (v4l2_ioctl(fd, VIDIOC_STREAMON, &fmt_v4l2.type) < 0) {
1238 void vpV4l2Grabber::stopStreaming()
1241 if ((fd >= 0) && (streaming ==
true)) {
1245 fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1246 if (v4l2_ioctl(fd, VIDIOC_STREAMOFF, &fmt_v4l2.type)) {
1250 for (
unsigned int i = 0; i < reqbufs.count; i++) {
1252 printBufInfo(buf_v4l2[i]);
1255 if (-1 == v4l2_munmap(buf_me[i].data, buf_me[i].size)) {
1278 unsigned char *vpV4l2Grabber::waiton(__u32 &index,
struct timeval ×tamp)
1280 struct v4l2_buffer buf;
1290 FD_SET(
static_cast<unsigned int>(fd), &rdset);
1291 switch (select(fd + 1, &rdset, NULL, NULL, &tv)) {
1305 memset(&buf, 0,
sizeof(buf));
1306 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1307 buf.memory = V4L2_MEMORY_MMAP;
1308 if (-1 == v4l2_ioctl(fd, VIDIOC_DQBUF, &buf)) {
1328 buf_v4l2[buf.index] = buf;
1332 field = buf_v4l2[index].field;
1334 timestamp = buf_v4l2[index].timestamp;
1342 return buf_me[buf.index].data;
1350 int vpV4l2Grabber::queueBuffer()
1352 unsigned int frame = queue % reqbufs.count;
1355 if (0 != buf_me[frame].refcount) {
1356 if (0 != queue - waiton_cpt)
1358 fprintf(stderr,
"v4l2: waiting for a free buffer..............\n");
1360 std::cout <<
"Normalement call ng_waiton_video_buf(buf_me+frame); --------\n";
1364 rc = v4l2_ioctl(fd, VIDIOC_QBUF, &buf_v4l2[frame]);
1391 void vpV4l2Grabber::queueAll()
1394 if (queue - waiton_cpt >= reqbufs.count) {
1397 if (0 != queueBuffer()) {
1408 void vpV4l2Grabber::printBufInfo(
struct v4l2_buffer buf)
1413 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1416 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1417 type =
"video-over";
1419 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1422 case V4L2_BUF_TYPE_VBI_CAPTURE:
1425 case V4L2_BUF_TYPE_VBI_OUTPUT:
1433 fprintf(stdout,
"v4l2: buf %d: type %d (%s) ad: 0x%lx offset 0x%x+%d (=0x%x),used %d\n", buf.index, buf.type,
1434 type.c_str(), buf.m.userptr, buf.m.offset, buf.length, buf.length, buf.bytesused);
1481 #elif !defined(VISP_BUILD_SHARED_LIBS)
1484 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)