zoukankan      html  css  js  c++  java
  • Zedboardwebcam设计问题篇(二)V4l2 Capture Sequence 捕获过程

    由于从一开始就用的超群晴天的程序来获取图像,所以对这个过程不是很了解。今天QT显示时改了程序,但是运行结果是没有图像,图像是乱的。

    下面我自己来分析和改动程序以便日后使用吧!

    http://blog.csdn.net/crazyman2010/article/details/6055022

    先看看这篇博客,写的不错

     经过多次尝试,发现是usbhub的问题,用完hub之后,第二次用就会出现两个video,这样就导致了乱的图像。我重新照了c++的代码,进行了编译:

    videodevice.cpp
    #include "videodevice.h"
    
    VideoDevice::VideoDevice(QString dev_name)
    {
        this->dev_name = dev_name;
        this->fd = -1;
        this->buffers = NULL;
        this->n_buffers = 0;
        this->index = -1;
    
    }
    
    int VideoDevice::open_device()
    {
        fd = open(dev_name.toStdString().c_str(), O_RDWR/*|O_NONBLOCK*/, 0);
       // fd = open(dev_name.toStdString().c_str(), O_RDWR|O_NONBLOCK, 0);
    
        if(-1 == fd)
        {
            emit display_error(tr("open: %1").arg(QString(strerror(errno))));
            return -1;
        }
        return 0;
    }
    
    int VideoDevice::close_device()
    {
        if(-1 == close(fd))
        {
            emit display_error(tr("close: %1").arg(QString(strerror(errno))));
            return -1;
        }
        return 0;
    }
    
    int VideoDevice::init_device()
    {
        v4l2_capability cap;
        v4l2_cropcap cropcap;
        v4l2_crop crop;
        v4l2_format fmt;
    
        if(-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap))
        {
            if(EINVAL == errno)
            {
                emit display_error(tr("%1 is no V4l2 device").arg(dev_name));
            }
            else
            {
                emit display_error(tr("VIDIOC_QUERYCAP: %1").arg(QString(strerror(errno))));
            }
            return -1;
        }
    
        if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
        {
            emit display_error(tr("%1 is no video capture device").arg(dev_name));
            return -1;
        }
    
        if(!(cap.capabilities & V4L2_CAP_STREAMING))
        {
            emit display_error(tr("%1 does not support streaming i/o").arg(dev_name));
            return -1;
        }
    
        CLEAR(cropcap);
    
        cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    
        if(0 == ioctl(fd, VIDIOC_CROPCAP, &cropcap))
        {
            CLEAR(crop);
            crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            crop.c = cropcap.defrect;
    
            if(-1 == ioctl(fd, VIDIOC_S_CROP, &crop))
            {
                if(EINVAL == errno)
                {
    //                emit display_error(tr("VIDIOC_S_CROP not supported"));
                }
                else
                {
                    emit display_error(tr("VIDIOC_S_CROP: %1").arg(QString(strerror(errno))));
                    return -1;
                }
            }
        }
        else
        {
            emit display_error(tr("VIDIOC_CROPCAP: %1").arg(QString(strerror(errno))));
            return -1;
        }
    
        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;
    
        if(-1 == ioctl(fd, VIDIOC_S_FMT, &fmt))
        {
            emit display_error(tr("VIDIOC_S_FMT").arg(QString(strerror(errno))));
            return -1;
        }
    
        if(-1 == init_mmap())
        {
            return -1;
        }
    
        return 0;
    }
    
    int VideoDevice::init_mmap()
    {
        v4l2_requestbuffers req;
        CLEAR(req);
    
        req.count = 4;
        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory = V4L2_MEMORY_MMAP;
    
        if(-1 == ioctl(fd, VIDIOC_REQBUFS, &req))
        {
            if(EINVAL == errno)
            {
                emit display_error(tr("%1 does not support memory mapping").arg(dev_name));
                return -1;
            }
            else
            {
                emit display_error(tr("VIDIOC_REQBUFS %1").arg(QString(strerror(errno))));
                return -1;
            }
        }
    
        if(req.count < 2)
        {
            emit display_error(tr("Insufficient buffer memory on %1").arg(dev_name));
            return -1;
        }
    
        buffers = (buffer*)calloc(req.count, sizeof(*buffers));
    
        if(!buffers)
        {
            emit display_error(tr("out of memory"));
            return -1;
        }
    
        for(n_buffers = 0; n_buffers < req.count; ++n_buffers)
        {
            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))
            {
                emit display_error(tr("VIDIOC_QUERYBUF: %1").arg(QString(strerror(errno))));
                return -1;
            }
    
            buffers[n_buffers].length = buf.length;
            buffers[n_buffers].start =
                    mmap(NULL, // start anywhere
                         buf.length,
                         PROT_READ | PROT_WRITE,
                         MAP_SHARED,
                         fd, buf.m.offset);
    
            if(MAP_FAILED == buffers[n_buffers].start)
            {
                emit display_error(tr("mmap %1").arg(QString(strerror(errno))));
                return -1;
            }
        }
        return 0;
    
    }
    
    int VideoDevice::start_capturing()
    {
        unsigned int i;
        for(i = 0; i < n_buffers; ++i)
        {
            v4l2_buffer buf;
            CLEAR(buf);
    
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory =V4L2_MEMORY_MMAP;
            buf.index = i;
    //        fprintf(stderr, "n_buffers: %d\n", i);
    
            if(-1 == ioctl(fd, VIDIOC_QBUF, &buf))
            {
                emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno))));
                return -1;
            }
        }
    
        v4l2_buf_type type;
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    
        if(-1 == ioctl(fd, VIDIOC_STREAMON, &type))
        {
            emit display_error(tr("VIDIOC_STREAMON: %1").arg(QString(strerror(errno))));
            return -1;
        }
        return 0;
    }
    
    int VideoDevice::stop_capturing()
    {
        v4l2_buf_type type;
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    
        if(-1 == ioctl(fd, VIDIOC_STREAMOFF, &type))
        {
            emit display_error(tr("VIDIOC_STREAMOFF: %1").arg(QString(strerror(errno))));
            return -1;
        }
        return 0;
    }
    
    int VideoDevice::uninit_device()
    {
        unsigned int i;
        for(i = 0; i < n_buffers; ++i)
        {
            if(-1 == munmap(buffers[i].start, buffers[i].length))
            {
                emit display_error(tr("munmap: %1").arg(QString(strerror(errno))));
                return -1;
            }
    
        }
        free(buffers);
        return 0;
    }
    
    int VideoDevice::get_frame(void **frame_buf, size_t* len)
    {
        v4l2_buffer queue_buf;
        CLEAR(queue_buf);
    
        queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        queue_buf.memory = V4L2_MEMORY_MMAP;
    
        if(-1 == ioctl(fd, VIDIOC_DQBUF, &queue_buf))
        {
            switch(errno)
            {
            case EAGAIN:
    //            perror("dqbuf");
                return -1;
            case EIO:
                return -1 ;
            default:
                emit display_error(tr("VIDIOC_DQBUF: %1").arg(QString(strerror(errno))));
                return -1;
            }
        }
    
        *frame_buf = buffers[queue_buf.index].start;
        *len = buffers[queue_buf.index].length;
        index = queue_buf.index;
    
        return 0;
    
    }
    
    int VideoDevice::unget_frame()
    {
        if(index != -1)
        {
            v4l2_buffer queue_buf;
            CLEAR(queue_buf);
    
            queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            queue_buf.memory = V4L2_MEMORY_MMAP;
            queue_buf.index = index;
    
            if(-1 == ioctl(fd, VIDIOC_QBUF, &queue_buf))
            {
                emit display_error(tr("VIDIOC_QBUF: %1").arg(QString(strerror(errno))));
                return -1;
            }
            return 0;
        }
        return -1;
    }
    videodevice.h
    #ifndef VIDEODEVICE_H
    #define VIDEODEVICE_H
    
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <fcntl.h>
    
    
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    
    #include <asm/types.h>
    #include <linux/videodev2.h>
    
    #include <QString>
    #include <QObject>
    
    #define CLEAR(x) memset(&(x), 0, sizeof(x))
    
    class VideoDevice : public QObject
    {
        Q_OBJECT
    public:
        VideoDevice(QString dev_name);
        //VideoDevice();
        int open_device();
        int close_device();
        int init_device();
        int start_capturing();
        int stop_capturing();
        int uninit_device();
        int get_frame(void **, size_t*);
        int unget_frame();
    
    private:
        int init_mmap();
    
        struct buffer
        {
            void * start;
            size_t length;
        };
        QString dev_name;
        int fd;
        buffer* buffers;
        unsigned int n_buffers;
        int index;
    
    signals:
        void display_error(QString);
    
    };
    
    #endif // VIDEODEVICE_H
    processimage.h
    #ifndef PROCESSIMAGE_H
    #define PROCESSIMAGE_H
    
    #include <QtGui>
    #include "videodevice.h"
    
    class ProcessImage : public QWidget
    {
        Q_OBJECT
    public:
        ProcessImage(QWidget *parent=0);
        ~ProcessImage();
    
    private:
        QPainter *painter;
        QLabel *label;
        QImage *frame;
        //QPixmap *frame;
        QTimer *timer;
        int rs;
        uchar *pp;
        uchar * p;
        unsigned int len;
        int convert_yuv_to_rgb_pixel(int y, int u, int v);
        int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height);
        VideoDevice *vd;
    
    private slots:
        void paintEvent(QPaintEvent *);
        void display_error(QString err);
    
    
    };
    
    #endif
    processImage.cpp

    这篇代码直接在程序中进行了ui的设计,因此直接运行就可以。

    移植到Zedboard上,先挂载,运行,比较顺利!

  • 相关阅读:
    paip.重装系统需要备份的资料总结..
    poj3078
    poj3009
    poj2151
    poj3274
    poj3436
    VC++:打开、保存文件对话框和浏览文件夹对话框
    目前所有的视频格式都有哪些?
    CMSHFlexGrid 类用法
    Matlab的ActiveX接口_百度文库
  • 原文地址:https://www.cnblogs.com/preorder69/p/2989695.html
Copyright © 2011-2022 走看看