#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 Frame_Buffer {
void * start;
size_t length;
};
static char * dev_name = "/dev/video0";//鎽勫儚澶磋澶囧悕
struct Frame_Buffer * buffers = NULL;
static unsigned int n_buffers = 0;
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define VIDEO_FORMAT V4L2_PIX_FMT_MJPEG// V4L2_PIX_FMT_YUYV;
#define BUFFER_COUNT 4
//////////////////////////////////////////////////////
//鑾峰彇涓€甯ф暟鎹?//////////////////////////////////////////////////////
static int frame2image (int fd)
{
struct v4l2_buffer buf;
unsigned int i;
if (fd < 0) {
printf("failed: no fd.\n");
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);
printf ("buf.index dq is %d,\n",buf.index);
FILE *file_fd = fopen("test-mmap.jpg", "w");//鍥剧墖鏂囦欢鍚?
if(!file_fd) return -1;
fwrite(buffers[buf.index].start, buffers[buf.index].length, 1, file_fd); //灏嗗叾鍐欏叆鏂囦欢涓?
ioctl (fd, VIDIOC_QBUF, &buf); //鍐嶅皢鍏跺叆鍒?
if(file_fd)
fclose (file_fd);
return 1;
}
int main (int argc,char ** argv)
//void catch_image(void)
{
unsigned int i,ret;
enum v4l2_buf_type type;
static int fd = -1;
fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);//鎵撳紑璁惧
if (fd < 0) {
printf("Open %s failed\n", dev_name);
return -1;
}
struct v4l2_capability cap;
ret = ioctl (fd, VIDIOC_QUERYCAP, &cap);//鑾峰彇鎽勫儚澶村弬鏁?
if (ret < 0) {
printf("VIDIOC_QUERYCAP failed (%d)\n", ret);
return ret;
}
// Print capability infomations
printf("Capability Informations:\n");
printf(" driver: %s\n", cap.driver);
printf(" card: %s\n", cap.card);
printf(" bus_info: %s\n", cap.bus_info);
printf(" version: %08X\n", cap.version);
printf(" capabilities: %08X\n", cap.capabilities);
// Set Stream Format
struct v4l2_format fmt;
CLEAR (fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = VIDEO_WIDTH;
fmt.fmt.pix.height = VIDEO_HEIGHT;
fmt.fmt.pix.pixelformat = VIDEO_FORMAT;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ret = ioctl (fd, VIDIOC_S_FMT, &fmt); //璁剧疆鍥惧儚鏍煎紡
if (ret < 0) {
printf("VIDIOC_S_FMT failed (%d)\n", ret);
return ret;
}
// Get Stream Format
CLEAR (fmt);
ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
if (ret < 0) {
LOG("VIDIOC_G_FMT failed (%d)\n", ret);
return ret;
}
// Print Stream Format
printf("Stream Format Informations:\n");
printf(" type: %d\n", fmt.type);
printf(" width: %d\n", fmt.fmt.pix.width);
printf(" height: %d\n", fmt.fmt.pix.height);
char fmtstr[8];
memset(fmtstr, 0, 8);
memcpy(fmtstr, &fmt.fmt.pix.pixelformat, 4);
printf(" pixelformat: %s\n", fmtstr);
printf(" field: %d\n", fmt.fmt.pix.field);
printf(" bytesperline: %d\n", fmt.fmt.pix.bytesperline);
printf(" sizeimage: %d\n", fmt.fmt.pix.sizeimage);
printf(" colorspace: %d\n", fmt.fmt.pix.colorspace);
printf(" priv: %d\n", fmt.fmt.pix.priv);
printf(" raw_date: %s\n", fmt.fmt.raw_data);
//-------------------------
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = BUFFER_COUNT;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ret = ioctl (fd, VIDIOC_REQBUFS, &req); //鐢宠缂撳啿锛宑ount鏄敵璇风殑鏁伴噺
if(ret < 0) {
printf("VIDIOC_REQBUFS failed (%d)\n", ret);
return ret;
}
if (req.count < 2)
printf("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");
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");
}
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");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == ioctl (fd, VIDIOC_STREAMON, &type)) //寮€濮嬫崟鎹夊浘鍍忔暟鎹?
printf ("VIDIOC_STREAMON failed\n");
for (;;) //杩欎竴娈垫秹鍙婂埌寮傛IO
{
fd_set fds;
struct timeval tv;
int r;
FD_ZERO (&fds);//灏嗘寚瀹氱殑鏂囦欢鎻忚堪绗﹂泦娓呯┖
FD_SET (fd, &fds);//鍦ㄦ枃浠舵弿杩扮闆嗗悎涓鍔犱竴涓柊鐨勬枃浠舵弿杩扮
/* Timeout. */
tv.tv_sec = 2;
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 (frame2image (fd))//濡傛灉鍙锛屾墽琛宺ead_frame ()鍑芥暟锛屽苟璺冲嚭寰幆
break;
}
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap (buffers[i].start, buffers[i].length))
printf ("munmap error");
close (fd);
printf("Camera test Done.\n");
return 0;
}
gcc *.c -o *