【转载】使用v4l2获取照片

capture.c

#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 <time.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";

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;

void itoa(int i,char *string)

{

int power,j;

j=i;

for(power=1;j>=10;j/=10)

power*=10;

for(;power>0;power/=10)

{

*string++='0'+i/power;

i%=power;

}

*string='\0';

}

//

//获取一帧数据

//

static int read_frame (void)

{

struct v4l2_buffer buf;

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);

fwrite(buffers[buf.index].start, buffers[buf.index].length, 1, file_fd); //

ioctl (fd, VIDIOC_QBUF, &buf); 

 

return 1;

}

 

///

//get local time

//

char MY_nowtime(char *save_time)

{

time_t t = time(NULL);

struct tm *time;

time = localtime(&t);

sprintf(save_time, "img%02d",time->tm_sec);

return 0;

}

 

int main (int argc,char ** argv)

{

    system("kill -9 `pidof mjpg_streamer`");

    sleep(2);

struct v4l2_capability cap; 

struct v4l2_format fmt;

unsigned int i;

enum v4l2_buf_type type;

char jpegfile[100];

int num=1;

// char save_time[128] = {0};

// MY_nowtime(save_time);

while (num < 11)

{

// itoa(num,jpegfile);

//    MY_nowtime(jpegfile);

// strcat(jpegfile,".jpg");

        sprintf(jpegfile, "img%02d.jpg", num);

printf("\n%d.jpg ok!\n",num);

file_fd = fopen(jpegfile, "w");//图片文件名

fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);//打开设备

 

ioctl (fd, VIDIOC_QUERYCAP, &cap);//获取摄像头参数

 

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); //设置图像格式

 

file_length = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; //计算图片大小

 

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); //申请缓冲,count是申请的数量

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 (;;)

{

  fd_set fds;

  struct timeval tv;

    int r;

 

        FD_ZERO (&fds);

      FD_SET (fd, &fds);

 

           tv.tv_sec = 2;

      tv.tv_usec = 0;

 

           r = select (fd + 1, &fds, NULL, NULL, &tv);

           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 ())

    break;

    }

num++;

 

  for (i = 0; i < n_buffers; ++i)

      if (-1 == munmap (buffers[i].start, buffers[i].length))

   printf ("munmap error");

close (fd);

fclose (file_fd);

    }

printf("copying. . . \n");

printf("wait please\n");

    system("mv *.jpg /www/captures/");

    printf("ok! you have get %d pictures in /www/captures/\n",num -1);

        sleep(2);

        system("stream");

        sleep(2);

exit (EXIT_SUCCESS);

return 0;

 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用v4l2获取mjpeg格式图片的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/videodev2.h> #define CAMERA_DEVICE "/dev/video0" #define CAPTURE_FILE "capture.jpeg" #define BUFFER_COUNT 4 struct buffer { void *start; size_t length; }; int main() { int fd; struct v4l2_capability cap; struct v4l2_format fmt; struct v4l2_requestbuffers req; struct v4l2_buffer buf; enum v4l2_buf_type type; struct buffer *buffers; int i, n_buffers; FILE *fp; // 打开摄像头设备 fd = open(CAMERA_DEVICE, O_RDWR); if (fd == -1) { perror("Failed to open camera device"); return EXIT_FAILURE; } // 查询摄像头设备的能力 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) { perror("Failed to query camera device"); return EXIT_FAILURE; } // 检查是否支持视频捕获 if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "Camera device does not support video capture\n"); return EXIT_FAILURE; } // 检查是否支持流形式的视频捕获 if (!(cap.capabilities & V4L2_CAP_STREAMING)) { fprintf(stderr, "Camera device does not support streaming\n"); return EXIT_FAILURE; } // 设置摄像头设备的格式 memset(&fmt, 0, sizeof(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_MJPEG; if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { perror("Failed to set camera device format"); return EXIT_FAILURE; } // 请求摄像头设备的缓冲区 memset(&req, 0, sizeof(req)); req.count = BUFFER_COUNT; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { perror("Failed to request camera device buffers"); return EXIT_FAILURE; } // 映射摄像头设备的缓冲区 buffers = calloc(req.count, sizeof(*buffers)); for (i = 0, n_buffers = 0; i < req.count; i++) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { perror("Failed to query camera device buffer"); return EXIT_FAILURE; } buffers[i].length = buf.length; buffers[i].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (buffers[i].start == MAP_FAILED) { perror("Failed to map camera device buffer"); return EXIT_FAILURE; } n_buffers++; } // 启动摄像头设备的视频流 for (i = 0; i < n_buffers; i++) { memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { perror("Failed to enqueue camera device buffer"); return EXIT_FAILURE; } } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) { perror("Failed to start camera device stream"); return EXIT_FAILURE; } // 从摄像头设备中获取图片 memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) { perror("Failed to dequeue camera device buffer"); return EXIT_FAILURE; } // 保存图片到文件 fp = fopen(CAPTURE_FILE, "wb"); if (fp == NULL) { perror("Failed to open capture file"); return EXIT_FAILURE; } fwrite(buffers[buf.index].start, buf.bytesused, 1, fp); fclose(fp); // 停止摄像头设备的视频流 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) { perror("Failed to stop camera device stream"); return EXIT_FAILURE; } // 释放摄像头设备的缓冲区 for (i = 0; i < n_buffers; i++) { if (munmap(buffers[i].start, buffers[i].length) == -1) { perror("Failed to unmap camera device buffer"); return EXIT_FAILURE; } } free(buffers); // 关闭摄像头设备 if (close(fd) == -1) { perror("Failed to close camera device"); return EXIT_FAILURE; } return EXIT_SUCCESS; } ``` 这段代码使用v4l2库调用摄像头设备的API,请求摄像头设备的缓冲区,映射缓冲区,启动视频流,从视频流中获取一张图片,保存图片到文件,停止视频流,释放缓冲区,最后关闭摄像头设备。请注意,此代码中的图片格式为MJPEG,如果你需要获取其他格式的图片,需要修改代码中的像素格式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值