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

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

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

1.查询驱动功能

  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.获取当前驱动支持的视频格式

  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.设置当前驱动的频捕获格式

  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个)并转换成物理地址,将物理地址映射到用户空间

  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.把数据放入缓存队列

  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.开启视频流

  1. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
  2. ioctl(fd,VIDIOC_STREAMON,&type);   
7.把数据从缓存队列中读取出来
  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.关闭视频流

  1. ioctl(fd,VIDIOC_STREAMOFF,&type);    

二、修改

原来如下——

  1. ioctl(fd,VIDIOC_QBUF,&buf);   
  2. ioctl(fd,VIDIOC_STREAMON,&type);    
  3. ioctl(fd,VIDIOC_DQBUF,&buf);    

现在改为——

  1. ioctl(fd,VIDIOC_STREAMON,&type);  
  2. usleep(800000);  
  3. ioctl(fd,VIDIOC_QBUF,&buf);  
  4. ioctl(fd,VIDIOC_DQBUF,&buf);   

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

三、工程实例

  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线程:

  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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值