这是一个V4L2的摄像头程序,驱动已经有了,这个驱动可以获取到一张图片并保持到根目录下,我如何就获取的摄像头数据实时的显示到LCD屏幕上去呢?求大神一起分析,我搞了很久了。谢谢
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include time.h>
#include
#include
#include
#include
#define CAMERA_DEVICE "/dev/video0"
#define CAPTURE_FILE "frame.avi"
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT 4
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
VideoBuffer framebuf[BUFFER_COUNT];
int main()
{
int i, ret;
// 打开设备
int fd;
fd = open(CAMERA_DEVICE, O_RDWR, 0);
if (fd < 0) {
printf("Open %s failedn", CAMERA_DEVICE);
return -1;
}
// 获取驱动信息
struct v4l2_capability cap;
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if (ret < 0) {
printf("VIDIOC_QUERYCAP failed (%d)n", ret);
return ret;
}
// Print capability infomations
printf("Capability Informations:n");
printf(" driver: %sn", cap.driver);
printf(" card: %sn", cap.card);
printf(" bus_info: %sn", cap.bus_info);
printf(" version: %08Xn", cap.version);
printf(" capabilities: %08Xn", cap.capabilities);
// 设置视频格式
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = VIDEO_WIDTH;
fmt.fmt.pix.height = VIDEO_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
if (ret < 0) {
printf("VIDIOC_S_FMT failed (%d)n", ret);
return ret;
}
// 获取视频格式
ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
if (ret < 0) {
printf("VIDIOC_G_FMT failed (%d)n", ret);
return ret;
}
// Print Stream Format
printf("Stream Format Informations:n");
printf(" type: %dn", fmt.type);
printf(" width: %dn", fmt.fmt.pix.width);
printf(" height: %dn", fmt.fmt.pix.height);
char fmtstr[8];
memset(fmtstr, 0, 8);
memcpy(fmtstr, &fmt.fmt.pix.pixelformat, 4);
printf(" pixelformat: %sn", fmtstr);
printf(" field: %dn", fmt.fmt.pix.field);
printf(" bytesperline: %dn", fmt.fmt.pix.bytesperline);
printf(" sizeimage: %dn", fmt.fmt.pix.sizeimage);
printf(" colorspace: %dn", fmt.fmt.pix.colorspace);
printf(" priv: %dn", fmt.fmt.pix.priv);
printf(" raw_date: %sn", fmt.fmt.raw_data);
// 请求分配内存
struct v4l2_requestbuffers reqbuf;
reqbuf.count = BUFFER_COUNT;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);
if(ret < 0) {
printf("VIDIOC_REQBUFS failed (%d)n", ret);
return ret;
}
// 获取空间
VideoBuffer* buffers = calloc( reqbuf.count, sizeof(*buffers) );
struct v4l2_buffer buf;
for (i = 0; i < reqbuf.count; i++)
{
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//读取缓存
ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);
if(ret < 0) {
printf("VIDIOC_QUERYBUF (%d) failed (%d)n", i, ret);
return ret;
}
// mmap buffer
framebuf[i].length = buf.length;
// 转换成相对地址
framebuf[i].start = (char *) mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (framebuf[i].start == MAP_FAILED) {
printf("mmap (%d) failed: %sn", i, strerror(errno));
return -1;
}
// Queen buffer 放入缓存队列
ret = ioctl(fd , VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("VIDIOC_QBUF (%d) failed (%d)n", i, ret);
return -1;
}
printf("Frame buffer %d: address=0x%x, length=%dn", i, (unsigned int)framebuf[i].start, framebuf[i].length);
}
// 开始录制
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd,VIDIOC_STREAMON, &type);
if (ret < 0) {
printf("VIDIOC_STREAMON failed (%d)n", ret);
return ret;
}
// Get frame
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if (ret < 0) {
printf("VIDIOC_DQBUF failed (%d)n", ret);
return ret;
}
// Process the frame
FILE *fp = fopen(CAPTURE_FILE, "wb");
if (fp < 0) {
printf("open frame data file failedn");
return -1;
}
fwrite(framebuf[buf.index].start, 1, buf.length, fp);
fclose(fp);
printf("Capture one frame saved in %sn", CAPTURE_FILE);
// Re-queen buffer
ret = ioctl(fd, VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("VIDIOC_QBUF failed (%d)n", ret);
return ret;
}
// Release the resource
for (i=0; i< 4; i++)
{
munmap(framebuf[i].start, framebuf[i].length);
}
close(fd);
printf("Camera test Done.n");
return 0;
}
|