亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 4781 | 回復(fù): 3
打印 上一主題 下一主題

[驅(qū)動] 【已解決】通過V4L2采集的圖片怎么無法打開?請教什么原因 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2014-01-23 19:02 |只看該作者 |倒序瀏覽
本帖最后由 Huntsmen 于 2014-01-24 08:56 編輯

在網(wǎng)上找的一個V4L2編程的經(jīng)典例子,程序運行后,保存了2張jpg的圖片,但是保存圖片在windows下無法打開,想請教一下是什么原因?

PS:實驗環(huán)境是arm9開發(fā)板,usb的UVC攝像頭;利用開發(fā)板自帶的usb攝像頭測試app是能看到圖像的;
[ 8802.695000] usb 1-1.2: new full-speed USB device number 3 using s3c2410-ohci
[ 8802.825000] uvcvideo: Found UVC 1.00 device USB 2.0 CAMERA (1c4f:3002)
[ 8802.890000] input: USB 2.0 CAMERA as /devices/platform/s3c2410-ohci/usb1/1-1/1-1.2/1-1.2:1.0/input/input1
  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 <sys/mman.h>
  9. #include <assert.h>
  10. #include <linux/videodev2.h>


  11. typedef struct
  12. {
  13.         void *start;
  14.         int length;
  15. }BUFTYPE;

  16. BUFTYPE *user_buf;
  17. int n_buffer = 0;

  18. //打開攝像頭設(shè)備
  19. int open_camer_device()
  20. {
  21.         int fd;

  22.         if((fd = open("/dev/video0",O_RDWR | O_NONBLOCK)) < 0)
  23.         {
  24.                 perror("Fail to open");
  25.                 exit(EXIT_FAILURE);
  26.         }
  27.        
  28.         return fd;
  29. }

  30. int init_mmap(int fd)
  31. {
  32.         int i = 0;
  33.         struct v4l2_requestbuffers reqbuf;

  34.         bzero(&reqbuf,sizeof(reqbuf));
  35.         reqbuf.count = 4;
  36.         reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  37.         reqbuf.memory = V4L2_MEMORY_MMAP;
  38.        
  39.         //申請視頻緩沖區(qū)(這個緩沖區(qū)位于內(nèi)核空間,需要通過mmap映射)
  40.         //這一步操作可能會修改reqbuf.count的值,修改為實際成功申請緩沖區(qū)個數(shù)
  41.         if(-1 == ioctl(fd,VIDIOC_REQBUFS,&reqbuf))
  42.         {
  43.                 perror("Fail to ioctl 'VIDIOC_REQBUFS'");
  44.                 exit(EXIT_FAILURE);
  45.         }
  46.        
  47.         n_buffer = reqbuf.count;
  48.        
  49.         printf("n_buffer = %d\n",n_buffer);

  50.         user_buf = calloc(reqbuf.count,sizeof(*user_buf));
  51.         if(user_buf == NULL){
  52.                 fprintf(stderr,"Out of memory\n");
  53.                 exit(EXIT_FAILURE);
  54.         }

  55.         //將內(nèi)核緩沖區(qū)映射到用戶進程空間
  56.         for(i = 0; i < reqbuf.count; i ++)
  57.         {
  58.                 struct v4l2_buffer buf;
  59.                
  60.                 bzero(&buf,sizeof(buf));
  61.                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  62.                 buf.memory = V4L2_MEMORY_MMAP;
  63.                 buf.index = i;
  64.                 //查詢申請到內(nèi)核緩沖區(qū)的信息
  65.                 if(-1 == ioctl(fd,VIDIOC_QUERYBUF,&buf))
  66.                 {
  67.                         perror("Fail to ioctl : VIDIOC_QUERYBUF");
  68.                         exit(EXIT_FAILURE);
  69.                 }

  70.                 user_buf[i].length = buf.length;
  71.                 user_buf[i].start =
  72.                         mmap(
  73.                                         NULL,/*start anywhere*/
  74.                                         buf.length,
  75.                                         PROT_READ | PROT_WRITE,
  76.                                         MAP_SHARED,
  77.                                         fd,buf.m.offset
  78.                                 );
  79.                 if(MAP_FAILED == user_buf[i].start)
  80.                 {
  81.                         perror("Fail to mmap");
  82.                         exit(EXIT_FAILURE);
  83.                 }
  84.         }       

  85.         return 0;
  86. }

  87. //初始化視頻設(shè)備
  88. int init_camer_device(int fd)
  89. {
  90.         struct v4l2_fmtdesc fmt;
  91.         struct v4l2_capability cap;
  92.         struct v4l2_format stream_fmt;
  93.         int ret;
  94.        
  95.         //當(dāng)前視頻設(shè)備支持的視頻格式
  96.         memset(&fmt,0,sizeof(fmt));
  97.         fmt.index = 0;
  98.         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  99.         while((ret = ioctl(fd,VIDIOC_ENUM_FMT,&fmt)) == 0)
  100.         {
  101.                 fmt.index ++ ;

  102.                 printf("{pixelformat = %c%c%c%c},description = '%s'\n",
  103.                                 fmt.pixelformat & 0xff,(fmt.pixelformat >> 8)&0xff,
  104.                                 (fmt.pixelformat >> 16) & 0xff,(fmt.pixelformat >> 24)&0xff,
  105.                                 fmt.description);
  106.         }

  107.         //查詢視頻設(shè)備驅(qū)動的功能
  108.         ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);
  109.         if(ret < 0){
  110.                 perror("FAIL to ioctl VIDIOC_QUERYCAP");
  111.                 exit(EXIT_FAILURE);
  112.         }

  113.         //判斷是否是一個視頻捕捉設(shè)備
  114.         if(!(cap.capabilities & V4L2_BUF_TYPE_VIDEO_CAPTURE))
  115.         {
  116.                 printf("The Current device is not a video capture device\n");
  117.                 exit(EXIT_FAILURE);
  118.        
  119.         }

  120.         //判斷是否支持視頻流形式
  121.         if(!(cap.capabilities & V4L2_CAP_STREAMING))
  122.         {
  123.                 printf("The Current device does not support streaming i/o\n");
  124.                 exit(EXIT_FAILURE);
  125.         }

  126.         //設(shè)置攝像頭采集數(shù)據(jù)格式,如設(shè)置采集數(shù)據(jù)的
  127.         //長,寬,圖像格式(JPEG,YUYV,MJPEG等格式)
  128.         stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  129.         stream_fmt.fmt.pix.width = 640;
  130.         stream_fmt.fmt.pix.height = 480;
  131.         stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
  132.         stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

  133.         if(-1 == ioctl(fd,VIDIOC_S_FMT,&stream_fmt))
  134.         {
  135.                 perror("Fail to ioctl");
  136.                 exit(EXIT_FAILURE);
  137.         }

  138.        
  139.         //初始化視頻采集方式(mmap)
  140.         init_mmap(fd);

  141.         return 0;
  142. }

  143. int start_capturing(int fd)
  144. {
  145.         unsigned int i;
  146.         enum v4l2_buf_type type;

  147.         //將申請的內(nèi)核緩沖區(qū)放入一個隊列中
  148.         for(i = 0;i < n_buffer;i ++)
  149.         {
  150.                 struct v4l2_buffer buf;

  151.                 bzero(&buf,sizeof(buf));
  152.                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  153.                 buf.memory = V4L2_MEMORY_MMAP;
  154.                 buf.index = i;
  155.                
  156.                 if(-1 == ioctl(fd,VIDIOC_QBUF,&buf))
  157.                 {
  158.                         perror("Fail to ioctl 'VIDIOC_QBUF'");
  159.                         exit(EXIT_FAILURE);
  160.                 }
  161.         }

  162.         //開始采集數(shù)據(jù)
  163.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  164.         if(-1 == ioctl(fd,VIDIOC_STREAMON,&type))
  165.         {
  166.                 printf("i = %d.\n",i);
  167.                 perror("Fail to ioctl 'VIDIOC_STREAMON'");
  168.                 exit(EXIT_FAILURE);
  169.         }

  170.         return 0;
  171. }

  172. //將采集好的數(shù)據(jù)放到文件中
  173. int process_image(void *addr,int length)
  174. {
  175.         FILE *fp;
  176.         static int num = 0;
  177.         char picture_name[20];
  178.        
  179.         sprintf(picture_name,"picture_%d.jpg",num ++);
  180.        
  181.         if((fp = fopen(picture_name,"w")) == NULL)
  182.         {
  183.                 perror("Fail to fopen");
  184.                 exit(EXIT_FAILURE);
  185.         }

  186.         printf("len=%d\n",length);
  187.         fwrite(addr,length,1,fp);
  188.         usleep(500);

  189.         fclose(fp);

  190.         return 0;
  191. }

  192. int read_frame(int fd)
  193. {
  194.         struct v4l2_buffer buf;
  195.         unsigned int i;

  196.         bzero(&buf,sizeof(buf));
  197.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  198.         buf.memory = V4L2_MEMORY_MMAP;
  199.        
  200.         //從隊列中取緩沖區(qū)
  201.         if(-1 == ioctl(fd,VIDIOC_DQBUF,&buf))
  202.         {
  203.                 perror("Fail to ioctl 'VIDIOC_DQBUF'");
  204.                 exit(EXIT_FAILURE);
  205.         }

  206.         assert(buf.index < n_buffer);
  207.         //讀取進程空間的數(shù)據(jù)到一個文件中
  208.         process_image(user_buf[buf.index].start,user_buf[buf.index].length);
  209.        
  210.         if(-1 == ioctl(fd,VIDIOC_QBUF,&buf))
  211.         {
  212.                 perror("Fail to ioctl 'VIDIOC_QBUF'");
  213.                 exit(EXIT_FAILURE);
  214.         }

  215.         return 1;
  216. }

  217. int mainloop(int fd)
  218. {
  219.         int count = 2;

  220.         while(count -- > 0)
  221.         {
  222.                 for(;;)
  223.                 {
  224.                         fd_set fds;
  225.                         struct timeval tv;
  226.                         int r;

  227.                         FD_ZERO(&fds);
  228.                         FD_SET(fd,&fds);

  229.                         /*Timeout*/
  230.                         tv.tv_sec = 2;
  231.                         tv.tv_usec = 0;
  232.                
  233.                         r = select(fd + 1,&fds,NULL,NULL,&tv);

  234.                         if(-1 == r)
  235.                         {
  236.                                 if(EINTR == errno)
  237.                                         continue;
  238.                                
  239.                                 perror("Fail to select");
  240.                                 exit(EXIT_FAILURE);
  241.                         }

  242.                         if(0 == r)
  243.                         {
  244.                                 fprintf(stderr,"select Timeout\n");
  245.                                 exit(EXIT_FAILURE);
  246.                         }

  247.                         if(read_frame(fd))
  248.                                 break;
  249.                 }
  250.         }

  251.         return 0;
  252. }

  253. void stop_capturing(int fd)
  254. {
  255.         enum v4l2_buf_type type;
  256.        
  257.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  258.         if(-1 == ioctl(fd,VIDIOC_STREAMOFF,&type))
  259.         {
  260.                 perror("Fail to ioctl 'VIDIOC_STREAMOFF'");
  261.                 exit(EXIT_FAILURE);
  262.         }
  263.        
  264.         return;
  265. }

  266. void uninit_camer_device()
  267. {
  268.         unsigned int i;

  269.         for(i = 0;i < n_buffer;i ++)
  270.         {
  271.                 if(-1 == munmap(user_buf[i].start,user_buf[i].length))
  272.                 {
  273.                         exit(EXIT_FAILURE);
  274.                 }
  275.         }
  276.        
  277.         free(user_buf);

  278.         return;
  279. }

  280. void close_camer_device(int fd)
  281. {
  282.         if(-1 == close(fd))
  283.         {
  284.                 perror("Fail to close fd");
  285.                 exit(EXIT_FAILURE);
  286.         }

  287.         return;
  288. }

  289. int main()
  290. {
  291.         int fd;      
  292.                         
  293.         fd = open_camer_device();

  294.         init_camer_device(fd);
  295.        
  296.         start_capturing(fd);
  297.        
  298.         mainloop(fd);
  299.        
  300.         stop_capturing(fd);

  301.         uninit_camer_device(fd);

  302.         close_camer_device(fd);

  303.         return 0;
  304. }
復(fù)制代碼
上面程序運行結(jié)果如下:
{pixelformat = YUYV},description = 'YUV 4:2:2 (YUYV)'
n_buffer = 4
len=153600
len=153600

論壇徽章:
0
2 [報告]
發(fā)表于 2014-01-24 08:55 |只看該作者
已經(jīng)知道原因,是因為這個攝像頭的輸出格式是YUV格式,V4L2采集保存的文件也是YUV格式的,這種格式用常見的看圖工具是無法顯示的,需要專門的YUV查看工具才可以看;比如YUVviewer

論壇徽章:
0
3 [報告]
發(fā)表于 2014-03-04 16:43 |只看該作者
不能顯示是因為格式不對,可以直接輸出jpg格式的文件修改
//stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
改成 V4L2_PIX_FMT_MJPEG 就可以了

論壇徽章:
0
4 [報告]
發(fā)表于 2015-08-27 23:47 |只看該作者
本帖最后由 peterpeter2015 于 2015-08-27 23:47 編輯

你好,在你的貼子里http://72891.cn/thread-4120327-1-1.html 我改了stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV  為stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;因為程序輸出為:{pixelformat = GREY},description = 'Greyscale 8-bit (Y800)'
n_buffer = 4
len=307200
len=307200

但是jpg文件還是不可以看,為什么?是不是不能直接將內(nèi)存里的數(shù)據(jù)存為jpg?需要轉(zhuǎn)換原始數(shù)據(jù)才能變成jpg?謝謝回復(fù).
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP