v4l2在ubuntu用抓图(memory mapping)

#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 *

你可能感兴趣的:(v4l2在ubuntu用抓图(memory mapping))