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) {
740 memcpy(static_cast<void*>(I.
bitmap), static_cast<void*>(bitmap + 1), height *
width *
sizeof(
vpRGBa) - 1);
741 I[height - 1][
width - 1].A = 0;
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) {
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) {
937 inp =
new struct v4l2_input[vpV4l2Grabber::
MAX_INPUTS];
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(){};
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static const unsigned int MAX_CTRL
void acquire(vpImage< unsigned char > &I)
static void YUYVToRGBa(unsigned char *yuyv, unsigned char *rgba, unsigned int width, unsigned int height)
void open(vpImage< unsigned char > &I)
static const __u32 MAX_FORMAT
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
vpV4l2FramerateType getFramerate()
Type * bitmap
points toward the bitmap
void setDevice(const std::string &devname)
vpV4l2PixelFormatType getPixelFormat()
static const unsigned int DEFAULT_INPUT
Error that can be emited by the vpFrameGrabber class and its derivates.
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)
vpV4l2Grabber & operator>>(vpImage< unsigned char > &I)
static const unsigned int FRAME_SIZE
void setHeight(unsigned h)
unsigned int height
Number of rows in the image.
static void YUYVToGrey(unsigned char *yuyv, unsigned char *grey, unsigned int size)
static const __u32 MAX_INPUTS
static void RGBaToGrey(unsigned char *rgba, unsigned char *grey, unsigned int width, unsigned int height, unsigned int nThreads=0)
void setWidth(unsigned w)
static const __u32 MAX_NORM
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setInput(unsigned input=vpV4l2Grabber::DEFAULT_INPUT)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
bool init
Set to true if the frame grabber has been initialized.
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
unsigned int getHeight() const
Defines a rectangle in the plane.
void setNBuffers(unsigned nbuffers)
unsigned int getWidth() const
unsigned int width
Number of columns in the image.
void setPixelFormat(vpV4l2PixelFormatType pixelformat)
static const unsigned int DEFAULT_SCALE
static const unsigned int MAX_BUFFERS
void setFramerate(vpV4l2FramerateType framerate)