1 Star 0 Fork 0

aspirefhaha / vlinfo

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
Clone or download
v4l2_test.c 8.76 KB
Copy Edit Web IDE Raw Blame History
aspirefhaha authored 2016-09-08 04:48 . nothing chang size
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <asm/types.h>
#include <linux/videodev2.h>
//#include <jpeglib.h>
#define CLEAR(x) memset (&(x), 0, sizeof (x))
struct buffer {
void * start;
size_t length;
};
//static char * dev_name = "/dev/video0";//摄像头设备名
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
FILE *file_fd;
static unsigned long file_length;
static unsigned char *file_name;
//////////////////////////////////////////////////////
//获取一帧数据
//////////////////////////////////////////////////////
static int read_frame (void)
{
struct v4l2_buffer buf;
unsigned int i;
static int file_suf = 0;
fprintf(stderr,"read_frame for %d times\n",file_suf);
char tmpfilename[128]={0};
sprintf(tmpfilename,"/data/yuyv/capfile%03d.yuyv",file_suf++);//图片文件名
file_fd = fopen(tmpfilename, "w");//图片文件名
if(file_fd ==NULL){
fprintf(stderr,"open file %s failed \n",tmpfilename);
return -1;
}
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl (fd, VIDIOC_DQBUF, &buf); //出列采集的帧缓冲
assert (buf.index < n_buffers);
fprintf (stderr,"buf.index dq is %d,\n",buf.index);
fwrite(buffers[buf.index].start, buf.bytesused, 1, file_fd); //将其写入文件中
fclose(file_fd);
ioctl (fd, VIDIOC_QBUF, &buf); //再将其入列
return 0;
}
int main (int argc,char ** argv)
{
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_fmtdesc efmt;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_dbg_chip_ident chip_ident;
char * devname = "/dev/video0";
unsigned int i;
enum v4l2_buf_type type;
v4l2_std_id vstd;
int tmpret = 0;
int ispal=0,isntsc =0;
int ismjpg = 0;
int isyuyv = 0;
int isrgbp = 0;
if(argc>=2)
devname = argv[1];
if(NULL == opendir("/data/yuyv")){
mkdir("/data/yuyv",0755) ;
}
fd = open (devname, O_RDWR /* required */ | O_NONBLOCK, 0);//打开设备
ioctl (fd, VIDIOC_QUERYCAP, &cap);//获取摄像头参数
fprintf(stderr,"Driver Name:%s\nCard Name:%s\nBus info:%s\nDriver Version:%u.%u.%u\n",cap.driver,cap.card,cap.bus_info,
(cap.version>>16)&0XFF, (cap.version>>8)&0XFF,cap.version&0XFF);
fprintf(stderr,"Capibility:%x\n",cap.capabilities);
if((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)==0){
fprintf(stderr,"unsupport video capture\n");
return -1;
}
if(0==(cap.capabilities & V4L2_CAP_STREAMING)){
fprintf(stderr,"unsupport streaming io\n");
return -1;
}
fprintf(stderr,"start g chip\n");
tmpret = ioctl(fd,VIDIOC_DBG_G_CHIP_IDENT,&chip_ident);
if(tmpret <0){
fprintf(stderr,"ioctl VIDIOC_DBG_G_CHIP_IDENT failed %d\n",errno);
//return -1;
}
fprintf(stderr,"g chip ret %d\n",tmpret);
//return -1;
fprintf(stderr,"start query std:");
do{
tmpret = ioctl(fd, VIDIOC_QUERYSTD, &vstd);
}while(tmpret == -1 && errno == EAGAIN);
fprintf(stderr,"ret %d vstd %llx\n",tmpret,vstd);
if(vstd & V4L2_STD_PAL){
fprintf(stderr,"support PAL\n");
ispal = 1;
}
if(vstd & V4L2_STD_NTSC){
fprintf(stderr,"support NTSC\n");
isntsc = 1;
}
if(isntsc == 0 && ispal ==0){
fprintf(stderr,"!!!!!!!!!!!!!!!unsupport PAL and NTSC both!!!!!\n");
}
CLEAR(efmt);
efmt.index = 0;
efmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while((tmpret = ioctl(fd,VIDIOC_ENUM_FMT,&efmt) )== 0){
fprintf(stderr,"index %d :\n\tpixelformat:'%c%c%c%c',description = '%s'\n",
efmt.index,efmt.pixelformat&0xff,(efmt.pixelformat>>8)&0xff,
(efmt.pixelformat>>16)&0xff,(efmt.pixelformat>>24)&0xff,
efmt.description);
if(memcmp((void *)&efmt.pixelformat,"MJPG",4)==0){
ismjpg = 1;
}
if(memcmp((void *)&efmt.pixelformat,"YUYV",4)==0){
isyuyv = 1;
}
if(memcmp((void *)&efmt.pixelformat,"RGBP",4)==0){
isrgbp = 1;
}
efmt.index++;
}
CLEAR(cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
tmpret = ioctl(fd,VIDIOC_CROPCAP,&cropcap);
if( -1 == tmpret){
fprintf(stderr,"call cropcap failed!\n");
return -1;
}
fprintf(stderr," cropcap bound:%d %d %d %d\ndefrect:%d %d %d %d\nfract %d %d\n",
cropcap.bounds.left,cropcap.bounds.top,cropcap.bounds.width,cropcap.bounds.height,
cropcap.defrect.left,cropcap.defrect.top,cropcap.defrect.width,cropcap.defrect.height,
cropcap.pixelaspect.numerator,cropcap.pixelaspect.denominator);
CLEAR (fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = cropcap.defrect.width;
if(isrgbp){
//fmt.fmt.pix.height = cropcap.defrect.height;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.width = 720;
}
else{
fmt.fmt.pix.height = 480;
}
//fmt.fmt.pix.pixelformat = isrgbp?V4L2_PIX_FMT_RGB565:V4L2_PIX_FMT_YUYV;
//fmt.fmt.pix.pixelformat = isrgbp?V4L2_PIX_FMT_RGB565:V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
//fmt.fmt.pix.field = V4L2_FIELD_NONE;
tmpret = ioctl (fd, VIDIOC_S_FMT, &fmt); //设置图像格式
if(tmpret == -1){
struct _tryfmts {
int height;
int width;
int filed;
unsigned fmt
};
struct _tryfmts tfmts[]={{240,320,V4L2_FIELD_INTERLACED,V4L2_PIX_FMT_RGB565},
{320,480,V4L2_FIELD_INTERLACED,V4L2_PIX_FMT_YUYV}};
fprintf(stderr,"set fmt ret %d failed,return format field 0x%x ,width %d height %d,pixelformat 0x%x\n",
tmpret,fmt.fmt.pix.field,fmt.fmt.pix.width , fmt.fmt.pix.height,fmt.fmt.pix.pixelformat);
return -1;
}
else{
fprintf(stderr,"set fmt ret %d,bytes per line %d ,height %d\n",tmpret,fmt.fmt.pix.bytesperline,
fmt.fmt.pix.height);
}
//return 0;
file_length = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; //计算图片大小
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
tmpret = ioctl (fd, VIDIOC_REQBUFS, &req); //申请缓冲,count是申请的数量
fprintf(stderr,"REQBUFS ret %d count %d\n",tmpret,req.count);
if (req.count < 2)
fprintf(stderr,"Insufficient buffer memory\n");
buffers = calloc (req.count, sizeof (*buffers));//内存中建立对应空间
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
{
struct v4l2_buffer buf; //驱动中的一帧
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf)){ //映射用户空间
printf ("VIDIOC_QUERYBUF error\n");
break;
}
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap (NULL /* start anywhere */, //通过mmap建立映射关系
buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
printf ("mmap failed\n");
}
if(n_buffers != req.count){
fprintf(stderr,"mmap all buffer failed at %d\n",n_buffers);
free(buffers);
return -1;
}
for (i = 0; i < n_buffers; ++i)
{
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == ioctl (fd, VIDIOC_QBUF, &buf)){//申请到的缓冲进入列队
printf ("VIDIOC_QBUF failed\n");
return -1;
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl (fd, VIDIOC_STREAMON, &type)){ //开始捕捉图像数据
printf ("VIDIOC_STREAMON failed\n");
return -1;
}
for (i = 0; i < 10; i++) //这一段涉及到异步IO
{
fd_set fds;
struct timeval tv;
int r;
FD_ZERO (&fds);//将指定的文件描述符集清空
FD_SET (fd, &fds);//在文件描述符集合中增加一个新的文件描述符
/* Timeout. */
tv.tv_sec = 5 ;
tv.tv_usec = 0;
r = select (fd + 1, &fds, NULL, NULL, &tv);//判断是否可读(即摄像头是否准备好),tv是定时
if (-1 == r) {
if (EINTR == errno)
continue;
printf ("select err\n");
}
if (0 == r) {
fprintf (stderr, "select timeout\n");
exit (EXIT_FAILURE);
}
if (read_frame ())//如果可读,执行read_frame ()函数,并跳出循环
break;
}
unmap:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap (buffers[i].start, buffers[i].length))
printf ("munmap error");
close (fd);
//fclose (file_fd);
exit (EXIT_SUCCESS);
return 0;
}

Comment ( 0 )

Sign in for post a comment

1
https://gitee.com/fhaha/vlinfo.git
git@gitee.com:fhaha/vlinfo.git
fhaha
vlinfo
vlinfo
master

Search