#include "v4l2cap.h"
#include <iostream>
#include <sys/time.h>
using namespace std;
v4l2cap::v4l2cap()
{
vd_info = NULL;
}
v4l2cap::~v4l2cap()
{
}
bool v4l2cap::v4l2cap_open(char *device)
{
vd_info->camfd = open(device, O_RDWR | O_NONBLOCK, 0);
if (vd_info->camfd < 0)
{
cout<<"can not open the device:"<<device<<endl;
return false;
}else
{
return true;
}
}
void v4l2cap::v4l2cap_close()
{
uint16 i = 0;
if (vd_info->is_streaming) /**< stop if it is still capturing */
v4l2cap_off();
if (vd_info->frame_buffer)
free(vd_info->frame_buffer);
if (vd_info->tmp_buffer)
free(vd_info->tmp_buffer);
vd_info->frame_buffer = NULL;
/* it is a good thing to unmap! */
for (i = 0; i < NB_BUFFER; i++)
{
if (-1 == munmap(vd_info->mem[i], vd_info->buf.length))
cout<<"munmap failed"<<endl;
}
close(vd_info->camfd);
}
void v4l2cap::v4l2cap_on()
{
vd_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl(vd_info->camfd, VIDIOC_STREAMON, &vd_info->type))
cout<<"unable to start capture"<<endl;
vd_info->is_streaming = 1;
}
void v4l2cap::v4l2cap_off()
{
vd_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl(vd_info->camfd, VIDIOC_STREAMOFF, &vd_info->type))
cout<<"unable to stop capture"<<endl;
vd_info->is_streaming = 0;
}
void v4l2cap::v4l2cap_get_property()
{
memset(&vd_info->cap, 0, sizeof(struct v4l2_capability));
if ( -1 == ioctl(vd_info->camfd, VIDIOC_QUERYCAP,&(vd_info->cap)))
cout<<"VIDIOC_QUERYCAP failed"<<endl;
cout<<"driver:"<<vd_info->cap.driver<<endl;
cout<<"card:"<<vd_info->cap.card<<endl;
cout<<"bus_info:"<<vd_info->cap.bus_info<<endl;
cout<<"version:"<<vd_info->cap.version<<endl;
/**
* 0x1:CAPTURE
* 0x04000000:STREAMING
*/
cout<<"capability:"<<vd_info->cap.capabilities<<endl;
cout<<"query capability success"<<endl;
}
void v4l2cap::v4l2cap_get_format()
{
memset(&vd_info->fmt,0,sizeof(struct v4l2_format));
vd_info->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl(vd_info->camfd, VIDIOC_G_FMT, &(vd_info->fmt)))
cout<<"can not get format"<<endl;
/**
* v4l2_pix_format has "pixelformat" or "pixelfmt"
* see vedeodev2.h get a correct one!!
* redflag width 2.6.28:pixelformat
* fc10 width 2.6.33: pixelfmt
* ??? glic???
*/
vd_info->format = vd_info->fmt.fmt.pix.pixelformat;
cout<<"format(num):"<<vd_info->format<<endl;
/**
* pixel fmt is 32 bit
* it is a four character code:abcd.dcba
* so it is easy to get the code for a interge
* see videodev2.h for more information
*/
char code[5];
int i=0;
for (i=0; i<4; i++)
code[i] = (vd_info->format & (0xff<<i*8)) >> i*8;
code[4] = 0;
cout<<"fomat(human readable):"<<code<<endl;
/* get more information here */
vd_info->width = vd_info->fmt.fmt.pix.width;
vd_info->height = vd_info->fmt.fmt.pix.height;
vd_info->field = (v4l2_field)vd_info->fmt.fmt.pix.field;
vd_info->bytes_per_line= vd_info->fmt.fmt.pix.bytesperline;
vd_info->size_image = vd_info->fmt.fmt.pix.sizeimage;
vd_info->color_space = (v4l2_colorspace)vd_info->fmt.fmt.pix.colorspace;
vd_info->priv = vd_info->fmt.fmt.pix.priv;
cout<<"width:"<<vd_info->width<<endl;
cout<<"height:"<<vd_info->height<<endl;
cout<<"field:"<<vd_info->field<<endl;
cout<<"bytesperline:"<<vd_info->bytes_per_line<<endl;
cout<<"sizeimage:"<<vd_info->size_image<<endl;
cout<<"colorspace:"<<vd_info->color_space<<endl;
cout<<"private field:"<<vd_info->priv<<endl;
cout<<"get fomat OK!"<<endl;
}
void v4l2cap::v4l2cap_set_format(int format, int width, int height)
{
memset(&vd_info->fmt,0,sizeof(struct v4l2_format));
vd_info->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vd_info->fmt.fmt.pix.width = width;
vd_info->fmt.fmt.pix.height = height;
vd_info->fmt.fmt.pix.pixelformat= format;
vd_info->fmt.fmt.pix.field = V4L2_FIELD_ANY;
if (-1 == ioctl(vd_info->camfd, VIDIOC_S_FMT, &(vd_info->fmt)))
cout<<"unable to set format"<<endl;
cout<<"set format success"<<endl;
}
bool v4l2cap::v4l2cap_init(char *device, int format, int width, int height)
{
int i;
/* initialize sth */
vd_info->format = format;
vd_info->width = width;
vd_info->height = height;
vd_info->is_quit = 1;
vd_info->frame_size_in = (vd_info->width * vd_info->height << 1);
switch (vd_info->format) /**< format will be also ok */
{
case V4L2_PIX_FMT_MJPEG:
vd_info->tmp_buffer =
(uint8 *)calloc(1, (size_t)vd_info->frame_size_in);
if (vd_info->tmp_buffer == NULL)
cout<<"unable alloc tmp_buffer"<<endl;
vd_info->frame_buffer =
(uint8 *)calloc(1, (size_t)vd_info->width * (vd_info->height+8) * 2);
if (vd_info->frame_buffer == NULL)
cout<<"unable alloc frame_buffer"<<endl;
break;
case V4L2_PIX_FMT_YUYV:
vd_info->frame_buffer =
(uint8 *)calloc(1,(size_t)vd_info->frame_size_in);
if (vd_info->frame_buffer == NULL)
cout<<"unable alloc frame_buffer"<<endl;
break;
default:
cout<<"Format Type Error!"<<endl;
return false;
}
/* open it */
vd_info->camfd = open(device, O_RDWR | O_NONBLOCK, 0);
if (vd_info->camfd < 0)
{
cout<<"can not open the device"<<endl;
return false;
}
if (-1 == ioctl(vd_info->camfd, VIDIOC_QUERYCAP, &vd_info->cap))
cout<<"query camera failed"<<endl;
if (0 == (vd_info->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
{
cout<<"video capture not supported"<<endl;
return false;
}
/* set format */
/**< it would be safe to use v4l2_format */
memset(&vd_info->fmt, 0, sizeof(struct v4l2_format));
vd_info->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vd_info->fmt.fmt.pix.width = width;
vd_info->fmt.fmt.pix.height = height;
vd_info->fmt.fmt.pix.field =V4L2_FIELD_ANY;
vd_info->fmt.fmt.pix.pixelformat = format;
if (-1 == ioctl(vd_info->camfd, VIDIOC_S_FMT, &vd_info->fmt))
cout<<"unable to set format"<<endl;
/*set the frame rate*/
struct v4l2_streamparm *parm = new struct v4l2_streamparm;
memset(parm,0,sizeof(struct v4l2_streamparm));
parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
// parm->parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
parm->parm.capture.timeperframe.denominator = 40 ;//时间间隔分母
parm->parm.capture.timeperframe.numerator = 1;//分子
if(-1 == ioctl(vd_info->camfd,VIDIOC_S_PARM,parm))
{
cout<<"Failed to set frame rate"<<endl;
return false;
}else
{
ioctl(vd_info->camfd, VIDIOC_G_PARM, parm);
int x = parm->parm.capture.timeperframe.denominator;
int y = parm->parm.capture.timeperframe.numerator;
int frame = y*1000/x;
cout<<"current frame rate is:"<<x<<" "<<y<<" "<<frame<<endl;
}
/* request buffers */
memset(&vd_info->rb, 0, sizeof(struct v4l2_requestbuffers));
vd_info->rb.count = NB_BUFFER; /**< 4 buffers */
vd_info->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vd_info->rb.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(vd_info->camfd, VIDIOC_REQBUFS, &vd_info->rb))
{
cout<<"unable to allocte buffers"<<endl;
return false;
}
/* map the buffers(4 buffer) */
for (i = 0; i < NB_BUFFER; i++)
{
memset(&vd_info->buf, 0, sizeof(struct v4l2_buffer));
vd_info->buf.index = i;
vd_info->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vd_info->buf.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(vd_info->camfd, VIDIOC_QUERYBUF, &vd_info->buf))
cout<<"unable to query buffer"<<endl;
/*debug_msg("length: %u offset