利用c++ 写一个相机程序 测试相机是否能有码流输出 不依赖opencv
时间: 2024-04-29 08:22:20 浏览: 201
基于c++的摄像头测试程序 实例
3星 · 编辑精心推荐
以下是一个简单的 C++ 程序,用于测试相机是否能够输出码流。该程序使用了 V4L2 库,不依赖于 OpenCV 库。你可以根据自己的需要进行修改和调整。
```c++
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define CAMERA_DEVICE "/dev/video0"
#define CAPTURE_WIDTH 640
#define CAPTURE_HEIGHT 480
#define BUFFER_COUNT 1
int main()
{
// 打开设备
int camera_fd = open(CAMERA_DEVICE, O_RDWR);
if (camera_fd == -1) {
std::cerr << "Failed to open camera device." << std::endl;
return -1;
}
// 查询设备能力
struct v4l2_capability cap;
if (ioctl(camera_fd, VIDIOC_QUERYCAP, &cap) == -1) {
std::cerr << "Failed to query device capabilities." << std::endl;
close(camera_fd);
return -1;
}
// 设置视频格式
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = CAPTURE_WIDTH;
fmt.fmt.pix.height = CAPTURE_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (ioctl(camera_fd, VIDIOC_S_FMT, &fmt) == -1) {
std::cerr << "Failed to set video format." << std::endl;
close(camera_fd);
return -1;
}
// 分配帧缓冲区
struct v4l2_requestbuffers reqbuf;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.count = BUFFER_COUNT;
reqbuf.memory = V4L2_MEMORY_MMAP;
if (ioctl(camera_fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
std::cerr << "Failed to request buffers." << std::endl;
close(camera_fd);
return -1;
}
// 映射帧缓冲区
struct v4l2_buffer buf;
void *buffer_start[BUFFER_COUNT];
for (int i = 0; i < BUFFER_COUNT; i++) {
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (ioctl(camera_fd, VIDIOC_QUERYBUF, &buf) == -1) {
std::cerr << "Failed to query buffer information." << std::endl;
close(camera_fd);
return -1;
}
buffer_start[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, camera_fd, buf.m.offset);
if (buffer_start[i] == MAP_FAILED) {
std::cerr << "Failed to map buffer." << std::endl;
close(camera_fd);
return -1;
}
}
// 将帧缓冲区加入队列
for (int i = 0; i < BUFFER_COUNT; i++) {
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (ioctl(camera_fd, VIDIOC_QBUF, &buf) == -1) {
std::cerr << "Failed to queue buffer." << std::endl;
close(camera_fd);
return -1;
}
}
// 开始采集
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(camera_fd, VIDIOC_STREAMON, &type) == -1) {
std::cerr << "Failed to start streaming." << std::endl;
close(camera_fd);
return -1;
}
// 从队列中取出帧缓冲区
while (true) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(camera_fd, &fds);
timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
int r = select(camera_fd + 1, &fds, NULL, NULL, &tv);
if (r == -1) {
std::cerr << "Failed to select." << std::endl;
close(camera_fd);
return -1;
} else if (r == 0) {
std::cerr << "Select timeout." << std::endl;
close(camera_fd);
return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (ioctl(camera_fd, VIDIOC_DQBUF, &buf) == -1) {
std::cerr << "Failed to dequeue buffer." << std::endl;
close(camera_fd);
return -1;
}
// 在这里处理图像数据,例如保存到文件或者显示到屏幕上
if (ioctl(camera_fd, VIDIOC_QBUF, &buf) == -1) {
std::cerr << "Failed to queue buffer." << std::endl;
close(camera_fd);
return -1;
}
}
// 停止采集
if (ioctl(camera_fd, VIDIOC_STREAMOFF, &type) == -1) {
std::cerr << "Failed to stop streaming." << std::endl;
close(camera_fd);
return -1;
}
// 释放帧缓冲区
for (int i = 0; i < BUFFER_COUNT; i++) {
if (munmap(buffer_start[i], buf.length) == -1) {
std::cerr << "Failed to unmap buffer." << std::endl;
close(camera_fd);
return -1;
}
}
// 关闭设备
close(camera_fd);
return 0;
}
```
该程序首先打开设备 `/dev/video0`,然后查询设备能力和设置视频格式。接着分配和映射帧缓冲区,并将其加入队列。程序进入循环后,从队列中取出帧缓冲区并处理图像数据,然后将其重新加入队列。最后停止采集,释放帧缓冲区,并关闭设备。
你可以在程序中添加代码来处理图像数据,例如将其保存到文件或者显示到屏幕上。在这个例子中,我们只是简单地取出了帧缓冲区,没有进行任何处理。如果相机能够输出码流,那么程序应该能够正常运行并输出一些调试信息。
阅读全文