android4.0 USB Camera实例(一)JNI层

一直想自己写一个从JNI层到应用层的Camera例子,android4.0上usb camera用不了 所以决定自己写一个  usb camera和coms原理都是一样的 基本v4l2 只不过源码数据格式不一样而已 下面我们就从JNI层开始

以下是我的代码,先上代码在 一步步说明

fimcgzsd.c

[cpp] view plain copy
  1. /* 
  2.  * Android USB Camera zc3xx Library 
  3.  * 
  4.  * Copyright (c) 2014  Store information technology guangzhou ltd<http://www.storeinf.com> 
  5.  * Copyright (c) 2014  hclydao <[email protected]> 
  6.  * 
  7.  * This program is free software; you can redistribute it and/or modify 
  8.  * it under the terms of the GNU General Public License as published by 
  9.  * the Free Software Foundation; either version 2 of the License. 
  10.  */  
  11. #include <errno.h>  
  12. #include <sys/types.h>      
  13. #include <sys/stat.h>   
  14. #include <fcntl.h>  
  15. #include <sys/ioctl.h>  
  16. #include <unistd.h>      
  17. #include <stdint.h>  
  18. #include <stdio.h>  
  19. #include <stdlib.h>  
  20. #include <asm/types.h>  
  21. #include <linux/videodev2.h>  
  22. #include <sys/mman.h>  
  23. #include <string.h>  
  24. #include <malloc.h>  
  25. #include <linux/fb.h>  
  26. #include <jni.h>  
  27. #include <string.h>  
  28. #include <android/log.h>  
  29. #include <syslog.h>  
  30.   
  31. #define  LOG_TAG    "FimcGzsd"  
  32. #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)  
  33. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , LOG_TAG, __VA_ARGS__)  
  34. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , LOG_TAG, __VA_ARGS__)  
  35. #define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , LOG_TAG, __VA_ARGS__)  
  36. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , LOG_TAG, __VA_ARGS__)  
  37.   
  38. struct fimc_buffer {  
  39.     unsigned char *start;  
  40.     size_t  length;  
  41. };  
  42.   
  43. static int fd = -1;  
  44. struct fimc_buffer *buffers=NULL;  
  45. struct v4l2_buffer v4l2_buf;  
  46. static int bufnum = 1;  
  47. static int mwidth,mheight;  
  48. /* 
  49.  *open usb camera device 
  50.  */  
  51. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_open(JNIEnv * env, jclass obj, const jbyteArray devname)  
  52. {  
  53.     jbyte *dev = (jbyte*)(*env)->GetByteArrayElements(env, devname, 0);  
  54.     fd = open(dev, O_RDWR, 0);    
  55.     if (fd<0)  
  56.     {  
  57.         LOGE("%s ++++ open error\n",dev);  
  58.         return  -1;  
  59.     }  
  60.     (*env)->ReleaseByteArrayElements(env, devname, dev, 0);  
  61.     return fd;  
  62. }  
  63. /* 
  64.  * init device 
  65.  */  
  66. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_init(JNIEnv * env, jclass obj, jint width, jint height,jint numbuf)  
  67. {  
  68.     int ret;  
  69.     int i;  
  70.     bufnum = numbuf;  
  71.     mwidth = width;  
  72.     mheight = height;  
  73.     struct v4l2_format fmt;   
  74.     struct v4l2_capability cap;  
  75.   
  76.     ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);  
  77.     if (ret < 0) {  
  78.         LOGE("%d :VIDIOC_QUERYCAP failed\n",__LINE__);  
  79.         return -1;  
  80.     }  
  81.     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {  
  82.         LOGE("%d : no capture devices\n",__LINE__);  
  83.         return -1;  
  84.     }  
  85.                   
  86.     memset( &fmt, 0, sizeof(fmt));  
  87.     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  88.     fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;  
  89.     fmt.fmt.pix.width = width;  
  90.     fmt.fmt.pix.height = height;                      
  91.     if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)  
  92.     {  
  93.         LOGE("++++%d : set format failed\n",__LINE__);  
  94.         return -1;  
  95.     }  
  96.   
  97.     struct v4l2_requestbuffers req;  
  98.     req.count = numbuf;  
  99.     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  100.     req.memory = V4L2_MEMORY_MMAP;  
  101.   
  102.     ret = ioctl(fd, VIDIOC_REQBUFS, &req);  
  103.     if (ret < 0) {  
  104.         LOGE("++++%d : VIDIOC_REQBUFS failed\n",__LINE__);  
  105.         return -1;  
  106.     }  
  107.   
  108.     buffers = calloc(req.count, sizeof(*buffers));  
  109.     if (!buffers) {  
  110.         LOGE ("++++%d Out of memory\n",__LINE__);  
  111.         return -1;  
  112.     }  
  113.   
  114.     for(i = 0; i< bufnum; ++i) {  
  115.         memset(&v4l2_buf, 0, sizeof(v4l2_buf));  
  116.         v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  117.         v4l2_buf.memory = V4L2_MEMORY_MMAP;  
  118.         v4l2_buf.index = i;  
  119.         ret = ioctl(fd , VIDIOC_QUERYBUF, &v4l2_buf);  
  120.         if(ret < 0) {  
  121.            LOGE("+++%d : VIDIOC_QUERYBUF failed\n",__LINE__);  
  122.            return -1;  
  123.         }  
  124.         buffers[i].length = v4l2_buf.length;  
  125.         if ((buffers[i].start = (char *)mmap(0, v4l2_buf.length,  
  126.                                              PROT_READ | PROT_WRITE, MAP_SHARED,  
  127.                                              fd, v4l2_buf.m.offset)) < 0) {  
  128.              LOGE("%d : mmap() failed",__LINE__);  
  129.              return -1;  
  130.         }  
  131.     }  
  132.     return 0;  
  133. }  
  134. /* 
  135.  *open usb camera device 
  136.  */  
  137. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_streamon(JNIEnv * env, jclass obj)  
  138. {  
  139.     int i;  
  140.     int ret;  
  141.     enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  142.     for(i = 0; i< bufnum; ++i) {  
  143.         memset(&v4l2_buf, 0, sizeof(v4l2_buf));  
  144.         v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  145.         v4l2_buf.memory = V4L2_MEMORY_MMAP;  
  146.         v4l2_buf.index = i;  
  147.         ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);  
  148.         if (ret < 0) {  
  149.             LOGE("%d : VIDIOC_QBUF failed\n",__LINE__);  
  150.             return ret;  
  151.         }  
  152.     }  
  153.     ret = ioctl(fd, VIDIOC_STREAMON, &type);  
  154.     if (ret < 0) {  
  155.         LOGE("%d : VIDIOC_STREAMON failed\n",__LINE__);  
  156.         return ret;  
  157.     }  
  158.     return 0;  
  159. }  
  160. /* 
  161.  *get one frame data 
  162.  */  
  163. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_dqbuf(JNIEnv * env, jclass obj,const jbyteArray videodata)  
  164. {  
  165.     int ret;  
  166.   
  167.     jbyte *data = (jbyte*)(*env)->GetByteArrayElements(env, videodata, 0);  
  168.     v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  169.     v4l2_buf.memory = V4L2_MEMORY_MMAP;  
  170.   
  171.     ret = ioctl(fd, VIDIOC_DQBUF, &v4l2_buf);  
  172.     if (ret < 0) {  
  173.         LOGE("%s : VIDIOC_DQBUF failed, dropped frame\n",__func__);  
  174.         return ret;  
  175.     }  
  176.   
  177.     memcpy(data,buffers[v4l2_buf.index].start,buffers[v4l2_buf.index].length);  
  178.     (*env)->ReleaseByteArrayElements(env, videodata, data, 0);  
  179.     return v4l2_buf.index;  
  180. }  
  181. /* 
  182.  *put in frame buffer to queue 
  183.  */  
  184. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_qbuf(JNIEnv * env, jclass obj,jint index)  
  185. {  
  186.     int ret;  
  187.   
  188.     v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  189.     v4l2_buf.memory = V4L2_MEMORY_MMAP;  
  190.     v4l2_buf.index = index;  
  191.   
  192.     ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);  
  193.     if (ret < 0) {  
  194.         LOGE("%s : VIDIOC_QBUF failed\n",__func__);  
  195.         return ret;  
  196.     }  
  197.   
  198.     return 0;  
  199. }  
  200. /* 
  201.  *streamoff 
  202.  */  
  203. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_streamoff(JNIEnv * env, jclass obj,jint index)  
  204. {  
  205.     enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  206.     int ret;  
  207.   
  208.     ret = ioctl(fd, VIDIOC_STREAMOFF, &type);  
  209.     if (ret < 0) {  
  210.         LOGE("%s : VIDIOC_STREAMOFF failed\n",__func__);  
  211.         return ret;  
  212.     }  
  213.   
  214.     return 0;  
  215. }  
  216. /* 
  217.  *release 
  218.  */  
  219. JNIEXPORT jint JNICALL Java_com_dao_usbcam_Fimcgzsd_release(JNIEnv * env, jclass obj)  
  220. {  
  221.     enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  222.     int ret;  
  223.     int i;  
  224.   
  225.     ret = ioctl(fd, VIDIOC_STREAMOFF, &type);  
  226.     if (ret < 0) {  
  227.         LOGE("%s : VIDIOC_STREAMOFF failed\n",__func__);  
  228.         return ret;  
  229.     }  
  230.   
  231.     for (i = 0; i < bufnum; i++) {  
  232.        ret = munmap(buffers[i].start, buffers[i].length);  
  233.         if (ret < 0) {  
  234.             LOGE("%s : munmap failed\n",__func__);  
  235.             return ret;  
  236.         }  
  237.     }  
  238.     free (buffers);  
  239.     close(fd);  
  240.     return 0;  
  241. }  

首先是open这个就不作说明了

第二初始化init函数

[cpp] view plain copy
  1. ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);  
  2. if (ret < 0) {  
  3.     LOGE("%d :VIDIOC_QUERYCAP failed\n",__LINE__);  
  4.     return -1;  
  5. }  
  6. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {  
  7.     LOGE("%d : no capture devices\n",__LINE__);  
  8.     return -1;  
  9. }  
获取设备相关信息,检查是否支持capture模式

[cpp] view plain copy
  1. memset( &fmt, 0, sizeof(fmt));  
  2. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  3. fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;  
  4. fmt.fmt.pix.width = width;  
  5. fmt.fmt.pix.height = height;                      
  6. if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)  
  7. {  
  8.     LOGE("++++%d : set format failed\n",__LINE__);  
  9.     return -1;  
  10. }  
设置格式,usb camera获取到的已经是jpeg格式 所以这里设置成RGB565格式

[cpp] view plain copy
  1. struct v4l2_requestbuffers req;  
  2. req.count = numbuf;  
  3. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  4. req.memory = V4L2_MEMORY_MMAP;  
  5.   
  6. ret = ioctl(fd, VIDIOC_REQBUFS, &req);  
  7. if (ret < 0) {  
  8.     LOGE("++++%d : VIDIOC_REQBUFS failed\n",__LINE__);  
  9.     return -1;  
  10. }  
申请缓冲区,这里申请numbuf个缓冲帧
[cpp] view plain copy
  1.    buffers = calloc(req.count, sizeof(*buffers));  
  2.    if (!buffers) {  
  3.        LOGE ("++++%d Out of memory\n",__LINE__);  
  4.     return -1;  
  5.    }  
  6.   
  7. for(i = 0; i< bufnum; ++i) {  
  8.     memset(&v4l2_buf, 0, sizeof(v4l2_buf));  
  9.     v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  10.     v4l2_buf.memory = V4L2_MEMORY_MMAP;  
  11.     v4l2_buf.index = i;  
  12.     ret = ioctl(fd , VIDIOC_QUERYBUF, &v4l2_buf);  
  13.     if(ret < 0) {  
  14.        LOGE("+++%d : VIDIOC_QUERYBUF failed\n",__LINE__);  
  15.        return -1;  
  16.     }  
  17.     buffers[i].length = v4l2_buf.length;  
  18.     if ((buffers[i].start = (char *)mmap(0, v4l2_buf.length,  
  19.                                          PROT_READ | PROT_WRITE, MAP_SHARED,  
  20.                                          fd, v4l2_buf.m.offset)) < 0) {  
  21.          LOGE("%d : mmap() failed",__LINE__);  
  22.          return -1;  
  23.     }  
  24. }  
映射虚拟内存到物理地址,获取每个缓冲区的物理地址


streamon函数

将缓冲区放入队列并开启数据流

dqbuf函数

获取一帧数据 返回当前缓冲区的序列号

qbuf函数

将指定缓冲区放入队列,获取到某一缓冲区的数据后需要重新将这个缓冲区放入队列

后面两个我就不多说明了


Android.mk文件:

[python] view plain copy
  1. LOCAL_PATH:= $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4. LOCAL_MODULE_TAGS := eng  
  5. LOCAL_SRC_FILES:= fimcgzsd.c  
  6. LOCAL_MODULE := libfimcgzsd  
  7. LOCAL_LDLIBS    := -llog  
  8. LOCAL_SHARED_LIBRARIES := libc libcutils  
  9. include $(BUILD_SHARED_LIBRARY) 

你可能感兴趣的:(android,Camera,usbcamera)