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

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

1.查询驱动功能

struct v4l2_capability cap;  
ioctl(fd,VIDIOC_QUERYCAP,&cap);  
printf("TK---------->>>>>Driver Name:%s\nCard Name:%s\nBus info:%s\n",cap.driver,cap.card,cap.bus_info);

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

struct v4l2_fmtdesc fmtdesc;  
fmtdesc.index = 0; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) != -1){  
  printf("TK-------->>>>>fmtdesc.description is %s\n",fmtdesc.description);  
  fmtdesc.index ++;  
}

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

struct v4l2_format fmt;  
memset(&fmt,0,sizeof(fmt));  
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
fmt.fmt.pix.width = 1280;  
fmt.fmt.pix.height = 720;  
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;  
fmt.fmt.pix.field       = V4L2_FIELD_NONE;//V4L2_FIELD_INTERLACED;  
fmt.fmt.pix.colorspace = 8;  
int fmtreslt = ioctl(fd,VIDIOC_S_FMT,&fmt);  
printf("TK--------_>>>>fmtreslt is %d\n",fmtreslt);  
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
//重新获取,看是否设置成功 
ioctl(fd,VIDIOC_G_FMT,&fmt);  
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个)并转换成物理地址,将物理地址映射到用户空间

struct v4l2_requestbuffers req;  
req.count = 4;  
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
req.memory = V4L2_MEMORY_MMAP;  
//分配内存
ioctl(fd,VIDIOC_REQBUFS,&req);  
struct buffer{  
  void *start;  
  unsigned int length;  
}*buffers;  
buffers = (struct buffer*)calloc (req.count, sizeof(*buffers));  
unsigned int n_buffers = 0;  
for(n_buffers = 0; n_buffers < req.count; ++n_buffers){  
  struct v4l2_buffer buf;  
  memset(&buf,0,sizeof(buf));  
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  buf.memory = V4L2_MEMORY_MMAP;  
  buf.index = n_buffers;  
  //转换成物理地址
  if(ioctl(fd,VIDIOC_QUERYBUF,&buf) == -1){  
    printf("TK---------_>>>>>>error\n");  
    close(fd);  
    exit(-1);  
  }  
  buffers[n_buffers].length = buf.length; 
  //映射到用户空间 
  buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);  
  if(MAP_FAILED == buffers[n_buffers].start){  
    printf("TK--------__>>>>>error 2\n");  
    close(fd);  
    exit(-1);  
  }  
}

5.把数据放入缓存队列

unsigned int i;  
enum v4l2_buf_type type;  
for(i = 0; i < 4; i++){  
  struct v4l2_buffer buf;  
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  buf.memory = V4L2_MEMORY_MMAP;  
  buf.index = i;  
  ioctl(fd,VIDIOC_QBUF,&buf);  
}

6.开启视频流

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
ioctl(fd,VIDIOC_STREAMON,&type); 
7.把数据从缓存队列中读取出来
unsigned int j;  
for(j = 0; j < 4; j++){  
  struct v4l2_buffer buf;  
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  buf.memory = V4L2_MEMORY_MMAP;  
  buf.index = 0;  
  ioctl(fd,VIDIOC_DQBUF,&buf);  
  char path[30];  
  snprintf(path,sizeof(path),"./v4l2test/720pmjpeg%d",buf.index);  
  int fdyuyv = open(path,O_WRONLY|O_CREAT,00700);  
  printf("TK--------->>>>fdyuyv is %d\n",fdyuyv);  
  int resultyuyv = write(fdyuyv,buffers[buf.index].start,1280*720*2);  
  printf("TK--------->>>resultyuyv is %d\n",resultyuyv);   
  close(fdyuyv);  
}

8.关闭视频流

ioctl(fd,VIDIOC_STREAMOFF,&type);  

二、修改

原来如下——

ioctl(fd,VIDIOC_QBUF,&buf); 
ioctl(fd,VIDIOC_STREAMON,&type);  
ioctl(fd,VIDIOC_DQBUF,&buf);  

现在改为——

ioctl(fd,VIDIOC_STREAMON,&type);
usleep(800000);
ioctl(fd,VIDIOC_QBUF,&buf);
ioctl(fd,VIDIOC_DQBUF,&buf); 

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

三、工程实例

status_t V4LCameraAdapter::startPreview()
{
  ......
/* change by tankai
    nQueued = 0;
    for (int i = 0; i < mPreviewBufferCount; i++) 
    {
        frame_count = -1;
        frame_buf = (void *)mPreviewBufs.keyAt(i);


        if((ret_c = getFrameRefCount(frame_buf,CameraFrame::PREVIEW_FRAME_SYNC))>=0)
            frame_count = ret_c;


        //if((ret_c = getFrameRefCount(frame_buf,CameraFrame::VIDEO_FRAME_SYNC))>=0)
        //    frame_count += ret_c;
 
        CAMHAL_LOGDB("startPreview--buffer address:0x%x, refcount:%d",(uint32_t)frame_buf,frame_count);
        if(frame_count>0)
            continue;
        //mVideoInfo->buf.index = i;
        mVideoInfo->buf.index = mPreviewBufs.valueFor((uint32_t)frame_buf);
        mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
#ifdef AMLOGIC_USB_CAMERA_SUPPORT
        if(mIsDequeuedEIOError){
            CAMHAL_LOGEA("DQBUF EIO error has occured!\n");
            return -EINVAL;
        }
#endif
        ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
        if (ret < 0) {
            CAMHAL_LOGEA("VIDIOC_QBUF Failed");
            return -EINVAL;
        }
        CAMHAL_LOGDB("startPreview --length=%d, index:%d", mVideoInfo->buf.length,mVideoInfo->buf.index);
        nQueued++;
    }
*///end tankai
    enum v4l2_buf_type bufType;
    if (!mVideoInfo->isStreaming) 
    {
        bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
#ifdef AMLOGIC_CAMERA_NONBLOCK_SUPPORT
        gettimeofday( &previewTime1, NULL);
#endif
        ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
        if (ret < 0) {
            CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));
            return ret;
        }


        mVideoInfo->isStreaming = true;
    }


    if( mEnableContiFocus &&
    	(CAM_FOCUS_MODE_AUTO != cur_focus_mode_for_conti) &&
    	(CAM_FOCUS_MODE_INFINITY != cur_focus_mode_for_conti)){
	struct v4l2_control ctl;
	ctl.id = V4L2_CID_FOCUS_AUTO;
	ctl.value = CAM_FOCUS_MODE_CONTI_VID;
	if(ioctl(mCameraHandle, VIDIOC_S_CTRL, &ctl)<0){
		CAMHAL_LOGDA("failed to set CAM_FOCUS_MODE_CONTI_VID!\n");
	}
	cur_focus_mode_for_conti = CAM_FOCUS_MODE_CONTI_VID;
    }
//add by tankai
    usleep(800000);
    nQueued = 0;
    for (int i = 0; i < mPreviewBufferCount; i++) 
    {
        frame_count = -1;
        frame_buf = (void *)mPreviewBufs.keyAt(i);


        if((ret_c = getFrameRefCount(frame_buf,CameraFrame::PREVIEW_FRAME_SYNC))>=0)
            frame_count = ret_c;


        //if((ret_c = getFrameRefCount(frame_buf,CameraFrame::VIDEO_FRAME_SYNC))>=0)
        //    frame_count += ret_c;
 
        CAMHAL_LOGDB("startPreview--buffer address:0x%x, refcount:%d",(uint32_t)frame_buf,frame_count);
        if(frame_count>0)
            continue;
        //mVideoInfo->buf.index = i;
        mVideoInfo->buf.index = mPreviewBufs.valueFor((uint32_t)frame_buf);
        mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
#ifdef AMLOGIC_USB_CAMERA_SUPPORT
        if(mIsDequeuedEIOError){
            CAMHAL_LOGEA("DQBUF EIO error has occured!\n");
            return -EINVAL;
        }
#endif
        ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
        if (ret < 0) {
            CAMHAL_LOGEA("VIDIOC_QBUF Failed");
            return -EINVAL;
        }
        CAMHAL_LOGDB("startPreview --length=%d, index:%d", mVideoInfo->buf.length,mVideoInfo->buf.index);
        nQueued++;
    }
//end tankai
  ......
}

补充:

看看preview线程:

int V4LCameraAdapter::previewThread()
{
  uint8_t* ptr = (uint8_t*) mPreviewBufs.keyAt(mPreviewIdxs.valueFor(index)); //gralloc显存
  if(mVideoInfo->buf.length != mVideoInfo->buf.bytesused){
    fillThisBuffer( ptr, CameraFrame::PREVIEW_FRAME_SYNC);
    /*
    status_t V4LCameraAdapter::fillThisBuffer(void* frameBuf, CameraFrame::FrameType frameType)
    {
      ret = ioctl(mCameraHandle, VIDIOC_QBUF, &hbuf_query);//入队列
      nQueued++;
    }
    */
  }
  char *fp = this->GetFrame(index);
  /*
  char * V4LCameraAdapter::GetFrame(int &index)
  {
    ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf); //出队列
  }
  */  
  uint8_t* src = (uint8_t*) fp; //Camera原始数据
  private_handle_t* gralloc_hnd = (private_handle_t*)ptr;
  dest = (uint8_t*)gralloc_hnd->base;
  if(DEFAULT_PREVIEW_PIXEL_FORMAT == V4L2_PIX_FMT_YUYV){ // 422I
    frame.mLength = width*height*2;
    memcpy(dest,src,frame.mLength);
  } 
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值