你的分享就是我们的动力 ---﹥

基于Qt4和V4L2的照相机程序

时间:2013-07-16 14:57来源:www.chengxuyuans.com 点击:

代码简介

基于Linux平台的V4L2接口,使用Qt Creator开发,目前只能使用输出JPEG格式的摄像头。界面中有实时预览和拍照键、退出键。参考了这里http://www.oschina.net/code/snippet_124925_3789

代码片段

#ifndef VIDEO_H
#define VIDEO_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/wait.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <asm/types.h>
#include <linux/videodev2.h>

#define CAM_DEV "/dev/video0"
#define CLEAR(x) memset (&(x), 0, sizeof (x))

#endif // VIDEO_H

代码片段

#ifndef CAMERA_H
#define CAMERA_H

#include <QWidget>

namespace Ui {
class Camera;
}

class Camera : public QWidget
{
    Q_OBJECT
    
public:
    explicit Camera(QWidget *parent = 0);
    bool cam_init();
    bool start_capture();
    void video_play();
    bool grab_picture();
    bool close_cam();
    ~Camera();
    
private:
    Ui::Camera *ui;
    QPixmap pixmap;
    QTimer *timer;
    QString filename;
private slots:
    bool eventFilter(QObject *watched, QEvent *event);
    void paintEvent(QPaintEvent *);

};

#endif // CAMERA_H

代码片段

#include "camera.h"
#include "ui_camera.h"
#include "video.h"
#include <QFile>
#include <QTimer>
#include <QDateTime>
#include <QDebug>
using namespace std;
static int cam_fd;
unsigned long file_length;
void *img[4];
int isstreaming=0;
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buffer;
const int W=320,H=240;
int n=2;
Camera::Camera(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Camera)
{
    ui->setupUi(this);
    ui->captrueBtn->installEventFilter(this);
    if(cam_init())
        //ui->statusLabel->setText("Ready");
        qDebug("camera init!");
    else
        //ui->statusLabel->setText("Error");
        qDebug("camera init error!");
    if(start_capture())
    {
        qDebug("stream on");
        ui->statusLabel->setText("Ready");
    }
    else
        qDebug("stream on error");
    //video_play();
    timer=new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(update()));
    timer->start(100);

}

Camera::~Camera()
{
    delete ui;
    close_cam();
    ::close(cam_fd);

}

bool Camera::eventFilter(QObject *watched, QEvent *event)
{
    if(watched==ui->captrueBtn)
    {
        if(event->type()==QEvent::MouseButtonPress)
        {
            QMatrix mat;
            mat.scale(0.9,0.9);
            QPixmap tmp=QPixmap(QString::fromUtf8(":/Camera-icon.png")).transformed(mat);
            ui->captrueBtn->setPixmap(tmp);
            if(grab_picture())
                qDebug("grab a pictrue!");
            return true;
        }
        if(event->type()==QEvent::MouseButtonRelease)
        {
            ui->captrueBtn->setPixmap(QPixmap(QString::fromUtf8(":/Camera-icon.png")));
            //sleep(1);
            ui->statusLabel->setText("Ready");
            qDebug("button release");
            return true;
        }
        return false;
    }
    return false;
}

void Camera::paintEvent(QPaintEvent *)
{
    video_play();
}

bool Camera::cam_init()
{
    QFile f(CAM_DEV);
    //open device
    if(f.exists())
    {
        cam_fd=::open(CAM_DEV,O_RDWR);
        if(cam_fd<0)
        {
            qDebug("open camera error");
            return false;
        }
    }
    //query capability
    CLEAR(cap);
    if(ioctl (cam_fd, VIDIOC_QUERYCAP, &cap)<0)
    {
        qDebug("VIDIOC_QUERYCAP:");
        return false;
    }
    qDebug("capabilities:0x%x",cap.capabilities);
    //set fomat
    CLEAR(fmt);
    fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width=W;
    fmt.fmt.pix.height=H;
    if(ioctl(cam_fd,VIDIOC_S_FMT,&fmt)<0)
    {
        qDebug("VIDIOC_S_FMT");
        return false;
    }
    fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ioctl(cam_fd,VIDIOC_G_FMT,&fmt);
    if(fmt.fmt.pix.pixelformat&V4L2_PIX_FMT_JPEG)
        qDebug("set format V4L2_PIX_FMT_JPEG");
    //file length
    file_length=fmt.fmt.pix.bytesperline*fmt.fmt.pix.height;
    //request memory
    CLEAR(req);
    req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory=V4L2_MEMORY_MMAP;
    req.count=4;
    if(ioctl(cam_fd,VIDIOC_REQBUFS,&req)<0)
    {
        qDebug("VIDIOC_REQBUFS:");
        return false;
    }
    qDebug("request memory!");
    //query buffer
    int i;
    for(i=0;i<4;i++)
    {
        CLEAR(buffer);
        buffer.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buffer.memory=V4L2_MEMORY_MMAP;
        buffer.index=i;
        if(ioctl(cam_fd,VIDIOC_QUERYBUF,&buffer)<0)
        {
            qDebug("VIDIOC_QUERYBUF:");
            return false;
        }
        //memory map
        img[i]=mmap(0,buffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,buffer.m.offset);
        if(img==MAP_FAILED)
        {
            qDebug("mmap failed:");
            return false;
        }
    }
    qDebug("memory mapped!");
    //queue the buffer
    for(i=0;i<4;i++)
    {
        CLEAR(buffer);
        buffer.index=i;
        buffer.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buffer.memory=V4L2_MEMORY_MMAP;
        if(ioctl(cam_fd,VIDIOC_QBUF,&buffer)<0)
            {
                qDebug("VIDIOC_QBUF:");
                return false;
            }
    }
    qDebug("queen buffer!");

    return true;
}

bool Camera::start_capture()
{
    if(!isstreaming)
    {
        //stream on
        if(ioctl(cam_fd,VIDIOC_STREAMON,&buffer.type)<0)
        {
            qDebug("VIDIOC_STREAMON:");
            return false;
        }
        isstreaming=1;
        //qDebug("stream on");
    }
    return true;
}

void Camera::video_play()
{

    //queue out
    if(ioctl (cam_fd, VIDIOC_DQBUF, &buffer)<0)
        {
            qDebug("VIDIOC_DQBUF:");
            //return false;
        }
    pixmap.loadFromData((uchar*)img[buffer.index],buffer.bytesused,"JPEG");
    ui->videoLabel->setPixmap(pixmap);
    //queue buffer
    ioctl(cam_fd, VIDIOC_QBUF, &buffer);
    //return true;
}

bool Camera::grab_picture()
{
    QDateTime datetime=QDateTime::currentDateTime();
    filename=datetime.toString("yyMMddhhmmss");
    filename+=".jpg";
    qDebug()<<filename;
    pixmap.save(filename);
    ui->statusLabel->setText("Saved");
    return true;
}

bool Camera::close_cam()
{
    if(isstreaming)
    {
        if(ioctl(cam_fd, VIDIOC_STREAMOFF, &buffer.type)<0)
            {
                qDebug("VIDIOC_STREAMOFF:");
                return false;
            }
            qDebug("stop capture!");
            //memory unmap
            int i;
            for(i=0;i<4;i++)
            {
                if(munmap(img[i],buffer.length)<0)
                {
                    qDebug("munmap:");
                    return false;
                }
            }
            qDebug("memory unmapped");
        isstreaming=0;
    }
    return true;
}


代码片段

#include "camera.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Camera w;
    //w.showFullScreen();
    w.show();
    
    return a.exec();
}

转载注明地址:http://www.chengxuyuans.com/code/C++/65786.html