微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > 嵌入式系统设计讨论 > 4.MTX20开发板添加USB Camera支持和应用程序验证。

4.MTX20开发板添加USB Camera支持和应用程序验证。

时间:10-02 整理:3721RD 点击:
因为工作的需要,自己对Camera HAL做过很多研究,本以为在MediaTek X20开发板上移植USB Camera会是很easy的事情,可还是遇到一些问题。
一)添加驱动支持
kernel-3.18对UVC的框架已经支持的很好,只需要打开编译开关即可,下面的开关是否全部有用处自己没有验证。

  1. select MEDIA_SUPPORT
  2.         select MEDIA_USB_SUPPORT
  3.         select MEDIA_CAMERA_SUPPORT
  4.         select MEDIA_CONTROLLER
  5.         select VIDEO_DEV
  6.         select VIDEO_V4L2_SUBDEV_API
  7.         select VIDEO_V4L2
  8.         select VIDEOBUF_GEN
  9.         select VIDEOBUF2_DMA_SG
  10.         select V4L2_MEM2MEM_DEV
  11.         select VIDEOBUF2_CORE
  12.         select VIDEOBUF2_MEMOPS
  13.         select VIDEOBUF2_DMA_CONTIG
  14.         select VIDEOBUF2_VMALLOC
  15.         select VIDEO_V4L2_INT_DEVICE
  16.         select V4L_PLATFORM_DRIVERS
  17.         select V4L_TEST_DRIVERS
  18.         select USB_VIDEO_CLASS
  19.         select USB_VIDEO_CLASS_INPUT_EVDEV
  20.         select USB_GSPCA

复制代码

编译,更新系统后开发板,开发板设置USB为HOST模式,插入USB Camera,应该就可以找到
类似/dev/video0设备节点,插入多个Camera设备时要分清楚自己要测试哪个。
如果没有/dev/video*设备节点,则说明系统不对,需要进一步调查。反正我前几天一直没有出现这个设备节点,后面又莫名其妙的出现了。
二)应用程序支持
我这里支持添加C代码,编译成一个可执行程序测试,后面在使用JNI和APK程序方式测试。

  1. #include "ImageProc.h"
  2. //01-24 07:43:06.439: E/TEST(3756): VIDIOC_DQBUF error 22, Invalid argument
  3. #define FOURCC_FORMAT                "%c%c%c%c"
  4. #define FOURCC_ARGS(c)                (c) & 0xFF, ((c) >> 8) & 0xFF, ((c) >> 16) & 0xFF, ((c) >> 24) & 0xFF

  5. int errnoexit(const char *s)
  6. {
  7.         LOGE("%s error %d, %s", s, errno, strerror (errno));
  8.         return ERROR_LOCAL;
  9. }

  10. int xioctl(int fd, int request, void *arg)
  11. {
  12.         int r;

  13.         do r = ioctl (fd, request, arg);
  14.         while (-1 == r && EINTR == errno);

  15.         return r;
  16. }

  17. //检查video设备名称
  18. int checkCamerabase(void){
  19.         struct stat st;
  20.         int i;
  21.         int start_from_4 = 1;
  22.        
  23.         /* if /dev/video[0-3] exist, camerabase=4, otherwise, camrerabase = 0 */
  24.         for(i=0 ; i<4 ; i++){
  25.                 sprintf(dev_name,"/dev/video%d",i);
  26.                 if (-1 == stat (dev_name, &st)) {
  27.                         start_from_4 &= 0;
  28.                 }else{
  29.                         start_from_4 &= 1;
  30.                 }
  31.         }

  32.         if(start_from_4){
  33.                 return 4;
  34.         }else{
  35.                 return 0;
  36.         }
  37. }
  38. //打开video设备
  39. int opendevice(int i)
  40. {
  41.         struct stat st;

  42.         sprintf(dev_name,"/dev/video%d",i);
  43.         //stat() 获得文件属性,并判断是否为字符设备文件
  44.         if (-1 == stat (dev_name, &st)) {
  45.                 LOGE("Cannot identify '%s': %d, %s", dev_name, errno, strerror (errno));
  46.                 return ERROR_LOCAL;
  47.         }

  48.         if (!S_ISCHR (st.st_mode)) {
  49.                 LOGE("%s is no device", dev_name);
  50.                 return ERROR_LOCAL;
  51.         }

  52.         fd = open (dev_name, O_RDWR);

  53.         if (-1 == fd) {
  54.                 LOGE("Cannot open '%s': %d, %s", dev_name, errno, strerror (errno));
  55.                 return ERROR_LOCAL;
  56.         }
  57.         return SUCCESS_LOCAL;
  58. }
  59. //初始化设备
  60. int initdevice(void)
  61. {
  62.         struct v4l2_capability cap;
  63.         struct v4l2_cropcap cropcap;
  64.         struct v4l2_crop crop;
  65.         struct v4l2_format fmt;
  66.         unsigned int min;
  67.         //VIDIOC_QUERYCAP 命令 来获得当前设备的各个属性
  68.         if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap)) {
  69.                 if (EINVAL == errno) {
  70.                         LOGE("%s is no V4L2 device", dev_name);
  71.                         return ERROR_LOCAL;
  72.                 } else {
  73.                         return errnoexit ("VIDIOC_QUERYCAP");
  74.                 }
  75.         }
  76.         //V4L2_CAP_VIDEO_CAPTURE 0x00000001
  77.         // 这个设备支持 video capture 的接口,即这个设备具备 video capture 的功能
  78.         if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
  79.                 LOGE("%s is no video capture device", dev_name);
  80.                 return ERROR_LOCAL;
  81.         }
  82.         //V4L2_CAP_STREAMING 0x04000000
  83.         // 这个设备是否支持 streaming I/O 操作函数
  84.         if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
  85.                 LOGE("%s does not support streaming i/o", dev_name);
  86.                 return ERROR_LOCAL;
  87.         }
  88.         //获得设备对 Image Cropping 和 Scaling 的支持
  89. #if 0
  90.         CLEAR (cropcap);

  91.         cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  92.         if (0 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
  93.                 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  94.                 crop.c = cropcap.defrect;

  95.                 if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
  96.                         switch (errno) {
  97.                                 case EINVAL:
  98.                                         break;
  99.                                 default:
  100.                                         break;
  101.                         }
  102.                 }
  103.         } else {
  104.         }
  105. #endif
  106.         //设置图形格式
  107.         CLEAR (fmt);

  108.         fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  109.         fmt.fmt.pix.width       = IMG_WIDTH;
  110.         fmt.fmt.pix.height      = IMG_HEIGHT;

  111.         fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//V4L2_PIX_FMT_YUYV;//V4L2_PIX_FMT_MJPEG;//V4L2_PIX_FMT_YUYV;
  112.         fmt.fmt.pix.field       = V4L2_FIELD_ANY;
  113.         //检查流权限
  114.         if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
  115.                 return errnoexit ("VIDIOC_S_FMT");
  116.                 LOGE("=0 IMG_WIDTH=0x%x, IMG_HEIGHT=0x%x, V4L2_PIX_FMT_YUYV=0x%x", IMG_WIDTH, IMG_HEIGHT, V4L2_PIX_FMT_YUYV);

  117.         min = fmt.fmt.pix.width * 2;
  118.         //每行像素所占的 byte 数
  119.         if (fmt.fmt.pix.bytesperline < min)
  120.                 fmt.fmt.pix.bytesperline = min;
  121.         min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
  122.         if (fmt.fmt.pix.sizeimage < min)
  123.                 fmt.fmt.pix.sizeimage = min;

  124.         return initmmap ();

  125. }
  126. //I/O模式选择
  127. int initmmap(void)
  128. {
  129.         struct v4l2_requestbuffers req;

  130.         CLEAR (req);

  131.         req.count               = 4;
  132.         req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  133.         req.memory              = V4L2_MEMORY_MMAP;

  134.         if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
  135.                 if (EINVAL == errno) {
  136.                         LOGE("%s does not support memory mapping", dev_name);
  137.                         return ERROR_LOCAL;
  138.                 } else {
  139.                         return errnoexit ("VIDIOC_REQBUFS");
  140.                 }
  141.         }

  142.         if (req.count < 2) {
  143.                 LOGE("Insufficient buffer memory on %s", dev_name);
  144.                 return ERROR_LOCAL;
  145.         }

  146.         buffers = calloc (req.count, sizeof (*buffers));

  147.         if (!buffers) {
  148.                 LOGE("Out of memory");
  149.                 return ERROR_LOCAL;
  150.         }

  151.         for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
  152.                 struct v4l2_buffer buf;

  153.                  CLEAR (buf);

  154.                 buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  155.                 buf.memory      = V4L2_MEMORY_MMAP;
  156.                 buf.index       = n_buffers;

  157.                 if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf))
  158.                         return errnoexit ("VIDIOC_QUERYBUF");

  159.                 buffers[n_buffers].length = buf.length;
  160.                 buffers[n_buffers].start =
  161.                 mmap (NULL ,
  162.                         buf.length,
  163.                         PROT_READ | PROT_WRITE,
  164.                         MAP_SHARED,
  165.                         fd, buf.m.offset);

  166.                 if (MAP_FAILED == buffers[n_buffers].start)
  167.                         return errnoexit ("mmap");
  168.         }

  169.         return SUCCESS_LOCAL;
  170. }

  171. int startcapturing(void)
  172. {
  173.         unsigned int i;
  174.         enum v4l2_buf_type type;

  175.         for (i = 0; i < n_buffers; ++i) {
  176.                 struct v4l2_buffer buf;

  177.                 CLEAR (buf);

  178.                 buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  179.                 buf.memory      = V4L2_MEMORY_MMAP;
  180.                 buf.index       = i;

  181.                 if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
  182.                         return errnoexit ("VIDIOC_QBUF");
  183.         }

  184.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  185.         if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
  186.                 return errnoexit ("VIDIOC_STREAMON");

  187.         return SUCCESS_LOCAL;
  188. }

  189. int readframeonce(void)
  190. {
  191.         int i = 1;
  192.         for (;;) {
  193.                 fd_set fds;
  194.                 struct timeval tv;
  195.                 int r;

  196.                 FD_ZERO (&fds);
  197.                 FD_SET (fd, &fds);

  198.                 tv.tv_sec = 2;
  199.                 tv.tv_usec = 0;

  200.                 r = select (fd + 1, &fds, NULL, NULL, &tv);

  201.                 if (-1 == r) {
  202.                         if (EINTR == errno)
  203.                                 continue;

  204.                         return errnoexit ("select");
  205.                 }

  206.                 if (0 == r) {
  207.                         LOGE("select timeout");
  208.                         return ERROR_LOCAL;

  209.                 }

  210.                 if (readframe (i)==1)
  211.                         break;

  212.         }

  213.         return SUCCESS_LOCAL;

  214. }


  215. void processimage (const void *p){
  216.                 yuyv422toABGRY((unsigned char *)p);
  217. }

  218. int readframe(int num){

  219.         struct v4l2_buffer buf;
  220.         unsigned int i;
  221.         int fd_save = 0;
  222.         //timeval cur_time;
  223.         time_t timep;
  224.         char str[32] = {0};
  225.         int nRet = 0;
  226.         CLEAR (buf);

  227.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  228.         buf.memory = V4L2_MEMORY_MMAP;
  229.         //buf.memory = V4L2_MEMORY_USERPTR;
  230.         //LOGE("fd=%d,request=%d,buf=%d",fd,VIDIOC_DQBUF,&buf);
  231.         if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
  232.                 switch (errno) {
  233.                         case EAGAIN:
  234.                                 return 0;
  235.                         case EIO:
  236.                         default:
  237.                                 return errnoexit ("VIDIOC_DQBUF");
  238.                 }
  239.         }

  240.         assert (buf.index < n_buffers);
  241. #if 0
  242.         processimage (buffers[buf.index].start);
  243.         //    gettimeofday(&cur_time, NULL);
  244.         struct tm *p;
  245.     time(&timep);
  246.     p = localtime(&timep); //取得当地时间
  247.         sprintf(str, "%d_%d.bmp", 123, num);
  248. #else
  249.         sprintf(str, "%d_%d.yuv", 123, num);
  250. #endif
  251.                 fd_save = open (str, O_RDWR | O_APPEND);
  252.                 LOGE("=0009=save open %s", str);

  253.         if (-1 == fd_save) {
  254.                 LOGE("=0010=Cannot open '%s': %d, %s", str, errno, strerror (errno));
  255.                 //return ERROR_LOCAL;
  256.         }
  257.         else
  258.                 {
  259.         nRet = write(fd_save, buffers[buf.index].start, buffers[buf.index].length);
  260.         if (-1 == nRet) {
  261.                 LOGE("=0011=Cannot open '%s': %d, %s", str, errno, strerror (errno));
  262.                 return ERROR_LOCAL;
  263.         }
  264.         else
  265.         {
  266.                 nRet = 10;
  267.         }
  268.                 }
  269.         close(fd_save);
  270.         if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
  271.                 return errnoexit ("VIDIOC_QBUF");
  272.         if(nRet == 10)
  273.                 {
  274.                
  275.                 }
  276.         return 1;
  277. }

  278. int stopcapturing(void)
  279. {
  280.         enum v4l2_buf_type type;

  281.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  282.         if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
  283.                 return errnoexit ("VIDIOC_STREAMOFF");

  284.         return SUCCESS_LOCAL;

  285. }

  286. int uninitdevice(void)
  287. {
  288.         unsigned int i;

  289.         for (i = 0; i < n_buffers; ++i)
  290.                 if (-1 == munmap (buffers[i].start, buffers[i].length))
  291.                         return errnoexit ("munmap");

  292.         free (buffers);

  293.         return SUCCESS_LOCAL;
  294. }
  295. //关闭设备
  296. int closedevice(void)
  297. {
  298.         if (-1 == close (fd)){
  299.                 fd = -1;
  300.                 return errnoexit ("close");
  301.         }

  302.         fd = -1;
  303.         return SUCCESS_LOCAL;
  304. }

  305. void yuyv422toABGRY(unsigned char *src)
  306. {

  307.         int width=0;
  308.         int height=0;

  309.         width = IMG_WIDTH;
  310.         height = IMG_HEIGHT;

  311.         int frameSize =width*height*2;

  312.         int i;

  313.         if((!rgb || !ybuf)){
  314.                 return;
  315.         }
  316.         int *lrgb = NULL;
  317.         int *lybuf = NULL;
  318.                
  319.         lrgb = &rgb[0];
  320.         lybuf = &ybuf[0];

  321.         if(yuv_tbl_ready==0){
  322.                 for(i=0 ; i<256 ; i++){
  323.                         y1192_tbl[i] = 1192*(i-16);
  324.                         if(y1192_tbl[i]<0){
  325.                                 y1192_tbl[i]=0;
  326.                         }

  327.                         v1634_tbl[i] = 1634*(i-128);
  328.                         v833_tbl[i] = 833*(i-128);
  329.                         u400_tbl[i] = 400*(i-128);
  330.                         u2066_tbl[i] = 2066*(i-128);
  331.                 }
  332.                 yuv_tbl_ready=1;
  333.         }

  334.         for(i=0 ; i<frameSize ; i+=4){
  335.                 unsigned char y1, y2, u, v;
  336.                 y1 = src[i];
  337.                 u = src[i+1];
  338.                 y2 = src[i+2];
  339.                 v = src[i+3];

  340.                 int y1192_1=y1192_tbl[y1];
  341.                 int r1 = (y1192_1 + v1634_tbl[v])>>10;
  342.                 int g1 = (y1192_1 - v833_tbl[v] - u400_tbl[u])>>10;
  343.                 int b1 = (y1192_1 + u2066_tbl[u])>>10;

  344.                 int y1192_2=y1192_tbl[y2];
  345.                 int r2 = (y1192_2 + v1634_tbl[v])>>10;
  346.                 int g2 = (y1192_2 - v833_tbl[v] - u400_tbl[u])>>10;
  347.                 int b2 = (y1192_2 + u2066_tbl[u])>>10;

  348.                 r1 = r1>255 ? 255 : r1<0 ? 0 : r1;
  349.                 g1 = g1>255 ? 255 : g1<0 ? 0 : g1;
  350.                 b1 = b1>255 ? 255 : b1<0 ? 0 : b1;
  351.                 r2 = r2>255 ? 255 : r2<0 ? 0 : r2;
  352.                 g2 = g2>255 ? 255 : g2<0 ? 0 : g2;
  353.                 b2 = b2>255 ? 255 : b2<0 ? 0 : b2;

  354.                 *lrgb++ = 0xff000000 | b1<<16 | g1<<8 | r1;
  355.                 *lrgb++ = 0xff000000 | b2<<16 | g2<<8 | r2;

  356.                 if(lybuf!=NULL){
  357.                         *lybuf++ = y1;
  358.                         *lybuf++ = y2;
  359.                 }
  360.         }

  361. }

  362. #if 1
  363. int main()
  364. {
  365.         int ret;
  366.         int num = 0;;
  367.     struct v4l2_format v4l2_fmt;
  368.     memset(&v4l2_fmt, 0, sizeof(v4l2_fmt));
  369.         LOGE("=0=usb camera imageproc\n");

  370.         if(camerabase<0){
  371.                 //camerabase = checkCamerabase();
  372.         }
  373.         ret = opendevice(0);
  374.         LOGE("=1=usb camera imageproc\n");

  375.         if(ret != ERROR_LOCAL){
  376.                 ret = initdevice();
  377.         }
  378.         v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  379.   ret = ioctl(fd, VIDIOC_G_FMT, &v4l2_fmt);
  380.   if ( ret < 0) {
  381.       LOGE("ERR(%s):VIDIOC_G_FMT failed. %s(%d)\n", __func__, strerror(errno), errno);
  382.      // return -1;
  383.   }

  384.         LOGE("=2=usb v4l2_fmt.fmt.pix.width=%d, v4l2_fmt.fmt.pix.height=%d, v4l2_fmt.fmt.pix.pixelformat=0x%x\n",
  385.         v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height, v4l2_fmt.fmt.pix.pixelformat);
  386.                         LOGE("  Frame format: "FOURCC_FORMAT"\n", FOURCC_ARGS(v4l2_fmt.fmt.pix.pixelformat));

  387.         if(ret != ERROR_LOCAL){
  388.                 ret = startcapturing();
  389.         LOGE("=1=usb camera imageproc\n");

  390.                 if(ret != SUCCESS_LOCAL){
  391.                         stopcapturing();
  392.                         uninitdevice ();
  393.                         closedevice ();
  394.                         LOGE("device resetted");       
  395.                 }

  396.         }
  397.         LOGE("=3=usb camera imageproc\n");

  398.         if(ret != ERROR_LOCAL){
  399.                 rgb = (int *)malloc(sizeof(int) * (IMG_WIDTH*IMG_HEIGHT));
  400.                 ybuf = (int *)malloc(sizeof(int) * (IMG_WIDTH*IMG_HEIGHT));
  401.         }
  402.         LOGE("=4=usb camera imageproc\n");
  403.                 //*************************************************
  404.                 while(num < 20)
  405.                 {
  406.                                 readframeonce();
  407.                                 num++;
  408.                         }
  409.         //*************************************************
  410.         LOGE("=5=usb camera imageproc\n");
  411.         stopcapturing ();
  412.         LOGE("=6=usb camera imageproc\n");

  413.         uninitdevice ();
  414.         LOGE("=7=usb camera imageproc\n");

  415.         closedevice ();

  416.         if(rgb) free(rgb);
  417.         if(ybuf) free(ybuf);
  418.         
  419.         fd = -1;
  420.        
  421.         return ret;

  422. }
  423. #else
  424. void
  425. Java_com_camera_simplewebcam_CameraPreview_pixeltobmp( JNIEnv* env,jobject thiz,jobject bitmap){

  426.         jboolean bo;


  427.         AndroidBitmapInfo  info;
  428.         void*              pixels;
  429.         int                ret;
  430.         int i;
  431.         int *colors;

  432.         int width=0;
  433.         int height=0;

  434.         if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
  435.                 LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
  436.                 return;
  437.         }
  438.    
  439.         width = info.width;
  440.         height = info.height;

  441.         if(!rgb || !ybuf) return;

  442.         if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
  443.                 LOGE("Bitmap format is not RGBA_8888 !");
  444.                 return;
  445.         }

  446.         if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
  447.                 LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
  448.         }

  449.         colors = (int*)pixels;
  450.         int *lrgb =NULL;
  451.         lrgb = &rgb[0];

  452.         for(i=0 ; i<width*height ; i++){
  453.                 *colors++ = *lrgb++;
  454.         }

  455.         AndroidBitmap_unlockPixels(env, bitmap);

  456. }

  457. jint
  458. Java_com_camera_simplewebcam_CameraPreview_prepareCamera( JNIEnv* env,jobject thiz, jint videoid){

  459.         int ret;

  460.         if(camerabase<0){
  461.                 camerabase = checkCamerabase();
  462.         }

  463.         ret = opendevice(camerabase + videoid);

  464.         if(ret != ERROR_LOCAL){
  465.                 ret = initdevice();
  466.         }
  467.         if(ret != ERROR_LOCAL){
  468.                 ret = startcapturing();

  469.                 if(ret != SUCCESS_LOCAL){
  470.                         stopcapturing();
  471.                         uninitdevice ();
  472.                         closedevice ();
  473.                         LOGE("device resetted");       
  474.                 }

  475.         }

  476.         if(ret != ERROR_LOCAL){
  477.                 rgb = (int *)malloc(sizeof(int) * (IMG_WIDTH*IMG_HEIGHT));
  478.                 ybuf = (int *)malloc(sizeof(int) * (IMG_WIDTH*IMG_HEIGHT));
  479.         }

  480.         return ret;
  481. }       



  482. jint
  483. Java_com_camera_simplewebcam_CameraPreview_prepareCameraWithBase( JNIEnv* env,jobject thiz, jint videoid, jint videobase){
  484.        
  485.                 int ret;

  486.                 camerabase = videobase;
  487.        
  488.                 return Java_com_camera_simplewebcam_CameraPreview_prepareCamera(env,thiz,videoid);
  489.        
  490. }

  491. void
  492. Java_com_camera_simplewebcam_CameraPreview_processCamera( JNIEnv* env,
  493.                                                                                 jobject thiz){

  494.         readframeonce();
  495. }

  496. void
  497. Java_com_camera_simplewebcam_CameraPreview_stopCamera(JNIEnv* env,jobject thiz){

  498.         stopcapturing ();

  499.         uninitdevice ();

  500.         closedevice ();

  501.         if(rgb) free(rgb);
  502.         if(ybuf) free(ybuf);
  503.         
  504.         fd = -1;

  505. }

  506. #endif

复制代码

上面是.c文件,下面是编译文件Android.mk,从代码就可以看出来,我的代码是从SimpleWebCam开源代码摘取的,特此感谢。

  1. LOCAL_PATH:= $(call my-dir)


  2. #########################################################
  3. include $(CLEAR_VARS)

  4. LOCAL_SRC_FILES:= ImageProc.c

  5. LOCAL_C_INCLUDES += external/jpeg \
  6.         external/skia/include/core/ \
  7.         frameworks/base/core/jni/android/graphics \
  8.         system/core/include/

  9. LOCAL_SHARED_LIBRARIES := libandroid_runtime


  10. LOCAL_CFLAGS := -Wall -fpic -pipe -O0

  11. LOCAL_MODULE    := ImageProc
  12. LOCAL_LDLIBS    := -llog

  13. include $(BUILD_EXECUTABLE)

复制代码

编译完成push到系统中,执行这个应用程序,pull出123_1.yuv文件。
直接使用vlc程序得到下面的结果:


使用另外一款YUV显示软件结果正常:


可以这么认为其实保存好的YUV数据文件的数据是对的,只是保存文件的头信息不对,导致两个软件显示结果不对,要深入理解这个问题就必须对YUV格式做进一步解析,这里只得出一个成功的结论。
三)总结:
1.对v4l2与Camera驱动的关系有了更进一步的认识;
2.对Camera模组支持模式:YUV和MJPG格式有了清晰认识;
3.对YUV格式数据文件读写加深了理解。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top