android 系统下v4l2调用camera,VIDIOC_REQBUFS总是不成功
最近在android下开放一个获取图片数据的camera程序,用到底层的v4l2调用,总是出现申请帧缓冲的错VIDIOC_REQBUFS调用返回是-1,不知道是哪的问题希望有大牛帮我看看,找出问题,谢谢!下面是我的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include<sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <asm/types.h>
#include<linux/videodev2.h>
#include "v4l2_capture.h"
int mFd=-1;
struct buffer *mBuffer;
int mBufferNr;
int mWidth;
int mHeight;
int mFormat=V4L2_PIX_FMT_YUV420;
int mFrameSize;
static const int V4L2_BUFFER_NR = 3;
int openDevice(const char *dev, int width, int height)
{
LOGV("begin openv4l2device\n");
struct v4l2_capability cap;
struct v4l2_format fmt;
if(mFd>0)
{
return -13;
}
mFd = open(dev,O_RDWR);
if(mFd<0)
{
LOGE("Error openv4l2de vice\n");
return -1;
}
LOGW("openv4l2device Successed:%d\n",mFd);
memset(&cap, 0, sizeof(cap));
if (ioctl(mFd,VIDIOC_QUERYCAP, &cap) < 0)
{
LOGE("E rror ioctl VIDIOC_QUERYCAP");
return -1;
}
LOGW("VIDIOC_QUERYCAP Successed\n");
if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)
{
LOGV("video capture not supported. 0x%X", cap.capabilities);
return -1;
}
if ((cap.capabilities & V4L2_CAP_STREAMING) == 0) {
LOGV("Capture device does not support streaming i/o");
return -1;
} // set device format
memset(&fmt, 0x0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
fmt.fmt.pix.pixelformat= mFormat;
fmt.fmt.pix.priv= 0;
fmt.fmt.pix.bytesperline =height;
fmt.fmt.pix.sizeimage = 0;
if(ioctl( mFd, VIDIOC_S_FMT, &fmt)<0)
{
LOGE("ErrorioctlDIOC _ S_FMT");
return -1;
}
LOGW("VIDIOC_S_FMT Successed\n");
mWidth =width;
mHeight =height;
mFrameSize= (width* height) << 1;
LOGV("end openv4l2device\n");
return mFd;
}
void closeDevice() {
LOGV("begin closeDevice\n");
stopStreaming();
termMmap();
if (mFd >= 0)
close(mFd);
LOGV("end closeDevice\n");
}
int setStreamParam(int framerate) {
LOGV("begin setStreamParam\n");
struct v4l2_streamparm parm;
int ret;
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if ((ret = ioctl(mFd, VIDIOC_G_PARM, &parm)) < 0)
{
LOGE("Error ioctl VIDIOC_G_PARM");
return ret;
}
parm.parm.capture.timeperframe.denominator = framerate;
parm.parm.capture.timeperframe.numerator = 1;
parm.parm.output.timeperframe.denominator = framerate;
parm.parm.output.timeperframe.numerator = 1;
if ((ret = ioctl(mFd, VIDIOC_S_PARM, &parm)) < 0)
LOGE("Error ioctl VIDIOC_S_PARM");
LOGV("end setStreamParam\n");
return ret;
}
int startStreaming() {
LOGV("begin startStreaming\n");
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int ret;
if ((ret = ioctl(mFd, VIDIOC_STREAMON, &type)) < 0)
LOGE("Error ioctl VIDIOC_STREAMON");
LOGW("VIDIOC_STREAMON sucessed\n");
LOGV("end startStreaming\n");
return ret;
}
int stopStreaming() {
LOGV("begin stopStreaming\n");
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int ret;
if ((ret = ioctl(mFd, VIDIOC_STREAMOFF, &type)) < 0)
LOGE("Error ioctl VIDIOC_STREAMOFF");
LOGW("VIDIOC_STREAMOFF sucessed\n");
LOGV("end stopStreaming\n");
return ret;
}
int grabStreamFrame(struct buffer *outBuffer) {
LOGV("begin grabStreamFrame\n");
struct v4l2_buffer buf;
int ret;
memset(&buf, 0x0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if ((ret = ioctl(mFd, VIDIOC_DQBUF, &buf)) < 0) {
LOGE("Error ioctl VIDIOC_DQBUF");
return ret;
} // copy data to output buffer
LOGV("VIDIOC_DQBUF sucessed\n");
outBuffer->length=mBuffer[buf.index].length;
memcpy(outBuffer->start, mBuffer[buf.index].start, mBuffer[buf.index].length);
if ((ret = ioctl(mFd, VIDIOC_QBUF, &buf)) < 0)
LOGE("Error ioctl VIDIOC_QBUF");
LOGW("VIDIOC_QBUF of get sucessed\n");
LOGV("end grabStreamFrame\n");
return ret;
}
int getFormat(int * width, int * height, int * format)
{
LOGV("begin getFormat\n");
struct v4l2_format fmt;
int ret;
memset(&fmt,0,sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if((ret = ioctl(mFd, VIDIOC_G_FMT,&fmt)) < 0) {
LOGE("Error ioctl VIDIOC_G_FMT\n");
return ret;
}
LOGW("VIDIOC_G_FMT sucessed\n");
* format = fmt.fmt.pix.pixelformat;
* width = fmt.fmt.pix.width;
* height = fmt.fmt.pix.height;
LOGV("end getFormat\n");
return ret;
}
int initMmap(){
LOGV("begin initMmap\n");
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
unsigned int i;
int out_length=-1;
int ret;
memset(&req, 0x0, sizeof(req));
req.count = V4L2_BUFFER_NR;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if ((ret = ioctl(mFd, VIDIOC_REQBUFS, &req)) < 0) {
LOGE("Error ioctl VIDIOC_REQBUFS\n");
return ret;
}
LOGW("VIDIOC_REQBUFS Seccussed\n");
mBuffer = (struct buffer *)calloc(req.count, sizeof(*mBuffer));
for (i = 0; i < req.count; i++) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if ((ret = ioctl(mFd, VIDIOC_QUERYBUF, &buf)) < 0) {
LOGE("Error ioctl VIDIOC_QUERYBUF");
return ret;
}
LOGW("VIDIOC_QUERYBUF Seccussed\n");
out_length=mBuffer[i].length = buf.length;
LOGW("mBuffer[%d].length\n",i,mBuffer[i].length);
mBuffer[i].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, mFd, buf.m.offset);
LOGW("mBuffer[%d].length=%d\n",i,mBuffer[i].length);
if (mBuffer[i].start == MAP_FAILED) {
LOGE("Error: Failed to map v4l2 device to memory");
return -1;
}
if ((ioctl(mFd, VIDIOC_QBUF, &buf)) < 0)
{
LOGE("Error ioctl VIDIOC_QBUF");
return -1;
}
LOGW("VIDIOC_QBUF Seccussed\n");
}
mBufferNr = req.count;
LOGW("mBufferNr = req.count%d\n",mBufferNr);
LOGV("end initMmap\n");
return out_length;
}
void termMmap(){
LOGV("begin termMmap\n");
mFd=-1;
if (!mBuffer)
return;
int i=0;
for (i = 0;i < mBufferNr;i++)
{
munmap(mBuffer[i].start, mBuffer[i].length);
}
free(mBuffer);
LOGV("end termMmap\n");
}