|
- /*
- *for a10 one video device ov7670 bmp
- *by jiangdou 2014-0701
- *
- *
- *
- *
- */
- #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 <sys/types.h>
- #include <linux/videodev2.h>
- #include <time.h>
- #define CLEAR(x) memset (&(x), 0, sizeof (x))
- typedef unsigned long DWORD;
- typedef int BOOL;
- typedef unsigned char BYTE;
- typedef unsigned short WORD;
- typedef float FLOAT;
- typedef int INT;
- typedef unsigned int UINT;
- typedef unsigned int *PUINT;
- struct buffer {
- void *start;
- size_t length;
- };
- static char *dev_name = "/dev/video0";//摄像头设备名
- static int fd = -1;
- struct buffer *buffers = NULL;
- static unsigned int n_buffers = 0;
- FILE *file_fd;
- FILE *hf;
- static unsigned long file_length;
- static unsigned char *file_name; //全局变量和静态全局变量的区别:都是静态存储方式,但全局变量可为多个源文件共同使用,静态全局变量只在本文件中使用
- //////////////////////////////////////////////////////
- //获取一帧数据
- //////////////////////////////////////////////////////
- BYTE clip255(long v)
- {
- if(v < 0) v=0;
- else if( v > 255) v=255;
- return (BYTE)v;
- }
- void yuv2bmp(BYTE *YUV2buff,BYTE *RGBbuff,DWORD dwSize)
- {
- DWORD count;
- for( count = 0; count < dwSize; count += 4 )
- {
- //Y0 U0 Y1 V0
- BYTE Y0 = *YUV2buff;
- BYTE U = *(++YUV2buff);
- BYTE Y1 = *(++YUV2buff);
- BYTE V = *(++YUV2buff);
- ++YUV2buff;
- long Y,C,D,E;
- BYTE R,G,B;
- Y = Y0;
- C = Y - 16;
- D = U - 128;
- E = V - 128;
- R = clip255(( 298 * C + 409 * E + 128) >> 8);
- G = clip255(( 298 * C - 100 * D - 208 * E + 128) >> 8);
- B = clip255(( 298 * C + 516 * D + 128) >> 8);
- *(RGBbuff) = B;
- *(++RGBbuff) = G;
- *(++RGBbuff) = R;
- Y = Y1;
- C = Y-16;
- D = U-128;
- E = V-128;
- R = clip255(( 298 * C + 409 * E + 128) >> 8);
- G = clip255(( 298 * C - 100 * D - 208 * E + 128) >> 8);
- B = clip255(( 298 * C + 516 * D + 128) >> 8);
- *(++RGBbuff) = B;
- *(++RGBbuff) = G;
- *(++RGBbuff) = R;
- ++RGBbuff;
- }
- }
- //unsigned char a[153600];//240x320
- //unsigned char rgbout[230400]="";
- //unsigned char rgbout2[230400]="";
- unsigned char a[614400];
- unsigned char rgbout[921600]="";
- unsigned char rgbout2[921600]="";
- static int read_frame (void) //函数声明为static,只能在本文件中调用
- {
- struct v4l2_buffer buf;
- unsigned int i;
- CLEAR (buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- ioctl (fd, VIDIOC_DQBUF, &buf); //出列采集的帧缓冲
- assert (buf.index < n_buffers);
- printf ("buf.index dq is %d,\n",buf.index);
- fwrite(buffers[buf.index].start, buffers[buf.index].length, 1, file_fd); //将其写入文件中
- ioctl (fd, VIDIOC_QBUF, &buf); //再将其入列
- return 1;
- }
- int v4l2_get_fmt()
- {
- struct v4l2_format my_fmt;
- }
- int main (int argc,char ** argv)
- {
- struct v4l2_capability cap;
- struct v4l2_format fmt,get_fmt;
- unsigned int i;
- enum v4l2_buf_type type;
- unsigned int format;
- file_fd = fopen("test-mmap.txt", "w");//图片文件名
- fd = open (dev_name, O_RDWR | O_NONBLOCK, 0);
- //ioctl (fd, VIDIOC_QUERYCAP, &cap);//获取摄像头参数
- //////////////////////////////////////////////////////////////////////////////
- ////////////////////////开启设置device,but I die this!///////////////////////
- struct v4l2_input inp;
- inp.index = 0;
- if (inp.type == V4L2_INPUT_TYPE_CAMERA)
- printf("enuminput type is V4L2_INPUT_TYPE_CAMERA!\n");
-
- if (-1 == ioctl (fd, VIDIOC_S_INPUT, &inp)) //设置输入index
- printf("VIDIOC_S_INPUT error!\n");
-
- /////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////
-
- CLEAR (fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = 640;//640
- fmt.fmt.pix.height = 480;//480
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//V4L2_PIX_FMT_RGB32;//YUYV
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- int ff = ioctl (fd, VIDIOC_S_FMT, &fmt); //设置图像格式
- if(ff<0){
- printf("failture VIDIOC_S_FMT\n");
- return 0;
- }
- printf("fmt.fmt.pix.width %d \n ",fmt.fmt.pix.width);
- printf("fmt.fmt.pix.bytesperline %d \n",fmt.fmt.pix.bytesperline);
- CLEAR(get_fmt);
- get_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if(-1 == ioctl(fd,VIDIOC_G_FMT,&get_fmt))
- printf("failture VIDIOC_S_FMT\n");
- format = fmt.fmt.pix.pixelformat;
- char code[5];
- int j = 0;
- for(j = 0; j < 4; j++)
- code[j] = (format & (0xff << j*8)) >> j*8;
- code[4] = 0;
- printf("format(human readble):%s\n",code);
- file_length = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; //计算图片大小
- printf("file_length is %d %ld",file_length,file_length);
- struct v4l2_requestbuffers req;
- CLEAR (req);
- req.count = 4;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- ioctl (fd, VIDIOC_REQBUFS, &req); //申请缓冲,count是申请的数量
- if (req.count < 2)
- printf("Insufficient buffer memory\n");
- buffers = calloc (req.count, sizeof (*buffers));//内存中建立对应空间
- for (n_buffers = 0; n_buffers < req.count; ++n_buffers) //这个for循环内部的buf,只在此循环内有效,循环结束就没有了;
- {
- struct v4l2_buffer buf; //驱动中的一帧-----------
- CLEAR (buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = n_buffers;
- printf("buf.length is %d",buf.length);
- if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf)) //映射用户空间
- printf ("VIDIOC_QUERYBUF error\n");
- buffers[n_buffers].length = buf.length;
- printf("buf.length %d\n\n",buf.length);
- printf("buf.length is displayed");
- buffers[n_buffers].start = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);//通过mmap建立映射关系
- if (MAP_FAILED == buffers[n_buffers].start)
- printf ("mmap failed\n");
- printf("buf.length is %d;",buf.length);
- if (-1 == ioctl (fd, VIDIOC_QBUF, &buf))//申请到的缓冲进入列队
- printf ("VIDIOC_QBUF failed\n");
- printf("buf.length is %d\n.",buf.length);
- }
-
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == ioctl (fd, VIDIOC_STREAMON, &type)) //开始捕捉图像数据
- printf ("VIDIOC_STREAMON failed\n");
- else printf("VIDIOC_STREAMON succeed\n");
-
- for (;;) //这一段涉及到异步IO
- {
- fd_set fds;
- struct timeval tv;
- int r;
- FD_ZERO (&fds);//将指定的文件描述符集清空
- FD_SET (fd, &fds);//在文件描述符集合中增加一个新的文件描述符
- tv.tv_sec = 2;
- tv.tv_usec = 0;
- r = select (fd + 1, &fds, NULL, NULL, &tv);//判断是否可读(即摄像头是否准备好),tv是定时
- if (-1 == r) {
- if (EINTR == errno)
- continue;
- printf ("select err\n");
- }
- if (0 == r) {
- fprintf (stderr, "select timeout\n");
- exit (EXIT_FAILURE);
- }
- if (read_frame ())//如果可读,执行read_frame ()函数,并跳出循环
- break;
- }
- unmap:
- for (i = 0; i < n_buffers; ++i)
- if (-1 == munmap (buffers[i].start, buffers[i].length))
- printf ("munmap error");
- close (fd);
- fclose (file_fd);
- printf("end-begin");
- FILE *p;
- p=fopen("test-mmap.txt","r");
- fread(a,1,614400,p);
- fclose(p);
- unsigned char *yuv=a;
- printf("1\n");
- unsigned char *q=rgbout;
- yuv2bmp(yuv,rgbout,614400);//153600
- printf("2\n");
- int j0,k;
-
- for ( j0 =0 ; j0<480; j0++)
- {
- for ( k=0; k <640*3 ;k++)
- {
- rgbout2[k+640*j0*3] = rgbout[640*(480-j0-1)*3+k] ;
- }
- }
- // HANDLE hf = CreateFile(
- // "F://Frame.bmp", GENERIC_WRITE, FILE_SHARE_READ, NULL,
- // CREATE_ALWAYS, NULL, NULL );
- hf=fopen("frame.bmp","w");
- if( hf == -1 )
- return 0;
- //if( hf == INVALID_HANDLE_VALUE )return 0;
- typedef struct tagBITMAPFILEHEADER {
- WORD bfType;
- DWORD bfSize;
- WORD bfReserved1;
- WORD bfReserved2;
- DWORD bfOffBits;
- } BITMAPFILEHEADER;
- typedef struct tagBITMAPINFOHEADER{
- DWORD biSize;
- long biWidth;
- long biHeight;
- WORD biPlanes;
- WORD biBitCount;
- DWORD biCompression;
- DWORD biSizeImage;
- long biXPelsPerMeter;
- long biYPelsPerMeter;
- DWORD biClrUsed;
- DWORD biClrImportant;
- } BITMAPINFOHEADER;
- // 写文件头
- BITMAPFILEHEADER bfh;
- // printf("bfh1=%d\n",sizeof(WORD)+sizeof(DWORD)+sizeof(WORD)+sizeof(WORD)+sizeof(DWORD));
- memset( &bfh, 0,sizeof(BITMAPFILEHEADER) );
- bfh.bfType = 'MB';
- bfh.bfSize = 14 + 921600 + sizeof( BITMAPINFOHEADER );
- bfh.bfOffBits = 14+ sizeof( BITMAPFILEHEADER );
- // DWORD dwWritten = 0;
- // WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
- printf("bfh=%d\n",sizeof(BITMAPFILEHEADER));
- printf("word=%d\n",sizeof(WORD));
- printf("Dword=%d\n",sizeof(DWORD));
- fwrite(&bfh.bfType,sizeof(WORD),1,hf);
- fwrite(&bfh.bfSize,sizeof(DWORD),1,hf);
- fwrite(&bfh.bfReserved1,sizeof(WORD),1,hf);
- fwrite(&bfh.bfReserved2,sizeof(WORD),1,hf);
- fwrite(&bfh.bfOffBits,sizeof(DWORD),1,hf);
- // 写位图格式
- BITMAPINFOHEADER bih;
- memset( &bih, 0, sizeof( bih ) );
- bih.biSize = sizeof( bih );
- bih.biWidth =640;
- bih.biHeight = 480;
- bih.biPlanes = 1;
- bih.biBitCount = 24;
- fwrite(&bih,sizeof(bih),1,hf);
- // printf("bih=%d\n",sizeof(bih));
- //WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
- // 写位图数据
- //WriteFile( hf, rgbout2, 921600, &dwWritten, NULL );
- // CloseHandle( hf );
- fwrite(rgbout2,921600,1,hf);//230400
- fclose(hf);
- //exit (EXIT_SUCCESS);
- return 0;
- }
复制代码 |
|