# Added some notes
# Rockie Cheng
# 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 <ASM/types. h>
# Include <Linux/videodev2.h>
# Define clear (x) memset (& (x), 0, sizeof (x ))
Struct buffer {
Void * start;
Size_t length;
};
Static char * dev_name = "/dev/video0"; // The Name Of The camera device.
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;
//////////////////////////////////////// //////////////
// Obtain a frame of data
//////////////////////////////////////// //////////////
Static int read_frame (void)
{
Struct v4l2_buffer Buf;
Unsigned int I;
Clear (BUF );
Buf. type = v4l2_buf_type_video_capture;
Buf. Memory = v4l2_memory_mmap;
IOCTL (FD, vidioc_dqbuf, & BUF); // frame buffering for column-collected data
Assert (BUF. index <n_buffers );
Printf ("Buf. Index DQ is % d, \ n", Buf. Index );
Fwrite (buffers [Buf. Index]. Start, buffers [Buf. Index]. length, 1, file_fd); // write it to the file
IOCTL (FD, vidioc_qbuf, & BUF); // Add it to the column
Return 1;
}
Int main (INT argc, char ** argv)
{
Struct v4l2_capability cap;
Struct v4l2_format FMT;
Unsigned int I;
Enum v4l2_buf_type;
File_fd = fopen ("test-mmap.jpg", "W"); // Image File Name
FD = open (dev_name, o_rdwr/* required */| o_nonblock, 0); // open the device
IOCTL (FD, vidioc_querycap, & Cap); // obtain camera parameters
Clear (FMT );
FMT. type = v4l2_buf_type_video_capture;
FMT. FMT. pix. width = 640;
FMT. FMT. pix. Height = 480;
FMT. FMT. pix. pixelformat = v4l2_pix_fmt_yuyv;
FMT. FMT. pix. Field = v4l2_field_interlaced;
IOCTL (FD, vidioc_s_fmt, & FMT); // sets the image format
File_length = FMT. FMT. pix. bytesperline * FMT. FMT. pix. height; // calculate the image size.
Struct v4l2_requestbuffers req;
Clear (req );
Req. Count = 4;
Req. type = v4l2_buf_type_video_capture;
Req. Memory = v4l2_memory_mmap;
IOCTL (FD, vidioc_reqbufs, & req); // Request Buffer. Count indicates the number of requests.
If (req. Count <2)
Printf ("insufficient buffer memory \ n ");
Buffers = calloc (req. Count, sizeof (* buffers); // create the corresponding space in the memory
For (n_buffers = 0; n_buffers <Req. Count; ++ n_buffers)
{
Struct v4l2_buffer Buf; // one frame in the driver
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) // map the user space
Printf ("vidioc_querybuf error \ n ");
Buffers [n_buffers]. Length = Buf. length;
Buffers [n_buffers]. Start =
MMAP (null/* start anywhere */, // establishes a ing through 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 ");
}
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) // The requested buffer enters the queue
Printf ("vidioc_qbuf failed \ n ");
}
Type = v4l2_buf_type_video_capture;
If (-1 = IOCTL (FD, vidioc_streamon, & type) // start capturing image data
Printf ("vidioc_streamon failed \ n ");
For (;) // This section involves asynchronous Io
{
Fd_set FDS;
Struct timeval TV;
Int R;
Fd_zero (& FDs); // clears the specified file descriptor set
Fd_set (FD, & FDs); // Add a new file descriptor to the file descriptor set.
/* Timeout .*/
TV. TV _sec = 2;
TV. TV _usec = 0;
R = select (FD + 1, & FDS, null, null, & TV); // determines whether the camera is readable (that is, whether the camera is ready), and TV is timed
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 () // if it is readable, execute the read_frame () function and exit the loop.
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;
}
This article from the Linux community website (www.linuxidc.com) original link: http://www.linuxidc.com/Linux/2011-03/33020.htm