Ubuntu 的源

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

#include <iostream>
using namespace std;
using namespace cv;

#define CAMERA    "/dev/video0"
#define CAPTURE_FILE "frame.yuv"
#define DBG_DIR "jpg/"

#define BUFFER_COUNT 8

typedef struct __video_buffer
{
    void* start;
    size_t length;

}video_buf_t;

int width = 160;
int height = 120;

static int fd;

bool v4l2_init();
bool v4l2_start();
void v4l2_cvshow();
int showFormat();

video_buf_t* framebuf;


int main(int argc, char* argv[])
{
    v4l2_init();
    cout << "init finished" << endl;
    showFormat();
    cout << "showFormat finished" << endl;
    v4l2_start();
    cout << "start finished" << endl;
    v4l2_cvshow();
    cout << "cvshow finished" << endl;
    //while(1);
    close(fd);
    return 0;
}


bool v4l2_init()
{
    if ((fd = open(CAMERA, O_RDWR)) == -1)
    {
        perror("Camera open failed!\n");
        return false;
    }

    //query camera capabilities
    struct v4l2_capability cap;

    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1)
    {
        perror("VIDIOC_QUERYCAP failed!\n");
        return false;
    }

    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 format
    struct v4l2_format fmt;
    memset(&fmt, 0, sizeof(fmt));

    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = width;
    fmt.fmt.pix.height = height;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;//V4L2_PIX_FMT_YUYV;V4L2_PIX_FMT_MJPEG
    fmt.fmt.pix.field = 1;//V4L2_FIELD_INTERLACED; V4L2_FIELD_NONE;V4L2_FIELD_ANY

    if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1)
    {
        perror("VIDIOC_S_FMT failed!\n");
        return false;
    }

    //get format
    if (ioctl(fd, VIDIOC_G_FMT, &fmt) == -1)
    {
        perror("VIDIOC_G_FMT failed!\n");
        return false;
    }
    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 true;
}

int showFormat()
{
    printf("-----------------------支持格式---------------------\n");
    struct v4l2_fmtdesc dis_fmtdesc;
    dis_fmtdesc.index = 0;
    dis_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    printf("Supportformat:\n");
    while (ioctl(fd, VIDIOC_ENUM_FMT, &dis_fmtdesc) != -1)
    {
        cout << "index: " << dis_fmtdesc.pixelformat<<" "<< dis_fmtdesc .type<< endl;
        printf("\t%d.%s\n", dis_fmtdesc.index + 1, dis_fmtdesc.description);
        dis_fmtdesc.index++;
    }
    return 0;
}


bool v4l2_start()
{
    //request memory allocation
    struct v4l2_requestbuffers reqbuf;
    reqbuf.count = BUFFER_COUNT;
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;

    if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) == -1)
    {
        perror("VIDIOC_REQBUFS failed!\n");
        return false;
    }

    framebuf = (video_buf_t*)calloc(reqbuf.count, sizeof(video_buf_t));
    struct v4l2_buffer buf;

    for (int i = 0; i < reqbuf.count; i++)
    {
        buf.index = i;
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1)
        {
            perror("VIDIOC_QUERYBUF failed!\n");
            return false;
        }

        //mmap buffer
        framebuf[i].length = buf.length;
        framebuf[i].start = mmap(NULL, buf.length,
            PROT_READ | PROT_WRITE,
            MAP_SHARED, fd, buf.m.offset);
        if (framebuf[i].start == MAP_FAILED)
        {
            perror("mmap failed!\n");
            return false;
        }
        //buffer queue
        if (ioctl(fd, VIDIOC_QBUF, &buf) == -1)
        {
            perror("VIDIOC_QBUF failed!\n");
            return false;
        }
    }
    //start camera capture
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(fd, VIDIOC_STREAMON, &type) == -1)
    {
        perror("VIDIOC_STREAMON failed!\n");
        return false;
    }

    return true;
}

int num = 0;

void v4l2_cvshow()
{
    bool quit = false;
    struct v4l2_buffer buf;
    CvMat cvmat;
    IplImage* image;
    int retry = 0;

    while (!quit)
    {
        cout << "line 192" << endl;
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        cout << "line 194" << endl;
        buf.memory = V4L2_MEMORY_MMAP;
        cout << "line 196" << endl;
        if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1)
            //    if (ioctl(fd, VIDIOC_DQBUF, &buf) > -2)
        {
            cout << "line 199" << endl;
            perror("VIDIOC_DQBUF failed!\n");
            cout << "line 201" << endl;
            usleep(10000);
            cout << "line 202" << endl;
            retry++;
            if (retry > 10)
                quit = true;
            continue;
        }

        cout << "num: " << num++ << endl;

        // Mat img(height,width,CV_8UC3,framebuf[buf.index].start);
        // imshow("Image",img);

        /*cvmat = cvMat(height, width, CV_8UC3, framebuf[buf.index].start);
        image = cvDecodeImage(&cvmat, 1);
        cvShowImage("Image", image);
        cvReleaseImage(&image);*/

        
        /*char jpgName[32];
        sprintf(jpgName, DBG_DIR "%03d.yuv",num++);
        FILE* fSource = fopen(jpgName, "wb");
        fwrite(framebuf[buf.index].start, 1, (size_t)buf.bytesused, fSource);
        fclose(fSource);*/

        if (ioctl(fd, VIDIOC_QBUF, &buf) == -1)
        {
            perror("VIDIOC_QBUF failed!\n");
            continue;
        }
        waitKey(10);
    }

}
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章