liudianwu |
2019-02-27 12:15 |
这个需要自己用v4l2写一个类。 - //查询设备属性
struct v4l2_capability cap; if(ioctl(camera_fd, VIDIOC_QUERYCAP, &cap) < 0) { qDebug() << TIMEMS << "error in VIDIOC_QUERYCAP"; close(camera_fd); return false; }
if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { qDebug() << TIMEMS << "it is not a video capture device"; close(camera_fd); return false; }
if(!(cap.capabilities & V4L2_CAP_STREAMING)) { qDebug() << TIMEMS << "it can not streaming"; close(camera_fd); return false; }
if(cap.capabilities == 0x4000001) { qDebug() << TIMEMS << "capabilities:" << "V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING"; }
//设置视频输入源 int input = 0; if(ioctl(camera_fd, VIDIOC_S_INPUT, &input) < 0) { qDebug() << TIMEMS << "error in VIDIOC_S_INPUT"; close(camera_fd); return false; }
//设置图片格式和分辨率 struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV ;//V4L2_PIX_FMT_YUV420 V4L2_PIX_FMT_YUYV fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; fmt.fmt.pix.width = cameraWidth; fmt.fmt.pix.height = cameraHeight;
if(ioctl(camera_fd, VIDIOC_S_FMT, &fmt) < 0) { close(camera_fd); return false; }
//查看图片格式和分辨率,判断是否设置成功 if(ioctl(camera_fd, VIDIOC_G_FMT, &fmt) < 0) { qDebug() << TIMEMS << "error in VIDIOC_G_FMT"; close(camera_fd); return false; }
//重新打印下宽高看下是否真正设置成功 qDebug() << TIMEMS << "cameraWidth =" << cameraWidth << "cameraHeight =" << cameraHeight << " width =" << fmt.fmt.pix.width << "height =" << fmt.fmt.pix.height; qDebug() << TIMEMS << "pixelformat =" << QString("%1%2%3%4").arg(QChar(fmt.fmt.pix.pixelformat & 0xFF)).arg(QChar((fmt.fmt.pix.pixelformat >> 8) & 0xFF)).arg(QChar((fmt.fmt.pix.pixelformat >> 16) & 0xFF)).arg(QChar((fmt.fmt.pix.pixelformat >> 24) & 0xFF));
//重新设置宽高为真实的宽高 cameraWidth = fmt.fmt.pix.width; cameraHeight = fmt.fmt.pix.height;
//设置帧格式 struct v4l2_streamparm parm; parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm.parm.capture.timeperframe.numerator = 1; parm.parm.capture.timeperframe.denominator = 25; parm.parm.capture.capturemode = 0;
if(ioctl(camera_fd, VIDIOC_S_PARM, &parm) < 0) { qDebug() << TIMEMS << "error in VIDIOC_S_PARM"; close(camera_fd); return false; }
if(ioctl(camera_fd, VIDIOC_G_PARM, &parm) < 0) { qDebug() << TIMEMS << "error in VIDIOC_G_PARM"; close(camera_fd); return false; }
//申请和管理缓冲区 struct v4l2_requestbuffers reqbuf; reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = 1;
if(ioctl(camera_fd, VIDIOC_REQBUFS, &reqbuf) < 0) { qDebug() << TIMEMS << "error in VIDIOC_REQBUFS"; close(camera_fd); return false; }
img_buffers = (ImgBuffer *)calloc(1, sizeof(ImgBuffer)); if(img_buffers == NULL) { qDebug() << TIMEMS << "error in calloc"; close(camera_fd); return false; }
struct v4l2_buffer buffer; for(int numBufs = 0; numBufs < 1; numBufs++) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = numBufs;
if(ioctl(camera_fd, VIDIOC_QUERYBUF, &buffer) < 0) { qDebug() << TIMEMS << "error in VIDIOC_QUERYBUF"; free(img_buffers); close(camera_fd); return false; }
img_buffers[numBufs].length = buffer.length; img_buffers[numBufs].start = (quint8 *)mmap (NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, camera_fd, buffer.m.offset); if(MAP_FAILED == img_buffers[numBufs].start) { qDebug() << TIMEMS << "error in mmap"; free(img_buffers); close(camera_fd); return false; }
//把缓冲帧放入队列 if(ioctl(camera_fd, VIDIOC_QBUF, &buffer) < 0) { qDebug() << TIMEMS << "error in VIDIOC_QBUF"; for(int i = 0; i <= numBufs; i++) { munmap(img_buffers[i].start, img_buffers[i].length); }
free(img_buffers); close(camera_fd); return false; } }
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(camera_fd, VIDIOC_STREAMON, &type) < 0) { qDebug() << TIMEMS << "error in VIDIOC_STREAMON"; for(int i = 0; i < 1; i++) { munmap(img_buffers[i].start, img_buffers[i].length); }
free(img_buffers); close(camera_fd); return false; }
qDebug() << TIMEMS << "init camera ok"; return true;
|
|