简介

海思摄像头架构并不支持标准Linux的V4L2架构,为此,我们提供中间件,实现二者之间的兼容。

使用

insmod hi3516ev200_v4l2.ko
./hi3516ev200_dopi_media /dev/video0 & #目前仅提供针对开发板上的320x240 LCD像素数据
./app #该应用将会采集摄像头数据在LCD上显示

PS: 运行前,请先加载海思的摄像头驱动LCD显示屏的驱动,如有不明可参考env.sh脚本

V4L2开发示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>
#include <assert.h>
#include <poll.h>
#include <errno.h>
#include <stdlib.h>
#define VIDEO_NAME  "/dev/video0"
struct videobuffer{
    unsigned int length;
    void* start;
};

int main()
{
    //open video
    int dev = open(VIDEO_NAME,  O_RDWR | O_NONBLOCK, 0);
    if(dev <0 ){
        printf("open video0 fail.\n");
        return -1;
    }


    //query capability
    struct v4l2_capability cap;
    ioctl(dev, VIDIOC_QUERYCAP, &cap);
    printf("--------------capability------------------\n");
    printf("driver:%s    \ncard:%s   \ncapabilities:%x\n",cap.driver,cap.card,cap.capabilities);

    //set and get format
    struct v4l2_fmtdesc fmtdesc;
    int ret;
    int i;
    memset(&fmtdesc, 0, sizeof(fmtdesc));
    fmtdesc.index = 0;
    fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    printf("-------------VIDIOC_ENUM_FMT--------------\n");
    while((ioctl(dev, VIDIOC_ENUM_FMT, &fmtdesc)) != -1)
    {
        printf("index:%d   \npixelformat:%c%c%c%c  \ndescription:%s\n",fmtdesc.index, fmtdesc.pixelformat&0xff,(fmtdesc.pixelformat>>8)&0xff,(fmtdesc.pixelformat>>16)&0xff,
        (fmtdesc.pixelformat>>24)&0xff,fmtdesc.description);
        fmtdesc.index++;
    }

    int width = 320, height = 240;
    struct v4l2_format format;
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    format.fmt.pix.width = width;
    format.fmt.pix.height = height;
    format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;  // 设置为yuyv格式数据
    format.fmt.pix.field = V4L2_FIELD_INTERLACED;
    ret = ioctl(dev, VIDIOC_S_FMT, &format);
    if(ret < 0){
        printf("VIDIOC_S_FMT fail\n");
        return -1;
    }
    memset(&format, 0, sizeof(format));
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ioctl(dev, VIDIOC_G_FMT, &format);
    if(ret < 0)
    {
        printf("VIDIOC_G_FMT fail\n");
        return -1;
    }
    printf("-----------------VIDIOC_G_FMT----------------------\n");
    printf("width:%d   \nheight:%d   \ntype:%x   pixelformat:%c%c%c%c\n",format.fmt.pix.width,format.fmt.pix.height,
        format.type,format.fmt.pix.pixelformat&0xff,(format.fmt.pix.pixelformat>>8)&0xff,(format.fmt.pix.pixelformat>>16)&0xff,
        (format.fmt.pix.pixelformat>>24)&0xff);

    //init mmap
    struct videobuffer framebuf;
    struct v4l2_requestbuffers reqbuf;

    reqbuf.count = 1;
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    ret = ioctl(dev, VIDIOC_REQBUFS, &reqbuf);
    if(0 != ret){
        printf("VIDIOC_REQBUFS fail\n");
        return -1;
    }
    //v4l2_buffer
    printf("----------------mmap----------------\n");

    struct v4l2_buffer buf;
    memset(&buf, 0, sizeof(buf));
    buf.index = 1;
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    ret = ioctl(dev, VIDIOC_QUERYBUF, &buf);

    framebuf.length = buf.length;
    framebuf.start = mmap(NULL, buf.length, PROT_READ|PROT_WRITE, 
        MAP_SHARED, dev, buf.m.offset);
    if(framebuf.start == MAP_FAILED){
        perror("mmap fail.\n");
        return -1;
    }
    printf("start:%p  length:%d\n",framebuf.start,framebuf.length);


    for(i=0;i < 1; i++){
        memset(&buf, 0, sizeof(buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;
        ret = ioctl(dev, VIDIOC_QBUF, &buf);
        if(0 != ret){
            perror("VIDIOC_QBUF fail.\n");
            return -1;
        }
    }

    enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ioctl(dev, VIDIOC_STREAMON, &type);
    //usleep(500000);
    struct pollfd pollfd;
    for(;;i++){

        memset(&pollfd, 0, sizeof(pollfd));
        pollfd.fd = dev;
        pollfd.events = POLLIN;
        ret = poll(&pollfd, 1, 800);
        printf("poll %d i=%d\n",pollfd.revents, i);
        if(-1 == ret){
            perror("VIDIOC_QBUF fail.\n");
            return -1;
        }else if(0 == ret){
            printf("poll time out\n");
            continue;
        }
        break;
    }
    //printf("-------------poll success---------------\n");
    // static struct v4l2_buffer buf;

    if(pollfd.revents & POLLIN){
        memset(&buf, 0, sizeof(buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        ret = ioctl(dev, VIDIOC_DQBUF, &buf);
        if(0 != ret){
            perror("VIDIOC_QBUF fail.\n");
            return -1;
        }
    }
    printf("-------------capture success---------------\n");

    FILE *fp = fopen("./yuv.yuv", "wb+");
    loff_t pos = 0;
    fwrite((char*)framebuf.start, 1, buf.length, fp);
    fclose(fp);
    close(dev);
    return 0;
}

文档更新时间: 2020-09-19 01:06   作者:cijliu