1、Video4linux下视频编程的流程
(1)打开视频设备:
(2) 读取设备信息
(3)更改设备当前设置(没必要的话可以不做)
(4)进行视频采集,两种方法:
a.内存映射
b.直接从设备读取
(5)对采集的视频进行处理
(6)关闭视频设备。
2、为程序定义的数据结构
- typedef struct v4l_struct
- {
- int fd;
- struct video_capability capability;
- struct video_channel channel[4];
- struct video_picture picture;
- struct video_window window;
- struct video_capture capture;
- struct video_buffer buffer;
- struct video_mmap mmap;
- struct video_mbuf mbuf;
- unsigned char *map;
- int frame;
- int framestat[2];
- }vd;
typedef struct v4l_struct
{
int fd;
struct video_capability capability;
struct video_channel channel[4];
struct video_picture picture;
struct video_window window;
struct video_capture capture;
struct video_buffer buffer;
struct video_mmap mmap;
struct video_mbuf mbuf;
unsigned char *map;
int frame;
int framestat[2];
}vd;
3、Video4linux支持的数据结构及其用途
- struct video_capability
- {
- char name[32];
- int type;
- int channels; /* Num channels */
- int audios; /* Num audio devices */
- int maxwidth; /* Supported width */
- int maxheight; /* And height */
- int minwidth; /* Supported width */
- int minheight; /* And height */
- };
- struct video_channel
- {
- int channel;
- char name[32];
- int tuners;
- __u32 flags;
- #define VIDEO_VC_TUNER 1 /* Channel has a tuner */
- #define VIDEO_VC_AUDIO 2 /* Channel has audio */
- __u16 type;
- #define VIDEO_TYPE_TV 1
- #define VIDEO_TYPE_CAMERA 2
- __u16 norm; /* Norm set by channel */
- };
- struct video_picture
- {
- __u16 brightness;
- __u16 hue;
- __u16 colour;
- __u16 contrast;
- __u16 whiteness; /* Black and white only */
- __u16 depth; /* Capture depth */
- __u16 palette; /* Palette in use */
- #define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
- #define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
- #define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
- #define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
- #define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
- #define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
- #define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
- #define VIDEO_PALETTE_YUYV 8
- #define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
- #define VIDEO_PALETTE_YUV420 10
- #define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
- #define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
- #define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
- #define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
- #define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
- #define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
- #define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
- #define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
- };
- struct video_window
- {
- __u32 x,y; /* Position of window */
- __u32 width,height; /* Its size */
- __u32 chromakey;
- __u32 flags;
- struct video_clip *clips; /* Set only */
- int clipcount;
- #define VIDEO_WINDOW_INTERLACE 1
- #define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */
- #define VIDEO_CLIP_BITMAP -1
- /* bitmap is 1024x625, a '1' bit represents a clipped pixel */
- #define VIDEO_CLIPMAP_SIZE (128 * 625)
- };
- struct video_capture
- {
- __u32 x,y; /* Offsets into image */
- __u32 width, height; /* Area to capture */
- __u16 decimation; /* Decimation divider */
- __u16 flags; /* Flags for capture */
- #define VIDEO_CAPTURE_ODD 0 /* Temporal */
- #define VIDEO_CAPTURE_EVEN 1
- };
- struct video_buffer
- {
- void *base;
- int height,width;
- int depth;
- int bytesperline;
- };
- struct video_mmap
- {
- unsigned int frame; /* Frame (0 - n) for double buffer */
- int height,width;
- unsigned int format; /* should be VIDEO_PALETTE_* */
- };
- #define VIDEO_MAX_FRAME 32
- struct video_mbuf
- {
- int size; /* Total memory to map */
- int frames; /* Frames */
- int offsets[VIDEO_MAX_FRAME];
- };
struct video_capability
{
char name[32];
int type;
int channels; /* Num channels */
int audios; /* Num audio devices */
int maxwidth; /* Supported width */
int maxheight; /* And height */
int minwidth; /* Supported width */
int minheight; /* And height */
};
struct video_channel
{
int channel;
char name[32];
int tuners;
__u32 flags;
#define VIDEO_VC_TUNER 1 /* Channel has a tuner */
#define VIDEO_VC_AUDIO 2 /* Channel has audio */
__u16 type;
#define VIDEO_TYPE_TV 1
#define VIDEO_TYPE_CAMERA 2
__u16 norm; /* Norm set by channel */
};
struct video_picture
{
__u16 brightness;
__u16 hue;
__u16 colour;
__u16 contrast;
__u16 whiteness; /* Black and white only */
__u16 depth; /* Capture depth */
__u16 palette; /* Palette in use */
#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
#define VIDEO_PALETTE_YUYV 8
#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
#define VIDEO_PALETTE_YUV420 10
#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
};
struct video_window
{
__u32 x,y; /* Position of window */
__u32 width,height; /* Its size */
__u32 chromakey;
__u32 flags;
struct video_clip *clips; /* Set only */
int clipcount;
#define VIDEO_WINDOW_INTERLACE 1
#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */
#define VIDEO_CLIP_BITMAP -1
/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
#define VIDEO_CLIPMAP_SIZE (128 * 625)
};
struct video_capture
{
__u32 x,y; /* Offsets into image */
__u32 width, height; /* Area to capture */
__u16 decimation; /* Decimation divider */
__u16 flags; /* Flags for capture */
#define VIDEO_CAPTURE_ODD 0 /* Temporal */
#define VIDEO_CAPTURE_EVEN 1
};
struct video_buffer
{
void *base;
int height,width;
int depth;
int bytesperline;
};
struct video_mmap
{
unsigned int frame; /* Frame (0 - n) for double buffer */
int height,width;
unsigned int format; /* should be VIDEO_PALETTE_* */
};
#define VIDEO_MAX_FRAME 32
struct video_mbuf
{
int size; /* Total memory to map */
int frames; /* Frames */
int offsets[VIDEO_MAX_FRAME];
};
这些struct都来自videodev.h
4、安装libjpeg
官方网站:http://www.ijg.org/
下载地址:http://www.ijg.org/files/
5、使用v4l的摄像头采集jpeg图像的代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <linux/videodev.h>
- #include <jpeglib.h>
- #define WIDTH 320
- #define HEIGHT 240
- #define V4L_DEVICE "/dev/video0"
- int write_jpeg(char *filename,unsigned char *buf,int quality,int width, int height, int gray)
- {
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- FILE *fp;
- int i;
- unsigned char *line;
- int line_length;
- if (NULL == (fp = fopen(filename,"w")))
- {
- fprintf(stderr,"grab: can't open %s: %s\n", filename, strerror(errno));
- return -1;
- }
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_compress(&cinfo);
- jpeg_stdio_dest(&cinfo, fp);
- cinfo.image_width = width;
- cinfo.image_height = height;
- cinfo.input_components = gray ? 1: 3;
- cinfo.in_color_space = gray ? JCS_GRAYSCALE: JCS_RGB;
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, quality, TRUE);
- jpeg_start_compress(&cinfo, TRUE);
- line_length = gray ? width : width * 3;
- for (i = 0, line = buf; i < height; i++, line += line_length)
- jpeg_write_scanlines(&cinfo, &line, 1);
- jpeg_finish_compress(&(cinfo));
- jpeg_destroy_compress(&(cinfo));
- fclose(fp);
- return 0;
- }
- int main()
- {
- unsigned char* buf;
- int i,j;
- int fd;
- int re;
- struct video_capability vcap;
- struct video_channel vc;
- struct video_mbuf mbuf;
- struct video_mmap map;
- fd = open(V4L_DEVICE, O_RDWR);
- if(fd<=0)
- {
- perror("open");
- exit(1);
- }
- if(ioctl(fd, VIDIOCGCAP, &vcap)<0)
- {
- perror("VIDIOCGCAP");
- exit(1);
- }
- printf("Video Capture Device Name : %s\n",vcap.name);
- for(i=0;i<vcap.channels;i++)
- {
- vc.channel = i;
- if(ioctl(fd, VIDIOCGCHAN, &vc)<0)
- {
- perror("VIDIOCGCHAN");
- exit(1);
- }
- printf("Video Source (%d) Name : %s\n",i, vc.name);
- }
- vc.channel=0;
- if(ioctl(fd, VIDIOCSCHAN, &vc) < 0)
- {
- perror("VIDIOCSCHAN");
- exit(1);
- }
- if(ioctl(fd, VIDIOCGMBUF, &mbuf) < 0)
- {
- perror("VIDIOCGMBUF");
- exit(1);
- }
- buf=(unsigned char *)mmap(0,mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
- if((int)buf < 0)
- {
- perror("mmap");
- exit(1);
- }
- map.frame = 0;
- map.height = HEIGHT;
- map.width = WIDTH;
- map.format = VIDEO_PALETTE_RGB24;
- if(ioctl(fd, VIDIOCMCAPTURE, &map)<0)
- {
- perror("VIDIOCMCAPTURE");
- exit(1);
- }
- if(ioctl(fd, VIDIOCSYNC, &map.frame)<0)
- {
- perror("VIDIOCSYNC");
- exit(1);
- }
- if(-1==(write_jpeg("./pic001.jpeg",buf,75,WIDTH,HEIGHT,0)))
- {
- printf("write_jpeg error\n");
- exit(1);
- }
- munmap(buf,mbuf.size);
- close(fd);
- return 0;
- }
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/videodev.h>
#include <jpeglib.h>
#define WIDTH 320
#define HEIGHT 240
#define V4L_DEVICE "/dev/video0"
int write_jpeg(char *filename,unsigned char *buf,int quality,int width, int height, int gray)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *fp;
int i;
unsigned char *line;
int line_length;
if (NULL == (fp = fopen(filename,"w")))
{
fprintf(stderr,"grab: can't open %s: %s\n", filename, strerror(errno));
return -1;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fp);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = gray ? 1: 3;
cinfo.in_color_space = gray ? JCS_GRAYSCALE: JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
line_length = gray ? width : width * 3;
for (i = 0, line = buf; i < height; i++, line += line_length)
jpeg_write_scanlines(&cinfo, &line, 1);
jpeg_finish_compress(&(cinfo));
jpeg_destroy_compress(&(cinfo));
fclose(fp);
return 0;
}
int main()
{
unsigned char* buf;
int i,j;
int fd;
int re;
struct video_capability vcap;
struct video_channel vc;
struct video_mbuf mbuf;
struct video_mmap map;
fd = open(V4L_DEVICE, O_RDWR);
if(fd<=0)
{
perror("open");
exit(1);
}
if(ioctl(fd, VIDIOCGCAP, &vcap)<0)
{
perror("VIDIOCGCAP");
exit(1);
}
printf("Video Capture Device Name : %s\n",vcap.name);
for(i=0;i<vcap.channels;i++)
{
vc.channel = i;
if(ioctl(fd, VIDIOCGCHAN, &vc)<0)
{
perror("VIDIOCGCHAN");
exit(1);
}
printf("Video Source (%d) Name : %s\n",i, vc.name);
}
vc.channel=0;
if(ioctl(fd, VIDIOCSCHAN, &vc) < 0)
{
perror("VIDIOCSCHAN");
exit(1);
}
if(ioctl(fd, VIDIOCGMBUF, &mbuf) < 0)
{
perror("VIDIOCGMBUF");
exit(1);
}
buf=(unsigned char *)mmap(0,mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if((int)buf < 0)
{
perror("mmap");
exit(1);
}
map.frame = 0;
map.height = HEIGHT;
map.width = WIDTH;
map.format = VIDEO_PALETTE_RGB24;
if(ioctl(fd, VIDIOCMCAPTURE, &map)<0)
{
perror("VIDIOCMCAPTURE");
exit(1);
}
if(ioctl(fd, VIDIOCSYNC, &map.frame)<0)
{
perror("VIDIOCSYNC");
exit(1);
}
if(-1==(write_jpeg("./pic001.jpeg",buf,75,WIDTH,HEIGHT,0)))
{
printf("write_jpeg error\n");
exit(1);
}
munmap(buf,mbuf.size);
close(fd);
return 0;
}
v4l编程的详细介绍:http://blog.youkuaiyun.com/luxiaoxun/archive/2011/05/27/6450783.aspx