V4L2框架摄像头挂载和抓取Demo实例

本文是总结和整理文章:

详解解释见:http://blog.csdn.net/shaolyh/article/details/6583226

感谢原博主的分享!

src:

#include <fimc.h>
 
static int fd_cam=-1 ;
static struct v4l2_requestbuffers reqbuf;
static VideoBuffer framebuf[BUFFER_COUNT];
static struct v4l2_buffer buf;
 
int Camera_OpenCam()
{
    // open device
    fd_cam = open(CAMERA_DEVICE, O_RDWR, 0);
    if (fd_cam < 0) {
        printf("Open %s failed\n", CAMERA_DEVICE);
        return -1;
    }
    return fd_cam ;
}
int Camera_CloseCam()
{
    return close(fd_cam);
}
int Camera_GetCamInfo()
{
    int ret=-1 ;
    // GetDevicInfo
    struct v4l2_capability cap;
    ret = ioctl(fd_cam, 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);
 
    return ret ;
}
int Camera_SetCamFMT()
{
    int ret = -1 ;
   // SetCamFMT
    struct v4l2_format fmt;
    memset(&fmt, 0, sizeof(fmt));
    fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width       = VIDEO_WIDTH;
    fmt.fmt.pix.height      = VIDEO_HEIGHT;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
    ret = ioctl(fd_cam, VIDIOC_S_FMT, &fmt);
    if (ret < 0) {
        printf("VIDIOC_S_FMT failed (%d)\n", ret);
        return ret;
    }
 
    // GetCamFMT to Verify
    ret = ioctl(fd_cam, VIDIOC_G_FMT, &fmt);
    if (ret < 0) {
        printf("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);
 
    return 0 ;
}
int Camera_RequestBuffers(struct v4l2_requestbuffers *reqbuf__)
{
    // Request Buffers from kernel
    int ret =-1 ;
    reqbuf__->count = BUFFER_COUNT;
    reqbuf__->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf__->memory = V4L2_MEMORY_MMAP;
 
    ret = ioctl(fd_cam , VIDIOC_REQBUFS, reqbuf__);
    if(ret < 0) {
        printf("VIDIOC_REQBUFS failed (%d)\n", ret);
        return ret;
    }
    return ret ;
}
int Camera_MapAndEnqueue(struct v4l2_requestbuffers *reqbuf__, struct v4l2_buffer *buf__,VideoBuffer *framebuf_)
{
    int i=-1,ret=-1 ;
     // Map And Enqueue
    for (i = 0; i < reqbuf__->count; i++)
    {
        buf__->index = i;
        buf__->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf__->memory = V4L2_MEMORY_MMAP;
        ret = ioctl(fd_cam , VIDIOC_QUERYBUF, buf__);
        if(ret < 0) {
            printf("VIDIOC_QUERYBUF (%d) failed (%d)\n", i, ret);
            return ret;
        }
 
        // mmap buffer
        framebuf_[i].length = buf__->length;
        framebuf_[i].start = (char *) mmap(0, buf__->length, PROT_READ|PROT_WRITE, MAP_SHARED, fd_cam, buf__->m.offset);
        if (framebuf_[i].start == MAP_FAILED) {
            printf("mmap (%d) failed: %s\n", i, strerror(errno));
            return -1;
        }
 
        // Queen buffer
        ret = ioctl(fd_cam , VIDIOC_QBUF, buf__);
        if (ret < 0) {
            printf("VIDIOC_QBUF (%d) failed (%d)\n", i, ret);
            return -1;
        }
 
        printf("Frame buffer %d: address=0x%x, length=%d\n", i, (unsigned int)framebuf_[i].start, framebuf_[i].length);
    }
    return 0 ;
}
void Camera_UNMap(VideoBuffer *framebuf_)
{
    int i=-1 ;
    // Release the resource
    for (i=0; i< 4; i++)
    {
        munmap(framebuf_[i].start, framebuf_[i].length);
    }
}
int Camera_StartCameraStreaming()
{
    int ret=-1 ;
    // start camera streaming
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ioctl(fd_cam, VIDIOC_STREAMON, &type);
    if (ret < 0) {
        printf("VIDIOC_STREAMON failed (%d)\n", ret);
        return ret;
    }
    return ret ;
}
int Camera_DeQueueBufferGetFrame( struct v4l2_buffer *buf_)
{
    int ret=-1 ;
    // De-queue buffer ,Get frame
    ret = ioctl(fd_cam, VIDIOC_DQBUF, buf_);
    if (ret < 0) {
        printf("VIDIOC_DQBUF failed (%d)\n", ret);
        return ret;
    }
    return ret ;
}
int Camera_EnQueueBuffer(struct v4l2_buffer *buf_)
{
    int ret = -1 ;
    // Re-queen buffer
    ret = ioctl(fd_cam, VIDIOC_QBUF, buf_);
    if (ret < 0) {
        printf("VIDIOC_QBUF failed (%d)\n", ret);
        return ret;
    }
    return 0 ;
}
void Camera_RecordYUYV(const char* YUYVFILE ,struct v4l2_buffer *buf_)
{
    // record frame YUYV
    FILE *fp = fopen(YUYVFILE, "wb");
    if (fp < 0) {
        printf("open frame data file failed\n");
        return ;
    }
    fwrite(framebuf[buf_->index].start, 1, buf_->length, fp);
    fclose(fp);
    printf("Capture one frame saved in %s\n", YUYVFILE);
}
int main()
{
    Camera_OpenCam();
    Camera_GetCamInfo() ;
    Camera_SetCamFMT();
 
    Camera_RequestBuffers(&reqbuf);
    Camera_MapAndEnqueue(&reqbuf,&buf,framebuf);
 
    Camera_StartCameraStreaming();
 
    Camera_DeQueueBufferGetFrame(&buf);
    Camera_RecordYUYV(CAPTURE_FILE,&buf);
    Camera_EnQueueBuffer(&buf);
 
    Camera_UNMap(framebuf);
    Camera_CloseCam();
 
    printf("Camera test Done.\n");
    return 0;
}


header:

#ifndef FIMC_H_
#define FIMC_H_
 
#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 CAMERA_DEVICE "/dev/video0"
#define CAPTURE_FILE "frame-yuyv.yuv"
 
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT 4
 
typedef struct VideoBuffer {
    void   *start;
    size_t  length;
} VideoBuffer;
 
 
#endif /* FIMC_H_ */

--------------------- 
作者:放牛娃不吃草 
来源:CSDN 
原文:https://blog.csdn.net/gubenpeiyuan/article/details/37726887 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/ds1130071727/article/details/83544794