|
平台:TQ2440,内核2.4.30,摄像头中星微uvc无驱的
终端提示信息如下::::
USB Camera Test
dth = 160 Height = 120
frame buffer: 480x272, 16bpp, 0x3fc00byte= 261120
部分代码如下:
int main(int argc, char** argv)
{
int numBufs;
printf("USB Camera Test\n");
int fd = open("/dev/video0", O_RDWR, 0); //打开摄像头设备,使用阻塞方式打开
if (fd<0)
{
printf("open error\n");
return -1;
}
struct v4l2_format fmt; //设置获取视频的格式
memset( &fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //视频数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //视频源的格式为JPEG或YUN4:2:2或RGB
fmt.fmt.pix.width = 640; //设置视频宽度
fmt.fmt.pix.height = 480; //设置视频高度
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) //使配置生效
{
printf("set format failed\n");
return -1;
}
struct v4l2_requestbuffers req; //申请帧缓冲
memset(&req, 0, sizeof (req));
req.count = 1; //缓存数量,即可保存的图片数量
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE
req.memory = V4L2_MEMORY_MMAP; //存储类型:V4L2_MEMORY_MMAP或V4L2_MEMORY_USERPTR
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) //使配置生效
{
perror("request buffer error \n");
return -1;
}
VideoBuffer *buffers = calloc(req.count, sizeof(VideoBuffer)); //将VIDIOC_REQBUFS获取内存转为物理空间
// printf("sizeof(VideoBuffer) is %d\n", sizeof(VideoBuffer));
struct v4l2_buffer buf;
for (numBufs = 0; numBufs < req.count; numBufs++)
{
memset( &buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE
buf.memory = V4L2_MEMORY_MMAP; //存储类型:V4L2_MEMORY_MMAP(内存映射)或V4L2_MEMORY_USERPTR(用户指针)
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) //使配置生效
{
printf("VIDIOC_QUERYBUF error\n");
return -1;
}
// printf("buf len is %d\n", sizeof(buf));
buffers[numBufs].length = buf.length;
buffers[numBufs].offset = (size_t) buf.m.offset;
buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, buf.m.offset); //使用mmap函数将申请的缓存地址转换应用程序的绝对地址
#if 0
printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n",
buffers[numBufs].length, buffers[numBufs].offset,
buffers[numBufs].start[0]);
printf("buf2 len is %d\n", sizeof(buffers[numBufs].start));
#endif
if (buffers[numBufs].start == MAP_FAILED)
{
perror("buffers error\n");
return -1;
}
if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) //放入缓存队列
{
printf("VIDIOC_QBUF error\n");
return -1;
}
}
enum v4l2_buf_type type; //开始视频显示
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE
if (ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
printf("VIDIOC_STREAMON error\n");
return -1;
}
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,永远都是V4L2_BUF_TYPE_VIDEO_CAPTURE
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) //读取视频源格式
{
printf("get format failed\n");
return -1;
}
else
{
printf("Picture:Width = %d Height = %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
// printf("Image size = %d\n", fmt.fmt.pix.sizeimage);
// printf("pixelformat = %d\n", fmt.fmt.pix.pixelformat);
}
FILE * fd_y_file = 0;
int a=0;
int k = 0;
//设置显卡设备framebuffer
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *infile; //Jpeg文件的句柄
unsigned char *buffer;
int fb;
char *fb_device;
unsigned int x;
unsigned int y;
if ((fb = open("/dev/fb0", O_RDWR)) < 0) //打开显卡设备
{
perror(__func__);
return (-1);
}
//获取framebuffer的状态
fb_stat(fb); //获取显卡驱动中的长、宽和显示位宽
printf("frame buffer: %dx%d, %dbpp, 0x%xbyte= %d\n",
fbdev.fb_width, fbdev.fb_height, fbdev.fb_bpp, fbdev.fb_size, fbdev.fb_size);
//映射framebuffer的地址
fbdev.fb_mem = mmap (NULL, fbdev.fb_size, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
//映射显存地址
fbdev.fb = fb;
//预览采集到的图像
while (1)
{
//如果把处理JPEG格式的数据和显示程序分离,把处理JPEG部分的数据作成一个新的线程,预览时会更加流畅。
for (numBufs = 0; numBufs < req.count; numBufs++)
{
char s[15];
sprintf(s, "%d.jpg", a);
if ((fd_y_file = fopen(s, "wb")) < 0)
{
printf("Unable to create y frame recording file\n");
return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //取得原始采集数据
buf.memory = V4L2_MEMORY_MMAP; //存储类型:V4L2_MEMORY_MMAP(内存映射)或V4L2_MEMORY_USERPTR(用户指针)
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0)//程序运行到这里就不动了,不知道什么原因?
{
perror("VIDIOC_DQBUF failed.\n");
return -1;
}
|
|