#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void)
{
//1.打开设备
int fd = open("/dev/video0", O_RDWR);
if(fd < 0)
{
perror("打开设备失败");
return -1;
}
//得到摄像头信息
struct v4l2_capability {
__u8 driver[16];
__u8 card[32];
__u8 bus_info[32];
__u32 version;
__u32 capabilities;
__u32 device_caps;
__u32 reserved[3];
}cap;
if((ioctl(fd,VIDIOC_QUERYCAP,&cap))==-1){
puts("ioctl error");
}
printf("%s\n",cap.driver);
printf("%s\n",cap.card);
printf("%x\n",cap.capabilities);
//查询支持的视频格式
// struct v4l2_fmtdesc fmtdesc;
struct v4l2_fmtdesc {
__u32 index; /* Format number */
__u32 type; /* enum v4l2_buf_type */
__u32 flags;
__u8 description[32]; /* Description string */
__u32 pixelformat; /* Format fourcc */
__u32 mbus_code; /* Media bus code */
__u32 reserved[3];
}fmtdesc;
fmtdesc.index=0;
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Support format:\n");
while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1) //查询摄像头支持格式
{
printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);
fmtdesc.index++;
}
//设置采集格式
/*720p格式,分辨率为1280×720p/60Hz,行频为45kHz 。*/
struct v4l2_format {
enum v4l2_buf_type {
V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
}type;
union {
// struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
__u8 raw_data[200]; /* user-defined */
struct v4l2_pix_format {
__u32 width;
__u32 height;
__u32 pixelformat;
__u32 field; /* enum v4l2_field */
__u32 bytesperline; /* for padding, zero if unused */
__u32 sizeimage;
__u32 colorspace; /* enum v4l2_colorspace */
__u32 priv; /* private data, depends on pixelformat */
__u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */
union {
/* enum v4l2_ycbcr_encoding */
__u32 ycbcr_enc;
/* enum v4l2_hsv_encoding */
__u32 hsv_enc;
};
__u32 quantization; /* enum v4l2_quantization */
__u32 xfer_func; /* enum v4l2_xfer_func */
}pix;
} fmt;
}vfmt;
// memset(&vfmt,0,sizeof(vfmt));
vfmt.type=1;
vfmt.fmt.pix.width=1280; //720p=1280*720
vfmt.fmt.pix.height=720;
vfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG; //通过ioctl(VIDIOC_ENUM_FMT)查询摄像头支持的格式
int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);
if(ret < 0)
{
perror("设置格式失败");
}
//4.申请内核缓冲区个数
// struct v4l2_requestbuffers reqbuffer;
struct v4l2_requestbuffers {
__u32 count;
__u32 type; /* enum v4l2_buf_type */
__u32 memory; /* enum v4l2_memory */
__u32 capabilities;
__u32 reserved[1];
}reqbuffer;
reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuffer.count = 1; //申请4个缓冲区
reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式
ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);
if(ret < 0)
{
perror("申请队列空间失败");
}
//设置 设备映射到内存的选项
struct v4l2_buffer {
__u32 index;
__u32 type;
__u32 bytesused;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
/* memory location */
__u32 memory;
union {
__u32 offset;
unsigned long userptr;
struct v4l2_plane *planes;
__s32 fd;
} m;
__u32 length;
__u32 reserved2;
union {
__s32 request_fd;
__u32 reserved;
};
}mapbuffer;
unsigned char *mptr;
unsigned int size;
mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mapbuffer.index = 0;
ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查询缓冲区状态
if(ret < 0)
{
perror("查询内核空间队列失败");
}
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_STREAMON, &type); //启动流
if(ret < 0)
{
perror("开启失败");
}
mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, mapbuffer.m.offset); //设备映射到缓冲区内存
size=mapbuffer.length;
ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区数据放入读队列中
if(ret < 0)
{
perror("放回失败");
}
ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer); //读当前队列缓冲区的数据
if(ret < 0)
{
perror("提取数据失败");
}
FILE *file=fopen("my.jpg", "w+");
fwrite(mptr,mapbuffer.length, 1, file);
fclose(file);
ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区放回队列中,准备存数据
if(ret < 0)
{
perror("放回队列失败");
}
ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
munmap(mptr, size);
close(fd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void){
int fd = open("/dev/video0", O_RDWR);
if(fd < 0)
{
perror("打开设备失败");
return -1;
}
struct v4l2_format vfmt;
vfmt.type=1;
vfmt.fmt.pix.width=1680;
vfmt.fmt.pix.height=1080;
vfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG;
int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);
if(ret < 0)
{
perror("设置格式失败");
}
struct v4l2_requestbuffers reqbuffer;
reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuffer.count = 1;
reqbuffer.memory = V4L2_MEMORY_MMAP ;
ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);
if(ret < 0)
{
perror("申请队列空间失败");
}
struct v4l2_buffer mapbuffer;
unsigned char *mptr;
unsigned int size;
mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mapbuffer.index = 0;
ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查询缓冲区状态
if(ret < 0)
{
perror("查询内核空间队列失败");
}
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_STREAMON, &type); //启动流
if(ret < 0)
{
perror("开启失败");
}
mptr= (unsigned char *)mmap(NULL, mapbuffer.length, PROT_READ|PROT_WRITE,
MAP_SHARED, fd,0); //设备映射到缓冲区内存
size=mapbuffer.length;
ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区数据放入读队列中
if(ret < 0)
{
perror("放回失败");
}
ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer); //读当前队列缓冲区的数据
if(ret < 0)
{
perror("提取数据失败");
}
FILE *file=fopen("my.jpg", "w+");
fwrite(mptr,mapbuffer.length, 1, file);
fclose(file);
ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
munmap(mptr, size);
close(fd);
return 0;
}
连续批量生成照片文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void)
{
//1.打开设备
int fd = open("/dev/video0", O_RDWR);
if(fd < 0)
{
perror("打开设备失败");
return -1;
}
//得到摄像头信息
struct v4l2_capability {
__u8 driver[16];
__u8 card[32];
__u8 bus_info[32];
__u32 version;
__u32 capabilities;
__u32 device_caps;
__u32 reserved[3];
}cap;
if((ioctl(fd,VIDIOC_QUERYCAP,&cap))==-1){
puts("ioctl error");
}
printf("%s\n",cap.driver);
printf("%s\n",cap.card);
printf("%x\n",cap.capabilities);
//查询支持的视频格式
// struct v4l2_fmtdesc fmtdesc;
struct v4l2_fmtdesc {
__u32 index; /* Format number */
__u32 type; /* enum v4l2_buf_type */
__u32 flags;
__u8 description[32]; /* Description string */
__u32 pixelformat; /* Format fourcc */
__u32 mbus_code; /* Media bus code */
__u32 reserved[3];
}fmtdesc;
fmtdesc.index=0;
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Support format:\n");
while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1) //查询摄像头支持格式
{
printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);
fmtdesc.index++;
}
//设置采集格式
/*720p格式,分辨率为1280×720p/60Hz,行频为45kHz 。*/
struct v4l2_format {
enum v4l2_buf_type {
V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
}type;
union {
// struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
__u8 raw_data[200]; /* user-defined */
struct v4l2_pix_format {
__u32 width;
__u32 height;
__u32 pixelformat;
__u32 field; /* enum v4l2_field */
__u32 bytesperline; /* for padding, zero if unused */
__u32 sizeimage;
__u32 colorspace; /* enum v4l2_colorspace */
__u32 priv; /* private data, depends on pixelformat */
__u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */
union {
/* enum v4l2_ycbcr_encoding */
__u32 ycbcr_enc;
/* enum v4l2_hsv_encoding */
__u32 hsv_enc;
};
__u32 quantization; /* enum v4l2_quantization */
__u32 xfer_func; /* enum v4l2_xfer_func */
}pix;
} fmt;
}vfmt;
// memset(&vfmt,0,sizeof(vfmt));
vfmt.type=1;
vfmt.fmt.pix.width=1280; //720p=1280*720
vfmt.fmt.pix.height=720;
vfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG; //通过ioctl(VIDIOC_ENUM_FMT)查询摄像头支持的格式
int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);
if(ret < 0)
{
perror("设置格式失败");
}
//4.申请内核缓冲区个数
// struct v4l2_requestbuffers reqbuffer;
struct v4l2_requestbuffers {
__u32 count;
__u32 type; /* enum v4l2_buf_type */
__u32 memory; /* enum v4l2_memory */
__u32 capabilities;
__u32 reserved[1];
}reqbuffer;
reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuffer.count = 1; //申请4个缓冲区
reqbuffer.memory = V4L2_MEMORY_MMAP ;//映射方式
ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);
if(ret < 0)
{
perror("申请队列空间失败");
}
//设置 设备映射到内存的选项
struct v4l2_buffer {
__u32 index;
__u32 type;
__u32 bytesused;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
/* memory location */
__u32 memory;
union {
__u32 offset;
unsigned long userptr;
struct v4l2_plane *planes;
__s32 fd;
} m;
__u32 length;
__u32 reserved2;
union {
__s32 request_fd;
__u32 reserved;
};
}mapbuffer;
mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mapbuffer.index = 0;
ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//查询缓冲区状态
if(ret < 0)
{
perror("查询内核空间队列失败");
}
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_STREAMON, &type); //启动流
if(ret < 0)
{
perror("开启失败");
}
unsigned char *mptr;
unsigned int size;
mptr= (unsigned char *)mmap(NULL,1280*720, PROT_READ|PROT_WRITE,
MAP_SHARED, fd,0); //设备映射到缓冲区内存
size=mapbuffer.length;
ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区数据放入读队列中
if(ret < 0)
{
perror("放回失败");
}
int t=0;
while(1){
ret = ioctl(fd, VIDIOC_DQBUF, &mapbuffer); //读当前队列缓冲区的数据
if(ret < 0)
{
perror("提取数据失败");
}
char wj[4];
sprintf(wj,"%d",t); //int-->char
FILE *file=fopen(wj,"w+");
fwrite(mptr,1280*720, 1, file);
fclose(file);
ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //把缓冲区放回队列中,准备存数据
if(ret < 0)
{
perror("放回队列失败");
}
t++;
sleep(1);
}
ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
munmap(mptr, size);
close(fd);
return 0;
}
ffmpeg -f image2 -i %d output.mp4
图片生成视频