您的位置:首页 > 编程语言

S3C2440通过v4l2采集在lcd上显示与多帧编程

2012-12-27 10:40 120 查看
#include <sys/time.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
//#include <jpeglib.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/videodev.h>
#include <linux/fb.h>

 

#define COLS 320
#define ROWS 240
#define V4L2_DEV_NODE "/dev/video13"
#define FB_DEV_NODE "/dev/fb0"

#define CLEAR(x) memset(&(x),0,sizeof(x))

typedef struct v4l2_format   V_FORMAT;
typedef struct fb_var_screeninfo F_VINFO;

struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;
char * fb_base_addr = NULL;

static void show_rgb565_img(void *scr, __u16 *data_buf)
{ 

	__u16 x, y;
	__u16 *fb_buf = (__u16 *)scr;
	fb_buf += (320);

	for (y = 0; y < ROWS; y++) {
		for (x = 0; x < COLS; x++) { 
			fb_buf[x] = *data_buf++ ;
		}
		fb_buf += 320;
	}
}

int main(void)
{

	int v4l2_fd = -1;
	int fb_fd = -1;
	int n=0;
	__u8 *fb_buf;
	__u8 *buf;
	__u32 screensize;
 
 	//unsigned int width = 0;
	//unsigned int height = 0;
	//unsigned int bpp = 0;

	V_FORMAT fmt;
	enum v4l2_buf_type type;
	type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	printf("Start Main \n");
	printf("Before openning video \n");
 
	v4l2_fd = open(V4L2_DEV_NODE, O_RDWR | O_NONBLOCK, 0);
 
	if (v4l2_fd < 0) {
		printf(" open video ERR\n");
		return 0;
	}
	printf("Before openning FB \n");
 
	fb_fd = open(FB_DEV_NODE, O_RDWR);
	if (fb_fd < 0) {
		printf("error open fb_fd\n");
		exit(1);
	}

	/* Get fixed screen information */
	if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_fix)) {
		printf("Error reading fb fixed information.\n");
		exit(1);
	}

	/* Get variable screen information 	*/
	if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &fb_var)) {
		printf("Error reading fb variable information.\n");
		exit(1);
	}
 
	screensize = fb_var.xres * fb_var.yres * fb_var.bits_per_pixel / 8;
	//screensize = 480 * 272 * 16 / 8;
 
	fb_buf = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);

	if ((int)fb_buf == -1) {
		printf("Error: failed to map framebuffer device to memory.\n");
		close(fb_fd);
		return -1;
	}

	CLEAR (fmt);
	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	fmt.fmt.pix.width = 320;
	fmt.fmt.pix.height = 240;
	//fmt.fmt.pix.depth = 16;
	fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
	//printf("VIDIOC_S_FMT is %x\n",VIDIOC_S_FMT);

	if ((ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt)) < 0) {
		printf("Error: failed to set video format.\n");
		return 0;
	}

	buf = malloc(320 * 240 * 3); 
	//printf("VIDIOC_STREAMON is %x\n",VIDIOC_STREAMON);
 
	if ((ioctl(v4l2_fd, VIDIOC_STREAMON, &type)) < 0) {
		printf("error ioctl streamon\n");
		return 0;
	}

	printf("start to get pic %d\n",(int)fmt.fmt.pix.sizeimage);
	while(1) {
		n=read(v4l2_fd, buf, 320*240*2);
		printf("display %d\n",n);
		show_rgb565_img(fb_buf,buf);
	}
}


多帧编程

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
 
#include <getopt.h>            

#include <fcntl.h>             
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
 
#include <asm/types.h>         
#include <linux/videodev2.h>
 
#define CLEAR(x) memset (&(x), 0, sizeof (x))
 
struct buffer {
         void *                  start;
         size_t                  length;
 };
 
static char *           dev_name        = "/dev/video12";
static int              fd              = -1;
struct buffer *         buffers         = NULL;
 
FILE *file_fd;
static unsigned long file_length;
//static unsigned char *file_name;
 
int main (int argc,char ** argv)
 {
struct v4l2_capability cap; 
struct v4l2_format fmt;
	char fourcc[5] = {0, 0, 0, 0, 0};
 
file_fd = fopen("test.yuv", "wb");
 
fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
 
    int ff = ioctl (fd, VIDIOC_QUERYCAP, &cap);

    if(ff < 0)
        printf("failture VIDIOC_QUERYCAP\n");
		
    printf("\n****Capability informations****\n");  
    printf("driver:   %s\n", cap.driver);  
      
    if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)  
       printf("Capture capability is supported\n");  
  
    if (cap.capabilities & V4L2_CAP_STREAMING)   
        printf("Streaming capability is supported\n");
 
CLEAR (fmt);
fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width       = 720; 
fmt.fmt.pix.height      = 288;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;  //视频数据存储类型//V4L2_PIX_FMT_JPEG;//V4L2_PIX_FMT_YVU420;//V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;

    ff = ioctl (fd, VIDIOC_S_FMT, &fmt);       //设置图像格式
    if (ff < 0)
        printf("failture VIDIOC_S_FMT\n");
		
	memmove(fourcc, &fmt.fmt.pix.pixelformat, 4);
	
	printf("Goint to capture frames %d x %d format: %4s framesize: %d\n",
				 fmt.fmt.pix.width,
				 fmt.fmt.pix.height,
				 fourcc,
				 fmt.fmt.pix.sizeimage);
 
file_length = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;  //计算图片大小
 
buffers = calloc (1, sizeof (*buffers));
	if (!buffers) {
		perror("Can't allocate buffer!\n");
		return 1;
	}
 
buffers[0].length = file_length;
buffers[0].start = malloc (file_length);
 
for (;;)    //这一段涉及到异步IO
{
    fd_set fds;
    struct timeval tv; //timeval结构的指针,用于决定select等待I/o的最长时间。如果为空将一直等待
    int r;
 
    FD_ZERO (&fds);  //将指定的文件描述符集清空
    FD_SET (fd, &fds);    //在文件描述符集合中增加一个新的文件描述符
 
   /* Timeout. */
    tv.tv_sec = 2;
    tv.tv_usec = 0;
	
	/*readset writeset exceptset指定我们要让内核测试读、写和异常条件的描述字。
	如果对某一个的条件不感兴趣,就可以把它设为NULL。
	如果三个指针都为NULL,我们就有了一个比sleep()函数更为精确的定时器
	(sleep()以秒为最小单位,这个以微妙为单位)。
	int select (int maxfdp1, fd_set *readset, fd_set *writeset, 
					fd_set *exceptset,
                	const struct timeval * timeout); */
	
   r = select (fd + 1, &fds, NULL, NULL, &tv); //判断是否可读(即摄像头是否准备好),tv是定时
 
   if (-1 == r) {
		if (EINTR == errno)
			continue;
			printf ("select");
    }
 /*
   if (0 == r) {
		fprintf (stderr, "select timeout\n");
		exit (EXIT_FAILURE);
    }
 */
   if (read (fd, buffers[0].start, buffers[0].length))//如果可读,执行read()函数,并跳出循环
    break;
}
 
	fwrite(buffers[0].start, buffers[0].length, 1, file_fd);
 
	free (buffers[0].start);
	close (fd);
	fclose (file_fd);
	exit (EXIT_SUCCESS);
	return 0;
 }

不管是ov511还是zc301的摄像头,它们采集的方式都是相同的,只不过采集到的数据有所差异,ov511的就是rgb的位流,而zc301是jpeg编码的位流。mouse_capture是根据servfox改编的一个专门从zc301摄像头获取一张jpeg图片,用来测试摄像头是否加载成功的小程序。这样就可以不用cat /dev/video0>1.jpg来测试摄像头是否正常。cat命令一运行,就源源不断地采集jpeg流。但是采到的图片只能显示第一个jpeg头和jpeg尾之间的数据。mouse_capture仅仅获得一张完整的jpeg。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: