Andrew Huang 转载请注明作者及联络方式
三星为测试CMOS模块,有一个简单的cam2fb.c 演示.它演示了RGB格式的CMOS摄像头,但是代码风格太乱了,因此我把代码重写,写成几个函数来简化处理.
这个代码只是简单的使用RGB格式,直接在屏幕上显示.
- /*
-
hxy_cam2fb.c
-
Author : Andrew Huang <bluedrum@163.com>
-
CMOS Camra RGB Format test
-
-
*/
-
#include <stdio.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <fcntl.h>
-
#include <unistd.h>
-
#include <ctype.h>
-
#include <errno.h>
-
#include <sys/mman.h>
-
#include <sys/time.h>
-
#include <sys/ioctl.h>
-
#include <asm/types.h>
-
#include <linux/videodev2.h>
-
#include <linux/fb.h>
-
#include <signal.h>
-
-
-
#define CAM_DEV_NAME "/dev/video0"
-
#define FB_DEV_NAME "/dev/fb0"
-
-
#define CAM_TYPE_RGB_16BPP (0)
-
#define CAM_TYPE_YUV_420 (1)
-
-
-
#define CAM_DATA_READ (0)
-
#define CAM_DATA_MMAP (1)
-
-
struct cam_dev {
-
int height;
-
int width;
-
int format;
-
int data_mode; /* 0 - 使用read(),1--使用mmap() 缓冲 */
-
-
int fd;
-
char * buf;
-
int buf_size;
-
};
-
-
struct fb_dev {
-
int height;
-
int width;
-
int bpp;
-
int bytes_by_pixel;
-
-
int fd;
-
char * buf;
-
int buf_size;
-
};
-
static inline void print_fps(struct timeval *s, struct timeval *e)
-
{
-
unsigned long time;
-
unsigned long sec;
-
unsigned long usec;
-
int fps = 0;
-
-
sec = e->tv_sec - s->tv_sec;
-
if (e->tv_usec > s->tv_usec)
-
usec = e->tv_usec - s->tv_usec;
-
else {
-
usec = e->tv_usec + 1000000 - s->tv_usec;
-
sec--;
-
}
-
time = sec * 1000 + (usec+1) / 1000;
-
-
if(time==0)
-
return;
-
-
fps = 30000 / time;
-
printf("%d fps\n", fps);
-
}
-
-
/* 打开FB设备 */
-
int fb_dev_open(struct fb_dev * pdev,int bpp,char * dev_name)
-
{
-
struct fb_var_screeninfo var;
-
-
-
if(dev_name == NULL)
-
dev_name = FB_DEV_NAME;
-
-
switch(bpp )
-
{
-
case 16:
-
pdev->bytes_by_pixel = 2;
-
break;
-
case 18:
-
case 24:
-
pdev->bytes_by_pixel = 4;
-
break;
-
default:
-
fprintf(stderr,"error bpp %d\n",bpp);
-
return -1;
-
}
-
-
-
pdev->fd = open(dev_name,O_RDWR);
-
if(pdev->fd == -1)
-
{
-
fprintf(stderr,"open %s failure\n",dev_name);
-
return -1;
-
}
-
-
if (ioctl(pdev->fd, FBIOGET_VSCREENINFO, &var)!=0)
-
{
-
close(pdev->fd);
-
perror("ioctl FBVAR");
-
return -2;
-
}
-
-
if(bpp != var.bits_per_pixel)
-
{
-
var.bits_per_pixel = bpp;
-
if (ioctl(pdev->fd, FBIOPUT_VSCREENINFO, &var)!=0)
-
{
-
close(pdev->fd);
-
perror("ioctl PUT FBVAR");
-
return -3;
-
}
-
}
-
-
pdev->width = var.xres;
-
pdev->height = var.yres;
-
pdev->bpp = bpp;
-
-
pdev->buf_size = pdev->width * pdev->height * pdev->bytes_by_pixel;
-
-
pdev->buf = mmap(NULL,pdev->buf_size,PROT_READ | PROT_WRITE, MAP_SHARED,pdev->fd,0);
-
if(pdev->buf == MAP_FAILED)
-
{
-
perror("mmap fb");
-
return -4;
-
}
-
-
-
printf("open fb %s :width %d,height %d ,bpp %d,buf 0x%x,size %d\n",
-
dev_name,pdev->width,pdev->height,pdev->bpp,pdev->buf,pdev->buf_size);
-
-
return 0;
-
-
}
-
-
int fb_dev_close(struct fb_dev* pdev)
-
{
-
munmap(pdev->buf,pdev->buf_size);
-
-
close(pdev->fd);
-
-
return 0;
-
}
-
-
-
int cam_dev_open(struct cam_dev * pdev,int width,int height,int format,int mode,char * dev_name)
-
{
-
struct v4l2_capability cap;
-
struct v4l2_input input;
-
struct v4l2_framebuffer fb;
-
int ret,on,index = 0;
-
-
if(dev_name == NULL)
-
dev_name = CAM_DEV_NAME;
-
-
memset(pdev,0,sizeof(struct cam_dev));
-
-
pdev->width = width;
-
pdev->height = height;
-
-
-
if(format == CAM_TYPE_RGB_16BPP)
-
pdev->buf_size = pdev->width * pdev->height * 2;
-
else if(format == CAM_TYPE_YUV_420)
-
pdev->buf_size = pdev->width * pdev->height * 4/3;
-
else
-
{
-
fprintf(stderr,"error camera format %d\n",format);
-
return -1;
-
}
-
-
pdev->fd = open(dev_name,O_RDWR);
-
if(pdev->fd == -1)
-
{
-
fprintf(stderr,"open %s failure\n",dev_name);
-
return -2;
-
}
-
-
if((ret=ioctl(pdev->fd, VIDIOC_QUERYCAP, &cap))!=0) {
-
fprintf(stderr,"VIDIOC_QUERYCAP error, %s\n",strerror(ret));
-
goto SET_ERROR;
-
}
-
-
printf("Driver:%s, Card:%s, cap=0x%x\n",cap.driver,cap.card,cap.capabilities);
-
-
memset(&input, 0, sizeof(input));
-
input.index= index;
-
if(ioctl(pdev->fd, VIDIOC_ENUMINPUT, &input)<0)
-
goto SET_ERROR;
-
-
printf("input[%d] name:%s\n",input.index,input.name);
-
-
index=0;
-
if((ret = ioctl(pdev->fd, VIDIOC_S_INPUT, &index))<0)
-
goto SET_ERROR;
-
-
if((ret = ioctl(pdev->fd, VIDIOC_S_OUTPUT, &index))<0)
-
goto SET_ERROR;
-
-
if((ret = ioctl(pdev->fd, VIDIOC_G_FBUF, &fb))<0)
-
goto SET_ERROR;
-
-
printf("g_fbuf:capabilities=0x%x,flags=0x%x,width=%d,height=%d\npixelformat=0x%x,bytesperline=%d,colorspace=%d,base=0x%x\n",
-
fb.capability,fb.flags,fb.fmt.width,fb.fmt.height,fb.fmt.pixelformat,
-
fb.fmt.bytesperline,fb.fmt.colorspace,fb.base);
-
-
//set capture format to yuv
-
fb.capability = cap.capabilities;
-
fb.fmt.width =width;
-
fb.fmt.height = height;
-
if(format == CAM_TYPE_RGB_16BPP)
-
fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
-
else if(format == CAM_TYPE_YUV_420)
-
fb.fmt.pixelformat = V4L2_PIX_FMT_YUV420;
-
-
if((ret = ioctl(pdev->fd, VIDIOC_S_FBUF, &fb))<0)
-
goto SET_ERROR;
-
-
on = 1;
-
if((ret = ioctl(pdev->fd, VIDIOC_OVERLAY, &on))<0)
-
goto SET_ERROR;
-
-
if(mode == CAM_DATA_READ)
-
pdev->buf = malloc(pdev->buf_size);
-
else
-
{
-
fprintf(stderr,"error data mode %d\n",mode);
-
goto SET_ERROR;
-
}
-
-
pdev->data_mode = mode;
-
-
return 0;
-
-
SET_ERROR:
-
close(pdev->fd);
-
return ret;
-
}
-
-
int cam_dev_close(struct cam_dev * pdev)
-
{
-
int on=0;
-
-
if(ioctl(pdev->fd, VIDIOC_OVERLAY, &on)<0)
-
{
-
perror("ioctl");
-
}
-
-
if(pdev->buf)
-
free(pdev->buf);
-
-
close(pdev->fd);
-
-
return 0;
-
}
-
-
-
void show_camera_on_fb(struct fb_dev* fdev,struct cam_dev * cdev)
-
{
-
unsigned int frames = 0;
-
struct timeval tv1;
-
struct timeval start_tv, end_tv;
-
struct timezone tz;
-
int len;
-
-
gettimeofday(&start_tv, &tz);
-
-
while(1)
-
{
-
-
if((len = read(cdev->fd,cdev->buf,cdev->buf_size)) <=0)
-
{
-
printf("read error\n");
-
continue;
-
}
-
-
if(len>fdev->buf_size)
-
len = fdev->buf_size;
-
-
memcpy(fdev->buf,cdev->buf,len);
-
-
frames++;
-
if(frames==30){
-
gettimeofday(&end_tv, &tz);
-
print_fps(&start_tv, &end_tv);
-
gettimeofday(&start_tv, &tz);
-
frames = 0;
-
}
-
-
-
}
-
}
-
-
struct fb_dev fbdev;
-
struct cam_dev camdev;
-
-
void exit_func(int sig)
-
{
-
printf("signal %d\n",sig);
-
-
cam_dev_close(&camdev);
-
fb_dev_close(&fbdev);
-
-
exit(0);
-
}
-
-
-
int main(int argc,char * argv[])
-
{
-
char cam_name[64] = CAM_DEV_NAME;
-
-
signal(SIGTERM,exit_func);
-
signal(SIGINT,exit_func);
-
-
if(argc > 1)
-
strncpy(cam_name,argv[1],sizeof(cam_name)-1);
-
-
if(fb_dev_open(&fbdev,16,NULL)!=0)
-
{
-
return -1;
-
}
-
-
if(cam_dev_open(&camdev,fbdev.width,fbdev.height,CAM_TYPE_RGB_16BPP,CAM_DATA_READ,cam_name)!=0)
-
{
-
fb_dev_close(&fbdev);
-
return -2;
-
}
-
-
show_camera_on_fb(&fbdev,&camdev);
-
-
cam_dev_close(&camdev);
-
fb_dev_close(&fbdev);
-
-
return 0;
-
}
测试结果在s3c6410上用cam测试成功
阅读(3900) | 评论(5) | 转发(4) |