zoukankan      html  css  js  c++  java
  • linux -- camera shot 拍照功能

    1. #include <stdio.h>  
    2. #include <string.h>  
    3. #include <errno.h>  
    4. #include <stdlib.h>  
    5. #include <sys/types.h>  
    6. #include <sys/stat.h>  
    7. #include <fcntl.h>  
    8. #include <time.h>  
    9. #include <sys/mman.h>  
    10. #include <assert.h>  
    11. #include <linux/videodev2.h>  
    12. #include <linux/fb.h>  
    13. #include <pthread.h>  
    14.   
    15. //照相机延时等待  
    16. #define TimeOut 5   
    17. //拍照 个数  
    18. #define CapNum 10  
    19. //设置照片宽度 高度  
    20. #define CapWidth 320  
    21. #define CapHeight 240  
    22. //申请Buf个数  
    23. #define ReqButNum 4  
    24. //使用前置或者后置Camera 前置设0,后置设1  
    25. #define IsRearCamera 0  
    26. //设置帧率  
    27. #define  FPS 10  
    28. //设置格式  
    29. #define PIXELFMT V4L2_PIX_FMT_YUYV  
    30.   
    31. #define CapDelay 100*1000  
    32.   
    33.   
    34. #define CLEAR(x)    memset(&(x), 0, sizeof(x))  
    35.   
    36. typedef unsigned char BYTE;  
    37. typedef unsigned short WORD;  
    38. typedef unsigned int DWORD;  
    39. typedef long LONG;  
    40.   
    41. typedef struct  
    42. {  
    43.     void *start;  
    44.     int length;  
    45. }BUFTYPE;  
    46. struct tsp_event {  
    47.     struct timeval time;  
    48.     unsigned short type;  
    49.     unsigned short code;  
    50.     unsigned int value;  
    51. };  
    52. typedef struct tagBITMAPFILEHEADER {  
    53.   WORD  bfType;  
    54.   DWORD bfSize;  
    55.   WORD  bfReserved1;  
    56.   WORD  bfReserved2;  
    57.   DWORD bfOffBits;  
    58. }__attribute__((packed)) BITMAPFILEHEADER, *PBITMAPFILEHEADER;  
    59.   
    60.   
    61. typedef struct tagBITMAPINFOHEADER {  
    62.   DWORD biSize;  
    63.   LONG  biWidth;  
    64.   LONG  biHeight;  
    65.   WORD  biPlanes;  
    66.   WORD  biBitCount;  
    67.   DWORD biCompression;  
    68.   DWORD biSizeImage;  
    69.   LONG  biXPelsPerMeter;  
    70.   LONG  biYPelsPerMeter;  
    71.   DWORD biClrUsed;  
    72.   DWORD biClrImportant;  
    73. }__attribute__((packed)) BITMAPINFOHEADER, *PBITMAPINFOHEADER;  
    74.   
    75.   
    76.   
    77. static BITMAPFILEHEADER file_head;  
    78. static BITMAPINFOHEADER info_head;  
    79.   
    80. typedef struct tagRGBQUAD {  
    81.   BYTE rgbBlue;  
    82.   BYTE rgbGreen;  
    83.   BYTE rgbRed;  
    84.   BYTE rgbReserved;  
    85. }__attribute__((packed)) RGBQUAD;  
    86.   
    87.   
    88. BUFTYPE *user_buf;  
    89. static int n_buffer = 0;  
    90.   
    91.   
    92. static struct fb_var_screeninfo vinfo;  
    93. static struct fb_fix_screeninfo finfo;  
    94. static int lcd_buf_size;  
    95. static char *fb_buf = NULL;  
    96. static int tsp_fd;  
    97. static pthread_t capture_tid;   
    98.   
    99. int display_x = 0;  
    100. int display_y = 0;  
    101.   
    102. int save_image()  
    103. {  
    104.     FILE *fp;  
    105.     static int num = 0;  
    106.     char picture_name[40]={''};  
    107.     char *addr = (char *)fb_buf;  
    108.     int length = CapWidth * CapHeight * vinfo.bits_per_pixel / 8;  
    109.     int fd;  
    110.     int data_size;  
    111.     int i,j,k;  
    112.     char *tmp_buf;  
    113.       
    114.     tmp_buf = (char *)malloc(length);  
    115.     if(tmp_buf == NULL)  
    116.     {  
    117.       
    118.         printf("tmp_buf alloc fail ");  
    119.         exit(EXIT_FAILURE);  
    120.     }  
    121.   
    122.     if(access("/udisk/camtest",0)!=0)  
    123.     {  
    124.         mkdir("/udisk/camtest", 0777);  
    125.     }  
    126.       
    127.     sprintf(picture_name,"/udisk/camtest/picture%d.bmp",num ++);  
    128.     printf("write image to sdcard:name:%s ",picture_name);  
    129.   
    130.   
    131.     data_size = length;  
    132.   
    133.     file_head.bfType = 0x4d42;  
    134.     file_head.bfSize = sizeof(file_head) + sizeof(info_head) + data_size;  
    135.     file_head.bfReserved1 = file_head.bfReserved2 = 0;  
    136.     file_head.bfOffBits = sizeof(file_head) + sizeof(info_head);  
    137.           
    138.     info_head.biSize = sizeof(info_head);  
    139.     info_head.biWidth = CapWidth;  
    140.     info_head.biHeight = CapHeight;  
    141.     info_head.biPlanes = 1;  
    142.     info_head.biBitCount = 32;  
    143.     info_head.biCompression = 0;  
    144.     info_head.biSizeImage = 0;  
    145.     info_head.biXPelsPerMeter = 0;  
    146.     info_head.biYPelsPerMeter = 0;  
    147.     info_head.biClrUsed = 0;  
    148.     info_head.biClrImportant = 0;  
    149.   
    150.   
    151.     fd = open(picture_name, O_RDWR | O_CREAT, 0644);  
    152.     if(fd < 0)  
    153.     {  
    154.         perror("create image error ");  
    155.         close (fd);  
    156.         exit(EXIT_FAILURE);  
    157.     }  
    158.   
    159.     write(fd, &file_head, sizeof(file_head));  
    160.       
    161.     write(fd, &info_head, sizeof(info_head));  
    162.   
    163.     int bmpLineLenth = CapWidth * vinfo.bits_per_pixel / 8;   
    164.     for(i = 0; i < length; i++)  
    165.     {  
    166.         tmp_buf[i] = fb_buf[(CapHeight - i/bmpLineLenth - 1) * finfo.line_length + i%bmpLineLenth];  
    167.     }  
    168.     for(i = 0; i < length; i++)  
    169.     {  
    170.         fb_buf[(i/bmpLineLenth) * finfo.line_length + i%bmpLineLenth + bmpLineLenth] = tmp_buf[i] ;  
    171.     }  
    172.       
    173.     write(fd, tmp_buf, length);  
    174.       
    175.     usleep(500);  
    176.     close(fd);  
    177.     return 0;  
    178. }  
    179. static void *capture_thread(void *pVoid)  
    180. {  
    181.     int ret;  
    182.     int key_change = 0;  
    183.     struct tsp_event tsp_value;  
    184. #define BTN_TOUCH       0x14a  
    185.     while(1)  
    186.     {  
    187.         printf("capture_thread ");  
    188.         ret = read(tsp_fd, &tsp_value, sizeof(struct tsp_event)); /* 如果无数据则休眠 */  
    189.           
    190.         if (ret < 0)  
    191.         {  
    192.         printf("fail to read ");  
    193.         return;  
    194.         }  
    195.         //如果触摸释放掉,则开始保存图片  
    196.         if((tsp_value.code == BTN_TOUCH) && (tsp_value.value == 0))  
    197.         save_image();  
    198.         printf("code:%04d,value:%04d ",tsp_value.code, tsp_value.value);  
    199.     }  
    200.   
    201. }  
    202. //打开摄像头设备  
    203. int open_camer_device()  
    204. {  
    205.     int fd;  
    206.   
    207. //非阻塞方式打开,如果打开错误,会立即返回  
    208.     if((fd = open("/dev/video0",O_RDWR | O_NONBLOCK)) < 0)  
    209.     {  
    210.         perror("Fail to open");  
    211.         exit(EXIT_FAILURE);  
    212.     }   
    213.   
    214.     printf("open cam success %d ",fd);  
    215.     return fd;  
    216. }  
    217.   
    218. //打开摄像头设备  
    219. int open_lcd_device()  
    220. {  
    221.     int fd;  
    222. //非阻塞方式打开,如果打开错误,会立即返回  
    223.     if((fd = open("/dev/fb0",O_RDWR | O_NONBLOCK)) < 0)  
    224.     {  
    225.         perror("Fail to open");  
    226.         exit(EXIT_FAILURE);  
    227.     }   
    228.     printf("open lcd success %d ",fd);  
    229.     return fd;  
    230. }  
    231.   
    232. //申请Camera Buf,并映射到用户空间,利用全局变量user_buf保存映射信息  
    233. int init_mmap(int lcd_fd, int cam_fd)  
    234. {  
    235.     int i = 0;  
    236.     int err;  
    237.     int ret;  
    238.     struct v4l2_control ctrl;  
    239.     struct v4l2_requestbuffers reqbuf;  
    240.   
    241.   
    242.     //mmap framebuffer      
    243.     fb_buf = (char *)mmap(  
    244.         NULL,  
    245.         lcd_buf_size,  
    246.         PROT_READ | PROT_WRITE,MAP_SHARED ,  
    247.         lcd_fd,   
    248.         0);      
    249.     if(NULL == fb_buf)  
    250.     {  
    251.         perror("Fail to mmap fb_buf");  
    252.         exit(EXIT_FAILURE);  
    253.     }  
    254.   
    255.     bzero(&reqbuf,sizeof(reqbuf));  
    256.     reqbuf.count = ReqButNum;  
    257.     reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    258.     reqbuf.memory = V4L2_MEMORY_MMAP;  
    259.     printf("start VIDIOC_REQBUFS ");  
    260.     //申请视频缓冲区(这个缓冲区位于内核空间,需要通过mmap映射)  
    261.     //这一步操作可能会修改reqbuf.count的值,修改为实际成功申请缓冲区个数  
    262.     if(-1 == ioctl(cam_fd,VIDIOC_REQBUFS,&reqbuf))  
    263.     {  
    264.         perror("Fail to ioctl 'VIDIOC_REQBUFS'");  
    265.         exit(EXIT_FAILURE);  
    266.     }  
    267.   
    268.     n_buffer = reqbuf.count;  
    269.   
    270.     user_buf = calloc(reqbuf.count,sizeof(*user_buf));  
    271.     if(user_buf == NULL){  
    272.         fprintf(stderr,"Out of memory ");  
    273.         exit(EXIT_FAILURE);  
    274.     }  
    275.   
    276.     //将内核缓冲区映射到用户进程空间  
    277.     for(i = 0; i < reqbuf.count; i ++)  
    278.     {  
    279.         struct v4l2_buffer buf;  
    280.           
    281.         bzero(&buf,sizeof(buf));  
    282.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    283.         buf.memory = V4L2_MEMORY_MMAP;  
    284.         buf.index = i;  
    285.         //查询申请到内核缓冲区的信息  
    286.         if(-1 == ioctl(cam_fd,VIDIOC_QUERYBUF,&buf))  
    287.         {  
    288.             perror("Fail to ioctl : VIDIOC_QUERYBUF");  
    289.             exit(EXIT_FAILURE);  
    290.         }  
    291.   
    292.         user_buf[i].length = buf.length;  
    293.         user_buf[i].start =   
    294.             mmap(  
    295.                     NULL,/*start anywhere*/  
    296.                     buf.length,  
    297.                     PROT_READ | PROT_WRITE,  
    298.                     MAP_SHARED,  
    299.                     cam_fd,buf.m.offset  
    300.                 );  
    301.           
    302.         if(MAP_FAILED == user_buf[i].start)  
    303.         {  
    304.             perror("Fail to mmap ");  
    305.             printf("%d ",i);  
    306.             exit(EXIT_FAILURE);  
    307.         }  
    308.     //  printf("start:08%lx ",user_buf[i].start);  
    309.     }     
    310.   
    311.     return 0;  
    312. }  
    313.   
    314.   
    315. //初始化视频设备  
    316. int init_device(int lcd_fd, int cam_fd)  
    317. {  
    318.     struct v4l2_fmtdesc fmt;  
    319.     struct v4l2_capability cap;  
    320.     struct v4l2_format stream_fmt;  
    321.     struct v4l2_input input;  
    322.     struct v4l2_control ctrl;  
    323.     struct v4l2_streamparm stream;  
    324.     int err;  
    325.     int ret;  
    326.   
    327.   
    328.   
    329.   
    330.     if(-1 == ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo))  
    331.     {  
    332.         perror("Fail to ioctl:FBIOGET_FSCREENINFO ");  
    333.         exit(EXIT_FAILURE);  
    334.     }  
    335.     if (-1==ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo))   
    336.     {  
    337.         perror("Fail to ioctl:FBIOGET_VSCREENINFO ");  
    338.         exit(EXIT_FAILURE);  
    339.     }  
    340.     lcd_buf_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;    
    341.     printf("vinfo.xres:%d, vinfo.yres:%d, vinfo.bits_per_pixel:%d, lcd_buf_size:%d, finfo.line_length:%d ",vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, lcd_buf_size, finfo.line_length);   
    342.   
    343.   
    344.   
    345.   
    346.   
    347.       
    348.     memset(&fmt,0,sizeof(fmt));  
    349.     fmt.index = 0;  
    350.     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    351.       
    352. //枚举视频设置支持的格式  
    353.     while((ret = ioctl(cam_fd,VIDIOC_ENUM_FMT,&fmt)) == 0)  
    354.     {  
    355.         fmt.index ++ ;  
    356.         printf("{pixelformat = %c%c%c%c},description = '%s' ",  
    357.                 fmt.pixelformat & 0xff,(fmt.pixelformat >> 8)&0xff,  
    358.                 (fmt.pixelformat >> 16) & 0xff,(fmt.pixelformat >> 24)&0xff,  
    359.                 fmt.description);  
    360.     }  
    361. //查询视频设备支持的功能  
    362.     ret = ioctl(cam_fd,VIDIOC_QUERYCAP,&cap);  
    363.     if(ret < 0){  
    364.         perror("FAIL to ioctl VIDIOC_QUERYCAP");  
    365.         exit(EXIT_FAILURE);  
    366.     }  
    367.   
    368.   
    369.     if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))  
    370.     {  
    371.         printf("The Current device is not a video capture device ");  
    372.         exit(EXIT_FAILURE);  
    373.       
    374.     }  
    375.   
    376.     if(!(cap.capabilities & V4L2_CAP_STREAMING))  
    377.     {  
    378.         printf("The Current device does not support streaming i/o ");  
    379.         exit(EXIT_FAILURE);  
    380.     }  
    381.   
    382.     CLEAR(stream_fmt);  
    383. //设置摄像头采集数据格式,如设置采集数据的  
    384. //长,宽,图像格式(JPEG,YUYV,MJPEG等格式)  
    385.     stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    386.     stream_fmt.fmt.pix.width = CapWidth;  
    387.     stream_fmt.fmt.pix.height = CapHeight;  
    388.     stream_fmt.fmt.pix.pixelformat = PIXELFMT;  
    389.     stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;  
    390.   
    391.     if(-1 == ioctl(cam_fd,VIDIOC_S_FMT,&stream_fmt))  
    392.     {  
    393.         printf("Can't set the fmt ");  
    394.         perror("Fail to ioctl ");  
    395.         exit(EXIT_FAILURE);  
    396.     }  
    397.     printf("VIDIOC_S_FMT successfully ");  
    398.   
    399.     init_mmap(lcd_fd, cam_fd);  
    400.       
    401. //通过S_PARM来设置FPS          
    402.     /* fimc_v4l2_s_parm */  
    403.   
    404.   CLEAR(stream);  
    405.     stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    406.     stream.parm.capture.capturemode = 0;  
    407.     stream.parm.capture.timeperframe.numerator = 1;  
    408.     stream.parm.capture.timeperframe.denominator = FPS;  
    409.   
    410.     err = ioctl(cam_fd, VIDIOC_S_PARM, &stream);  
    411.     if(err < 0)  
    412.     printf("FimcV4l2 start: error %d, VIDIOC_S_PARM", err);  
    413.   
    414.     return 0;  
    415. }  
    416.   
    417. int start_capturing(int cam_fd)  
    418. {  
    419.     unsigned int i;  
    420.     enum v4l2_buf_type type;  
    421.     //将申请的内核缓冲区放入一个队列中  
    422.     for(i = 0;i < n_buffer;i ++)  
    423.     {  
    424.         struct v4l2_buffer buf;  
    425.   
    426.   
    427.         bzero(&buf,sizeof(buf));  
    428.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    429.         buf.memory = V4L2_MEMORY_MMAP;  
    430.         buf.index = i;  
    431.           
    432.         if(-1 == ioctl(cam_fd,VIDIOC_QBUF,&buf))  
    433.         {  
    434.             perror("Fail to ioctl 'VIDIOC_QBUF'");  
    435.             exit(EXIT_FAILURE);  
    436.         }  
    437.     }  
    438.   
    439.   
    440.     //开始采集数据  
    441.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    442.     if(-1 == ioctl(cam_fd,VIDIOC_STREAMON,&type))  
    443.     {  
    444.         printf("i = %d. ",i);  
    445.         perror("Fail to ioctl 'VIDIOC_STREAMON'");  
    446.         exit(EXIT_FAILURE);  
    447.     }  
    448.     return 0;  
    449. }  
    450.   
    451. inline int clip(int value, int min, int max)   
    452. {      
    453.     return (value > max ? max : value < min ? min : value);   
    454. }  
    455. //将采集好的数据放到文件中  
    456. int process_image(void *addr,int length)  
    457. {  
    458.     unsigned char* in=(char*)addr;      
    459.     int width=CapWidth;      
    460.     int height=CapHeight;      
    461.     int istride=CapWidth *2;      
    462.     int x,y,j;     
    463.     int y0,u,y1,v,r,g,b;      
    464.     long location=0;   
    465.     //printf("vinfo.xoffset:%d,vinfo.yoffset:%d ",vinfo.xoffset,vinfo.yoffset);     
    466.     for ( y = 0; y < height; ++y)      
    467.     {          
    468.         for (j = 0, x=0; j < width * 2 ; j += 4,x +=2)         
    469.         {           
    470.             location = (x+display_x) * (vinfo.bits_per_pixel/8) + (y+display_y) * finfo.line_length;   
    471.             y0 = in[j];           
    472.             u = in[j + 1] - 128;  
    473.             y1 = in[j + 2];                    
    474.             v = in[j + 3] - 128;   
    475.             r = (298 * y0 + 409 * v + 128) >> 8;  
    476.             g = (298 * y0 - 100 * u - 208 * v + 128) >> 8;  
    477.             b = (298 * y0 + 516 * u + 128) >> 8;    
    478.             fb_buf[ location + 0] = clip(b, 0, 255);  
    479.             fb_buf[ location + 1] = clip(g, 0, 255);  
    480.             fb_buf[ location + 2] = clip(r, 0, 255);  
    481.             fb_buf[ location + 3] = 255;   
    482.             r = (298 * y1 + 409 * v + 128) >> 8;   
    483.             g = (298 * y1 - 100 * u - 208 * v + 128) >> 8;  
    484.             b = (298 * y1 + 516 * u + 128) >> 8;   
    485.             fb_buf[ location + 4] = clip(b, 0, 255);  
    486.             fb_buf[ location + 5] = clip(g, 0, 255);    
    487.             fb_buf[ location + 6] = clip(r, 0, 255);  
    488.             fb_buf[ location + 7] = 255;                
    489.         }        in +=istride;      }  
    490.       
    491. //  usleep(500);  
    492.     return 0;  
    493. }  
    494.   
    495.   
    496. int read_frame(int cam_fd)  
    497. {  
    498.     struct v4l2_buffer buf;  
    499.     unsigned int i;  
    500.       
    501.     bzero(&buf,sizeof(buf));  
    502.     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    503.     buf.memory = V4L2_MEMORY_MMAP;  
    504. //从Camera buf中把数据拿出来  
    505.     if(-1 == ioctl(cam_fd,VIDIOC_DQBUF,&buf))  
    506.     {  
    507.         perror("Fail to ioctl 'VIDIOC_DQBUF'");  
    508.         exit(EXIT_FAILURE);  
    509.     }  
    510.   
    511.     assert(buf.index < n_buffer);  
    512.   
    513.     process_image(user_buf[buf.index].start,user_buf[buf.index].length);  
    514. //把处理过的Buf 重新入队   
    515.     if(-1 == ioctl(cam_fd,VIDIOC_QBUF,&buf))  
    516.     {  
    517.         perror("Fail to ioctl 'VIDIOC_QBUF'");  
    518.         exit(EXIT_FAILURE);  
    519.     }  
    520.     return 1;  
    521. }  
    522.   
    523. //利用select 进行超时处理  
    524. int mainloop(int cam_fd)  
    525. {   
    526.     int count = 1;//CapNum;  
    527.     clock_t startTime, finishTime;  
    528.     double selectTime, frameTime;  
    529.       
    530.     while(count++  > 0)  
    531.     {  
    532.         for(;;)  
    533.         {  
    534.             fd_set fds;  
    535.             struct timeval tv;  
    536.             int r;  
    537.         //  startTime = clock();  
    538.   
    539.               
    540.             FD_ZERO(&fds);  
    541.             FD_SET(cam_fd,&fds);  
    542.   
    543.   
    544.             /*Timeout*/  
    545.             tv.tv_sec = TimeOut;  
    546.             tv.tv_usec = 0;  
    547.           
    548.             r = select(cam_fd + 1,&fds,NULL,NULL,&tv);  
    549.   
    550.   
    551.             if(-1 == r)  
    552.             {  
    553.                 if(EINTR == errno)  
    554.                     continue;  
    555.                   
    556.                 perror("Fail to select");  
    557.                 exit(EXIT_FAILURE);  
    558.             }  
    559.   
    560.   
    561.             if(0 == r)  
    562.             {  
    563.                 fprintf(stderr,"select Timeout ");  
    564.                 exit(EXIT_FAILURE);  
    565.             }  
    566.             startTime = clock();  
    567.             if(read_frame(cam_fd))  
    568.             {  
    569.                 finishTime = clock();  
    570.         //      printf("delta:%dms ", (finishTime - startTime)/1000);  
    571.                 break;  
    572.             }  
    573.         }  
    574.             usleep(CapDelay);  
    575.     }  
    576.   
    577.   
    578.     return 0;  
    579. }  
    580.   
    581.   
    582. void stop_capturing(int cam_fd)  
    583. {  
    584.     enum v4l2_buf_type type;  
    585.       
    586.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
    587.     if(-1 == ioctl(cam_fd,VIDIOC_STREAMOFF,&type))  
    588.     {  
    589.         perror("Fail to ioctl 'VIDIOC_STREAMOFF'");  
    590.         exit(EXIT_FAILURE);  
    591.     }  
    592.       
    593.     return;  
    594. }  
    595.   
    596.   
    597. void uninit_camer_device()  
    598. {  
    599.     unsigned int i;  
    600.   
    601.   
    602.     for(i = 0;i < n_buffer;i ++)  
    603.     {  
    604.         if(-1 == munmap(user_buf[i].start, user_buf[i].length))  
    605.         {  
    606.             exit(EXIT_FAILURE);  
    607.         }  
    608.     }  
    609.     if (-1 == munmap(fb_buf, lcd_buf_size))   
    610.     {            
    611.         perror(" Error: framebuffer device munmap() failed. ");            
    612.         exit (EXIT_FAILURE) ;         
    613.     }     
    614.     free(user_buf);  
    615.   
    616.   
    617.     return;  
    618. }  
    619.   
    620.   
    621. void close_camer_device(int lcd_fd, int cam_fd)  
    622. {  
    623.     if(-1 == close(lcd_fd))  
    624.     {  
    625.         perror("Fail to close lcd_fd");  
    626.         exit(EXIT_FAILURE);  
    627.     }  
    628.     if(-1 == close(cam_fd))  
    629.     {  
    630.         perror("Fail to close cam_fd");  
    631.         exit(EXIT_FAILURE);  
    632.     }  
    633.   
    634.     return;  
    635. }  
    636.   
    637.   
    638. int main()  
    639. {  
    640.    
    641.     int lcd_fd;  
    642.     int cam_fd;  
    643.     if((tsp_fd = open("/dev/event0", O_RDWR)) < 0)  
    644.     {  
    645.         printf("Fail to open");  
    646.         return -1;  
    647.     }   
    648.     lcd_fd = open_lcd_device();  
    649.     cam_fd = open_camer_device();  
    650.     pthread_create(&capture_tid,NULL,capture_thread,(void *)NULL);    
    651.     init_device(lcd_fd, cam_fd);  
    652. //  init_mmap(lcd_fd, cam_fd);  
    653.   
    654.     start_capturing(cam_fd);  
    655.   
    656.     mainloop(cam_fd);  
    657.       
    658.     stop_capturing(cam_fd);  
    659.   
    660.     uninit_camer_device();  
    661.   
    662.     close_camer_device(lcd_fd, cam_fd);  
    663.   
    664.   
    665.     return 0;  
  • 相关阅读:
    Excel中的Vlookup函数用法
    C# WinForm 在窗口菜单上显示已打开窗体的标题及其窗体的排列
    C#使用Windows注册表编辑
    World Creater
    AtService.exe 占用CPU资源较高的解决办法
    几段SQL Server语句和存储过程(转载)
    代码转换工具
    ReSharper 4.5 Feature Map
    DXperienceXaf9.2.6 Personal Computer SN
    RegexBuddy v3.1.1 破解版
  • 原文地址:https://www.cnblogs.com/zym0805/p/4736754.html
Copyright © 2011-2022 走看看