Android系统Camera预览刚打开时由暗变明

来源:互联网 发布:vasp软件使用 编辑:程序博客网 时间:2024/06/01 08:06

http://blog.csdn.net/tankai19880619/article/details/16983627

一、回忆下V4L2驱动操作流程

1.查询驱动功能

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct v4l2_capability cap;    
  2. ioctl(fd,VIDIOC_QUERYCAP,&cap);    
  3. printf("TK---------->>>>>Driver Name:%s\nCard Name:%s\nBus info:%s\n",cap.driver,cap.card,cap.bus_info);  

2.获取当前驱动支持的视频格式

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct v4l2_fmtdesc fmtdesc;    
  2. fmtdesc.index = 0; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  3. while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) != -1){    
  4.   printf("TK-------->>>>>fmtdesc.description is %s\n",fmtdesc.description);    
  5.   fmtdesc.index ++;    
  6. }  

3.设置当前驱动的频捕获格式

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct v4l2_format fmt;    
  2. memset(&fmt,0,sizeof(fmt));    
  3. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  4. fmt.fmt.pix.width = 1280;    
  5. fmt.fmt.pix.height = 720;    
  6. fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;    
  7. fmt.fmt.pix.field       = V4L2_FIELD_NONE;//V4L2_FIELD_INTERLACED;    
  8. fmt.fmt.pix.colorspace = 8;    
  9. int fmtreslt = ioctl(fd,VIDIOC_S_FMT,&fmt);    
  10. printf("TK--------_>>>>fmtreslt is %d\n",fmtreslt);    
  11. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   
  12. //重新获取,看是否设置成功   
  13. ioctl(fd,VIDIOC_G_FMT,&fmt);    
  14. printf("TK----------->>>>>fmt.fmt.width is %d\nfmt.fmt.pix.height is %d\nfmt.fmt.pix.colorspace is %d\n",fmt.fmt.pix.width,fmt.fmt.pix.height,fmt.fmt.pix.colorspace);    

4.分配内存(一般不超过5个)并转换成物理地址,将物理地址映射到用户空间

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct v4l2_requestbuffers req;    
  2. req.count = 4;    
  3. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  4. req.memory = V4L2_MEMORY_MMAP;    
  5. //分配内存  
  6. ioctl(fd,VIDIOC_REQBUFS,&req);    
  7. struct buffer{    
  8.   void *start;    
  9.   unsigned int length;    
  10. }*buffers;    
  11. buffers = (struct buffer*)calloc (req.count, sizeof(*buffers));    
  12. unsigned int n_buffers = 0;    
  13. for(n_buffers = 0; n_buffers < req.count; ++n_buffers){    
  14.   struct v4l2_buffer buf;    
  15.   memset(&buf,0,sizeof(buf));    
  16.   buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  17.   buf.memory = V4L2_MEMORY_MMAP;    
  18.   buf.index = n_buffers;    
  19.   //转换成物理地址  
  20.   if(ioctl(fd,VIDIOC_QUERYBUF,&buf) == -1){    
  21.     printf("TK---------_>>>>>>error\n");    
  22.     close(fd);    
  23.     exit(-1);    
  24.   }    
  25.   buffers[n_buffers].length = buf.length;   
  26.   //映射到用户空间   
  27.   buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);    
  28.   if(MAP_FAILED == buffers[n_buffers].start){    
  29.     printf("TK--------__>>>>>error 2\n");    
  30.     close(fd);    
  31.     exit(-1);    
  32.   }    
  33. }  

5.把数据放入缓存队列

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. unsigned int i;    
  2. enum v4l2_buf_type type;    
  3. for(i = 0; i < 4; i++){    
  4.   struct v4l2_buffer buf;    
  5.   buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  6.   buf.memory = V4L2_MEMORY_MMAP;    
  7.   buf.index = i;    
  8.   ioctl(fd,VIDIOC_QBUF,&buf);    
  9. }  

6.开启视频流

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  2. ioctl(fd,VIDIOC_STREAMON,&type);   
7.把数据从缓存队列中读取出来
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. unsigned int j;    
  2. for(j = 0; j < 4; j++){    
  3.   struct v4l2_buffer buf;    
  4.   buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  5.   buf.memory = V4L2_MEMORY_MMAP;    
  6.   buf.index = 0;    
  7.   ioctl(fd,VIDIOC_DQBUF,&buf);    
  8.   char path[30];    
  9.   snprintf(path,sizeof(path),"./v4l2test/720pmjpeg%d",buf.index);    
  10.   int fdyuyv = open(path,O_WRONLY|O_CREAT,00700);    
  11.   printf("TK--------->>>>fdyuyv is %d\n",fdyuyv);    
  12.   int resultyuyv = write(fdyuyv,buffers[buf.index].start,1280*720*2);    
  13.   printf("TK--------->>>resultyuyv is %d\n",resultyuyv);     
  14.   close(fdyuyv);    
  15. }  

8.关闭视频流

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ioctl(fd,VIDIOC_STREAMOFF,&type);    

二、修改

原来如下——

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ioctl(fd,VIDIOC_QBUF,&buf);   
  2. ioctl(fd,VIDIOC_STREAMON,&type);    
  3. ioctl(fd,VIDIOC_DQBUF,&buf);    

现在改为——

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ioctl(fd,VIDIOC_STREAMON,&type);  
  2. usleep(800000);  
  3. ioctl(fd,VIDIOC_QBUF,&buf);  
  4. ioctl(fd,VIDIOC_DQBUF,&buf);   

其实就是刚打开时的数据不能要!!!!!

三、工程实例

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. status_t V4LCameraAdapter::startPreview()  
  2. {  
  3.   ......  
  4. /* change by tankai 
  5.     nQueued = 0; 
  6.     for (int i = 0; i < mPreviewBufferCount; i++)  
  7.     { 
  8.         frame_count = -1; 
  9.         frame_buf = (void *)mPreviewBufs.keyAt(i); 
  10.  
  11.  
  12.         if((ret_c = getFrameRefCount(frame_buf,CameraFrame::PREVIEW_FRAME_SYNC))>=0) 
  13.             frame_count = ret_c; 
  14.  
  15.  
  16.         //if((ret_c = getFrameRefCount(frame_buf,CameraFrame::VIDEO_FRAME_SYNC))>=0) 
  17.         //    frame_count += ret_c; 
  18.   
  19.         CAMHAL_LOGDB("startPreview--buffer address:0x%x, refcount:%d",(uint32_t)frame_buf,frame_count); 
  20.         if(frame_count>0) 
  21.             continue; 
  22.         //mVideoInfo->buf.index = i; 
  23.         mVideoInfo->buf.index = mPreviewBufs.valueFor((uint32_t)frame_buf); 
  24.         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
  25.         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; 
  26. #ifdef AMLOGIC_USB_CAMERA_SUPPORT 
  27.         if(mIsDequeuedEIOError){ 
  28.             CAMHAL_LOGEA("DQBUF EIO error has occured!\n"); 
  29.             return -EINVAL; 
  30.         } 
  31. #endif 
  32.         ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf); 
  33.         if (ret < 0) { 
  34.             CAMHAL_LOGEA("VIDIOC_QBUF Failed"); 
  35.             return -EINVAL; 
  36.         } 
  37.         CAMHAL_LOGDB("startPreview --length=%d, index:%d", mVideoInfo->buf.length,mVideoInfo->buf.index); 
  38.         nQueued++; 
  39.     } 
  40. *///end tankai  
  41.     enum v4l2_buf_type bufType;  
  42.     if (!mVideoInfo->isStreaming)   
  43.     {  
  44.         bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  45. #ifdef AMLOGIC_CAMERA_NONBLOCK_SUPPORT  
  46.         gettimeofday( &previewTime1, NULL);  
  47. #endif  
  48.         ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType);  
  49.         if (ret < 0) {  
  50.             CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));  
  51.             return ret;  
  52.         }  
  53.   
  54.   
  55.         mVideoInfo->isStreaming = true;  
  56.     }  
  57.   
  58.   
  59.     if( mEnableContiFocus &&  
  60.         (CAM_FOCUS_MODE_AUTO != cur_focus_mode_for_conti) &&  
  61.         (CAM_FOCUS_MODE_INFINITY != cur_focus_mode_for_conti)){  
  62.     struct v4l2_control ctl;  
  63.     ctl.id = V4L2_CID_FOCUS_AUTO;  
  64.     ctl.value = CAM_FOCUS_MODE_CONTI_VID;  
  65.     if(ioctl(mCameraHandle, VIDIOC_S_CTRL, &ctl)<0){  
  66.         CAMHAL_LOGDA("failed to set CAM_FOCUS_MODE_CONTI_VID!\n");  
  67.     }  
  68.     cur_focus_mode_for_conti = CAM_FOCUS_MODE_CONTI_VID;  
  69.     }  
  70. //add by tankai  
  71.     usleep(800000);  
  72.     nQueued = 0;  
  73.     for (int i = 0; i < mPreviewBufferCount; i++)   
  74.     {  
  75.         frame_count = -1;  
  76.         frame_buf = (void *)mPreviewBufs.keyAt(i);  
  77.   
  78.   
  79.         if((ret_c = getFrameRefCount(frame_buf,CameraFrame::PREVIEW_FRAME_SYNC))>=0)  
  80.             frame_count = ret_c;  
  81.   
  82.   
  83.         //if((ret_c = getFrameRefCount(frame_buf,CameraFrame::VIDEO_FRAME_SYNC))>=0)  
  84.         //    frame_count += ret_c;  
  85.    
  86.         CAMHAL_LOGDB("startPreview--buffer address:0x%x, refcount:%d",(uint32_t)frame_buf,frame_count);  
  87.         if(frame_count>0)  
  88.             continue;  
  89.         //mVideoInfo->buf.index = i;  
  90.         mVideoInfo->buf.index = mPreviewBufs.valueFor((uint32_t)frame_buf);  
  91.         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  92.         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;  
  93. #ifdef AMLOGIC_USB_CAMERA_SUPPORT  
  94.         if(mIsDequeuedEIOError){  
  95.             CAMHAL_LOGEA("DQBUF EIO error has occured!\n");  
  96.             return -EINVAL;  
  97.         }  
  98. #endif  
  99.         ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);  
  100.         if (ret < 0) {  
  101.             CAMHAL_LOGEA("VIDIOC_QBUF Failed");  
  102.             return -EINVAL;  
  103.         }  
  104.         CAMHAL_LOGDB("startPreview --length=%d, index:%d", mVideoInfo->buf.length,mVideoInfo->buf.index);  
  105.         nQueued++;  
  106.     }  
  107. //end tankai  
  108.   ......  
  109. }  

补充:

看看preview线程:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int V4LCameraAdapter::previewThread()  
  2. {  
  3.   uint8_t* ptr = (uint8_t*) mPreviewBufs.keyAt(mPreviewIdxs.valueFor(index)); //gralloc显存  
  4.   if(mVideoInfo->buf.length != mVideoInfo->buf.bytesused){  
  5.     fillThisBuffer( ptr, CameraFrame::PREVIEW_FRAME_SYNC);  
  6.     /* 
  7.     status_t V4LCameraAdapter::fillThisBuffer(void* frameBuf, CameraFrame::FrameType frameType) 
  8.     { 
  9.       ret = ioctl(mCameraHandle, VIDIOC_QBUF, &hbuf_query);//入队列 
  10.       nQueued++; 
  11.     } 
  12.     */  
  13.   }  
  14.   char *fp = this->GetFrame(index);  
  15.   /* 
  16.   char * V4LCameraAdapter::GetFrame(int &index) 
  17.   { 
  18.     ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf); //出队列 
  19.   } 
  20.   */    
  21.   uint8_t* src = (uint8_t*) fp; //Camera原始数据  
  22.   private_handle_t* gralloc_hnd = (private_handle_t*)ptr;  
  23.   dest = (uint8_t*)gralloc_hnd->base;  
  24.   if(DEFAULT_PREVIEW_PIXEL_FORMAT == V4L2_PIX_FMT_YUYV){ // 422I  
  25.     frame.mLength = width*height*2;  
  26.     memcpy(dest,src,frame.mLength);  
  27.   }   


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕妇腰扭了很痛怎么办 怀孕了腰扭了疼怎么办 小龙芭比扭腰机开机没有声音怎么办 高中生训练数学计算的准确性怎么办 跑步累了跑不动了怎么办 一跑步就岔气了怎么办 婴儿关节折邹发红怎么办? 打了借条人跑了怎么办 吃凉的胃不舒服怎么办 跑步机带子跑偏怎么办 在跑步机上摔倒怎么办 弯道以后就是直线行驶怎么办 跑步机的声音大怎么办 科二一直考不过怎么办 考科目三太紧张怎么办 科目三太紧张了怎么办 跑步慢怎么办怎样跑快 铣床铣得不直怎么办 考试的时候检测仪响怎么办 吸入腐蚀性气体导致嗓子疼怎么办 孕妇已做c13检查怎么办 静电除尘器绝缘子箱温度低怎么办 高中三角函数计算总算不对怎么办 江苏高考物理考d怎么办 高二化学学不好怎么办 中考最后一次月考下滑怎么办 物联网卡网速慢怎么办 机械表长时间不带不走了怎么办 高中档案有涂改痕迹怎么办 大学平时成绩为0怎么办 电大英语考试成绩取消了怎么办 网贷评分不足要怎么办 学业水平广东1c怎么办 绣花机速度太慢怎么办 娃脖子有点烂了怎么办 7月省内流量套餐怎么办 qq手游授权失败怎么办 钉钉不够6人创建怎么办 钉钉 不够6个人怎么办 plsql删错了表怎么办 吊兰长出来的茎怎么办