📄 v4l2video.c
字号:
/*head files:*/#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 <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>//////////////////////////////////////////declarations://state reset:#define CLEAR(x) memset(&(x),0,sizeof(x))//devices:#define V4L2_DEVICE "/dev/video0"
#define FBVID_DEVICE "/dev/fb/3"#define OUTPUTFILE "/mnt/gjf/vidrecord.uyvy"///////////////////////////////////////////////////////////////////////////////////////////#define SCREEN_BPP 16#define D1_WIDTH 352#define D1_HEIGHT 288#define D1_LINE_WIDTH (D1_WIDTH * SCREEN_BPP / 8)#define D1_FRAME_SIZE (D1_LINE_WIDTH * D1_HEIGHT)////////////////////////////////////////////////////////////////////////////////////////////typedef enum{ IO_METHOD_READ, IO_METHOD_MMAP, IO_METHOD_USERPTR}io_method;struct buffer{ void* start; size_t length;};static char* video_device=NULL;static char* output_device=NULL;static io_method io=IO_METHOD_MMAP;struct buffer* buffers=NULL;static unsigned int n_buffers=0;static int videofd = -1 ; //device discription for video device;static int outputfd = -1 ; //device discprition for output device; static int captureSize = 0 ; //picture sizestatic unsigned int imagewidth = 0 ; //image widthstatic unsigned int imageheight = 0 ; //image heightstatic unsigned int timelimit = 1 ; //capturing timestatic unsigned int totalframes = 0 ; //catpturing frames#define FRAME 0#define TIME 1static int flag = FRAME;////////////////////////////////////////////////////////typedef enum{YUYV=0,UYVY}imageType;static imageType format=YUYV;/////////////////////////////////////////////////////////command line:static const char short_options[]="d:pmruw:h:t:f:o:";static const struct option long_options[] ={ {"device",required_argument,NULL,'d'}, {"help",no_argument,NULL,'p'}, {"mmap",no_argument,NULL,'m'}, {"read",no_argument,NULL,'r'}, {"usrptr",no_argument,NULL,'u'}, {"width",required_argument,NULL,'w'}, {"height",required_argument,NULL,'h'}, {"time",required_argument,NULL,'t'}, {"frame",required_argument,NULL,'f'}, {"format",required_argument,NULL,'o'}, { 0 , 0 , 0 , 0 }};static void usage(FILE* fp,int argc,char **argv){ fprintf (fp,"Usage: %s [options]\n\n" "Options:\n" "-d | --device name Video device name [/dev/video]\n" "-p | --help Print this message\n" "-m | --mmap Use memory mapped buffers\n" "-r | --read Use read() calls\n" "-u | --userp Use application allocated buffers\n" "-w | --image width\n" "-h | --image height\n" "-t | --capture time\n" "-f | --number of frames\n" "-o | --image format\n" "", argv[0]);}void process_command(int argc,char **argv){ int index ; int next_option ; int f = -1; video_device = V4L2_DEVICE ; output_device = FBVID_DEVICE ; imagewidth = D1_WIDTH ; imageheight = D1_HEIGHT ; timelimit = 1 ; totalframes = 0 ; format = UYVY ; flag = FRAME ; do{ next_option = getopt_long(argc,argv,short_options,long_options,&index) ; switch(next_option) { case 'd' : video_device=optarg ; break; case 'p' : usage(stdout,argc,argv) ; exit(EXIT_FAILURE) ; case 'm': io = IO_METHOD_MMAP ; break ; case 'r': io = IO_METHOD_READ ; break ; case 'u': io = IO_METHOD_USERPTR ; break ; case 'w': imagewidth = atoi(optarg); break; case 'h': imageheight = atoi(optarg); break; case 't': flag = TIME; timelimit = atoi( optarg ) ; break; case 'f': flag = FRAME; totalframes = atoi( optarg ) ; break; case 'o': f = atoi(optarg); format = ( f >= YUYV && f <= UYVY )? f : UYVY; break; case -1: break ; default: usage(stdout,argc,argv) ; exit(EXIT_FAILURE) ; } }while(next_option!=-1);}///////////////////videoCapture:void open_device(){ struct stat st; if (-1 == stat (video_device, &st)) { fprintf (stderr, "Cannot identify ’%s’: %d, %s\n",video_device, errno, strerror (errno)); exit (EXIT_FAILURE); } if (!S_ISCHR (st.st_mode)) { fprintf (stderr, "%s is no device\n", video_device); exit (EXIT_FAILURE); } videofd = open (video_device, O_RDWR | O_NONBLOCK, 0); if (videofd == -1) { fprintf ( stderr, "Cannot open ’%s’: %d, %s\n", video_device , errno , strerror (errno) ); exit (EXIT_FAILURE); }}static void init_read(unsigned int bufSize) //directly read{ buffers = calloc (1, sizeof (*buffers)); if (!buffers) { fprintf (stderr, "Out of memory\n"); exit (EXIT_FAILURE); } buffers[0].length = bufSize ; buffers[0].start = malloc (bufSize); if (!buffers[0].start) { fprintf (stderr, "Out of memory\n"); exit (EXIT_FAILURE); }}static void init_mmap() //map the driver's buffer to application buffer{ struct v4l2_requestbuffers req; CLEAR (req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(videofd, VIDIOC_REQBUFS, &req) == -1) { //allocate buffer in the driver memory space if (EINVAL == errno) { fprintf (stderr, "%s does not support ""memory mapping\n", video_device); exit (EXIT_FAILURE); } else { fprintf(stderr,"Failed:VIDIOC_REQBUFS"); exit (EXIT_FAILURE); } } if (req.count < 2) { //double buffers fprintf (stderr, "Insufficient buffer memory on %s\n", video_device); exit (EXIT_FAILURE); } buffers = calloc (req.count, sizeof (*buffers)); if (!buffers) { fprintf (stderr, "Out of memory\n"); exit (EXIT_FAILURE); } 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 (videofd, VIDIOC_QUERYBUF, &buf)) { //query the state of one of the buffers in driver space fprintf(stderr,"Failed:VIDIOC_QUERYBUF "); exit(EXIT_FAILURE); } buffers[n_buffers].length = buf.length; buffers[n_buffers].start = mmap ( NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, videofd, buf.m.offset); if (buffers[n_buffers].start == MAP_FAILED ) { fprintf(stderr,"Failed:when MMAP"); exit(EXIT_FAILURE); } }}static void init_usrptr(unsigned int bufSize) //{ struct v4l2_requestbuffers req; CLEAR (req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_USERPTR; if (-1 == ioctl (videofd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { fprintf (stderr, "%s does not support ""user pointer i/o\n", video_device); exit (EXIT_FAILURE); } else { fprintf(stderr,"Failed:VIDIOC_REQBUFS\n"); } } buffers = calloc (4, sizeof (*buffers)); if (!buffers) { fprintf (stderr, "Out of memory\n"); exit (EXIT_FAILURE); } for (n_buffers = 0; n_buffers < 4; ++n_buffers) { buffers[n_buffers].length = bufSize; buffers[n_buffers].start = malloc (bufSize); //allocate buffers in user space if (!buffers[n_buffers].start) { fprintf (stderr, "Out of memory\n"); exit (EXIT_FAILURE); } } }static int xioctl( int fd,int request,void * arg){ int r; do{ r = ioctl (fd, request, arg); } while (-1 == r && EINTR == errno); return r;}#define VPFE_STD_AUTO ((v4l2_std_id)(0x1000000000000000ULL))void init_device(){ struct v4l2_capability cap;
struct v4l2_cropcap cropCap;
struct v4l2_crop crop;
struct v4l2_format fmt; unsigned int min;
//get the capture device's capabilities if (ioctl(videofd, VIDIOC_QUERYCAP, &cap) == -1) {
if (errno == EINVAL) {
fprintf ( stderr, "%s is no V4L2 device\n",video_device);
exit(EXIT_FAILURE);
}
fprintf(stderr,"Failed VIDIOC_QUERYCAP on %s (%s)\n", video_device,strerror(errno));
exit(EXIT_FAILURE);
} if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf(stderr,"%s is no video capture device\n", video_device);
exit(EXIT_FAILURE);
}
switch (io) { case IO_METHOD_READ: if (!(cap.capabilities & V4L2_CAP_READWRITE)) { fprintf (stderr, "%s does not support read i/o\n",video_device); exit (EXIT_FAILURE); } break; case IO_METHOD_MMAP: case IO_METHOD_USERPTR: if (!(cap.capabilities & V4L2_CAP_STREAMING)) { fprintf (stderr, "%s does not support streaming i/o\n",video_device); exit (EXIT_FAILURE); } } //set croping and scaling attribure CLEAR(cropCap); cropCap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (0 == ioctl (videofd, VIDIOC_CROPCAP, &cropCap)) { crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropCap.defrect; /* reset to default */ if (-1 == ioctl (videofd, VIDIOC_S_CROP, &crop)) { switch (errno) { case EINVAL: fprintf(stderr,"Cropping not supported\n"); //exit (EXIT_FAILURE); default: fprintf(stderr, "Failed:VIDIOC_S_CROP"); // exit (EXIT_FAILURE); } } } else { fprintf(stderr,"Failed:VIDIOC_CROPCAP"); //exit(EXIT_FAILURE); } //set picture format fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = D1_WIDTH; //720 fmt.fmt.pix.height = D1_HEIGHT; //480 switch(format) { case YUYV : fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; break; case UYVY : fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -