基于ARM的视频监控

           视频监控分为两部分,PC端,ARM板端。  PC端的软件界面是用QT写的, 登入名等用到QSql数据库的一些相关知识,也有仿照锐捷客户端来设计界面。

在这里小抱怨下锐捷客户端啦,不过已经有人破解咯。     那首先,我们通过PC段输入用户名,密码,用户名密码都存在数据库里,当然用户名密码都是可以更改的。 

之后登入上,选择连接选项,输入开发板IP,连接。传数据是用socket编程。不过在此之前,还要配置好PC机IP,用网线来传送数据,那么在局域网内把IP设为同一网段。这边在ARM板用

ifconfig命令查看子网掩码,IP,网关等。 之后在PC设置。    之前要准备的文件系统,环境配置就不多说,前篇博文“音乐播放器”有讲解。 一切就绪,那就来行使监控功能了。 

 

 

ARM端用SecureCRT工具来查看。

 

 

PC端IP设置。

 

 

PC端登入界面(英文界面),不过本人把图片标题给隐藏了,因为上面有学校校徽怕侵权啦。

 

 

 

PC端登入界面(中文界面)。

 

 

输入正确用户名密码登入进次界面。

 

 

菜单栏上面设置选项下面有个连接选项,选择那么跳出此界面。端口号,这个就是程序里已经给定。比如说http就是80端口,这边我们设定为666.

当然也可以是其他,只要不和其他端口冲突即可。

 

 

这边就是摄像头即将要获取的图像,之所以把书目贴出来,是希望对大家有些帮助。

 

 

PC端监控画面。

 

 

ARM板端监控画面,可以看到和PC端是一样的。  不过PC端会比ARM端稍稍延时。

 

部分源码:

 

#include "editpasswd.h"
#include "connection.h"

EditPasswd::EditPasswd(QWidget *parent) :
    QDialog(parent)
{
    this->setWindowTitle(tr("passwd modified"));
    QGridLayout *gridLayout=new QGridLayout;
   QVBoxLayout *vboxLayout=new QVBoxLayout(this);
    oldLabel=new QLabel(tr("current passward"));
   newLabel=new QLabel(tr("new passward"));
    renewLabel=new QLabel(tr("confirm new passward"));
   oldLineEdit=new QLineEdit(this);

   newLineEdit=new QLineEdit(this);
    renewLineEdit=new QLineEdit(this);
       okButton=new QPushButton(tr("ok"));
    oldLabel->setBuddy(oldLineEdit);
    newLabel->setBuddy(newLineEdit);
    renewLabel->setBuddy(renewLineEdit);

    gridLayout->setMargin(15);
    gridLayout->setSpacing(10);

    gridLayout->addWidget(oldLabel,0,0);
    gridLayout->addWidget(oldLineEdit,0,2);
    gridLayout->addWidget(newLabel,1,0);
    gridLayout->addWidget(newLineEdit,1,2);
    gridLayout->addWidget(renewLabel,2,0);
    gridLayout->addWidget(renewLineEdit,2,2);


    newLineEdit->setStatusTip(tr("please input passward of six figures"));
    newLineEdit->setMaxLength(6);
    oldLineEdit->setEchoMode(QLineEdit::Password);
    newLineEdit->setEchoMode(QLineEdit::Password);
    renewLineEdit->setMaxLength(6);
    renewLineEdit->setEchoMode(QLineEdit::Password);
    vboxLayout->addLayout(gridLayout);
    vboxLayout->addWidget(okButton,0,Qt::AlignBottom|Qt::AlignCenter);
    oldLineEdit->text().clear();
    newLineEdit->text().clear();
    renewLineEdit->text().clear();

connect(okButton,SIGNAL(clicked()),this,SLOT(slotok()));

}
void EditPasswd::slotok()
{



    if(oldLineEdit->text().isEmpty()||newLineEdit->text().isEmpty()||renewLineEdit->text().isEmpty())
    {

        QMessageBox::warning(this, tr("warning"), tr("please complete the inoformation!"),
                             QMessageBox::Ok);
    }
    else
    {
        if(newLineEdit->text().length()!=6)
        {
            QMessageBox::information(this, tr("information"), tr("The new passward is not six figures!"),
                                     QMessageBox::Ok);
        }
        else if(newLineEdit->text()!=renewLineEdit->text())
        {
             QMessageBox::information(this, tr("information"), tr("The two passwards you typed do not match,please input again!"),
                                     QMessageBox::Ok);


            oldLineEdit->text().clear();
            newLineEdit->text().clear();
            renewLineEdit->text().clear();

        }
        else
        {
            QSqlQuery query;

            query.exec("select * from logininfor");
            query.next();
            if(query.value(1).toString()==oldLineEdit->text())
            {
                bool temp=query.exec(QString("update logininfor set passward='%1' where passward='%2'")
                                     .arg(newLineEdit->text()).arg(oldLineEdit->text()));
                if(temp)
                {
                    QMessageBox::information(this, tr("information"), tr("passward modification success!"),
                                             QMessageBox::Ok);
                    oldLineEdit->text().clear();
                    newLineEdit->text().clear();
                    renewLineEdit->text().clear();

                }

                else
                {
                   QMessageBox::information(this, tr("information"), tr("passward change failure,can't access database!"),
                                                   QMessageBox::Ok);

                     oldLineEdit->text().clear();
                    newLineEdit->text().clear();
                    renewLineEdit->text().clear();

                }

            }

            else
            {
               QMessageBox::warning(this, tr("warning"), tr("The current passward is mistake,please input again!"),
                                     QMessageBox::Ok);

                oldLineEdit->text().clear();
                newLineEdit->text().clear();
                renewLineEdit->text().clear();
            }
        }

    }
}
EditPasswd::~EditPasswd()
{
    oldLineEdit->text().clear();
    newLineEdit->text().clear();
    renewLineEdit->text().clear();


}

 

#include "logininterface.h"
#include "ui_logininterface.h"
#include<QMessageBox>
#include<QCheckBox>
#include<QDebug>
#include<QtSql>
LoginInterface::LoginInterface(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::LoginInterface)
{
    ui->setupUi(this);
    ui->lineEdit_passwd->setEchoMode(QLineEdit::Password);

   ifChinese=0;
   ui->comboBox->setCurrentIndex(1);
   connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(change_Language()));
}

LoginInterface::~LoginInterface()
{
    delete ui;
}
void LoginInterface::on_pushButtonlogin_clicked()
{

    if(ui->lineEdit_passwd->text().isEmpty()|ui->lineEdit_usr->text().isEmpty())
    {
        QMessageBox::information(this, tr("please input user and passward"),
                                 tr("please input user and passward first!"), QMessageBox::Ok);
        ui->lineEdit_usr->setFocus();

    }
    else
    {

        QSqlQuery query;


                query.exec("select * from logininfor");
                query.next();
                if ((query.value(0).toString().trimmed() == ui->lineEdit_usr->text())
                    &&(query.value(1).toString().trimmed() == ui->lineEdit_passwd->text()))
                {
                    QDialog::accept();
                }
                else
                {
                    QMessageBox::warning(this, tr("user or passward is wrong"),
                                         tr("please input correct user and passward to login!"), QMessageBox::Ok);
                    if(!ui->checkBoxsave->isChecked())
                    {
                    qDebug()<<"execute";
                    ui->lineEdit_passwd->clear();
                    ui->lineEdit_usr->clear();
                    ui->lineEdit_usr->setFocus();//设置光标的初始位置
                    }
                }

    }
}

void LoginInterface::on_pushButtonexit_clicked()
   {


  switch( QMessageBox::information(this,tr("video monitor system"),tr("Are you sure to exit?"),
                                   QMessageBox::Yes,QMessageBox::No))
  {

  case QMessageBox::Yes:
      this->close();
  case QMessageBox::No:
      return;

  }

   }

void LoginInterface::change_Language()
{
if(ui->comboBox->currentIndex()==0)
    {

 ifChinese=1;
 ui->labelusr->setText(tr("用户名"));
 ui->labelpasswd->setText(tr("密码"));
 this->setWindowTitle(tr("视频监控系统"));
ui->pushButtonexit->setText(tr("退出"));
ui->pushButtonlogin->setText(tr("登陆"));
ui->checkBoxsave->setText(tr("保存密码"));


}
else
{
ifChinese=0;

}





}

 

#include "mainwindow.h"

#include<QtSql>
mainWindow::mainWindow(QWidget *parent) :
    QMainWindow(parent)
{

 this->setWindowTitle(tr("video monitor system"));
label=new QLabel(this);


this->setCentralWidget(label);
this->resize(700,525);
socket=new QTcpSocket(this);
datasize=0;

createAction();
createMenu();


this->label->setStyleSheet("background-image:url(:/new/Storm.jpg)");
}
void mainWindow::createAction()
{
openAction =new QAction(tr("open"),this);

openAction->setShortcut(tr("Ctrl+O"));
connect(openAction,SIGNAL(triggered()),this,SLOT(openFile()));
 exitAction=new QAction(tr("exit"),this);
 exitAction->setShortcut(tr("Ctrl+E"));
connect(exitAction,SIGNAL(triggered()),this,SLOT(exitMessage()));
 helpAction=new QAction(tr("help"),this);
helpAction->setShortcut(tr("Ctrl+H"));
connect(helpAction,SIGNAL(triggered()),this,SLOT(helpShow()));
passwdAction=new QAction(tr("change passward"),this);
passwdAction->setShortcut(tr("Ctrl+P"));
 connectAction=new QAction(tr("connect"),this) ;
 connectAction->setShortcut(tr("Ctrl+S"));
connect(passwdAction,SIGNAL(triggered()),this,SLOT(passwdShow()));
connect(connectAction,SIGNAL(triggered()),this,SLOT(connectMessage()));
connect(socket,SIGNAL(readyRead()),this,SLOT(readMessage()));
}
void mainWindow::createMenu()
{

  fileMenu=this->menuBar()->addMenu(tr("menu"));
  editMenu=this->menuBar()->addMenu(tr("setup"));
  aboutMenu=this->menuBar()->addMenu(tr("help"));
fileMenu->addAction(openAction);
fileMenu->addAction(exitAction);
editMenu->addAction(passwdAction);
editMenu->addAction(connectAction);
aboutMenu->addAction(helpAction);

}
void mainWindow::openFile()
{

}
void mainWindow::helpShow()
{
    QMessageBox::about( this, tr( "About Video Monitor System" ),
                        tr( "<p><b><b><b>Video Monitor System</b></b></b></p><p></p>"
                            "<p>Version 0.0.0 (2012-10-10)</p><p></p>"
                            "<p>If you have some questions,mail(stu_lizi@sina.cn)</p><p></p>"
                            "<p>For more infomation, please visit our monitor system</p>"
                            "<p><a href = http://www.baidu.com>http://www.baidu.com</a></p>" ) );
}
void mainWindow::passwdShow()
{
 qApp->processEvents();

w.setFixedSize(500,150);
 w.oldLineEdit->setFocus();
 w.oldLineEdit->clear();
 w.newLineEdit->clear();
 w.renewLineEdit->clear();

 w.show();

}
void mainWindow::exitMessage()
{
  switch(QMessageBox::information(this,tr("video monitor system"),tr("Are you sure to exit?"),
                                                                   QMessageBox::Yes,QMessageBox::No))
  {
case QMessageBox::Yes:
   this->close();
  break;
case QMessageBox::No:
  break;
default:
  break;

}
}
void mainWindow::connectMessage()
 {

widget=new QWidget;
connectui.setupUi(widget);
widget->show();
widget->setWindowTitle(tr("server information"));
connect(connectui.pushButtonconnect,SIGNAL(clicked()),this,SLOT(connectserver()));
}
void mainWindow::connectserver()
{

    socket->connectToHost(connectui.lineEditip->text(),connectui.lineEdit_port->text().toInt());
if(!socket->waitForConnected(3000))
{
    QMessageBox::information(this,tr("server information"),tr("please confirm your iP address、port,the server is running"),QMessageBox::Ok);

return;
}
widget->close();


}
void mainWindow::readMessage()
{

    while(socket->bytesAvailable()>0)
    {
        if(datasize==0)
        {
            QDataStream in(socket);
            in.setVersion(QDataStream::Qt_4_5);
            if(socket->bytesAvailable()<sizeof(quint64))
                return ;
            in>>datasize;

        }
        qDebug()<<datasize;

        if(datasize > socket->bytesAvailable())
            return ;

        QByteArray array=socket->read(datasize);
        QBuffer buffer(&array);
        buffer.open(QIODevice::ReadOnly);
        QImageReader reader(&buffer,"bmp");
        image=reader.read();
        if(!image.isNull())
        {
            datasize=0;
            socket->reset();
            label->setSizeIncrement(image.size());
            label->setPixmap(QPixmap::fromImage(image));
        }

        else
        {

            qDebug()<<"error!!!!!!!!!!!";
        }



}
}

 

#include <QtGui/QApplication>
#include "logininterface.h"
#include"mainwindow.h"
#include"connection.h"
int main(int argc, char *argv[])
{


    QApplication a(argc, argv);

    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030"));
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));


    if(!createConnection())
      {
      return 0;
      }
LoginInterface w;




QTranslator translator;


    if(w.exec()==QDialog::Accepted)
    {


        if(w.ifChinese==1)
        {

       translator.load(":/new/en.qm");
       a.installTranslator(&translator);
      }

     QPixmap pixmap(":/new/smile.bmp");
     QSplashScreen splash(pixmap);

     splash.show();
     splash.resize(700,525);
       a.processEvents();

        mainWindow window;

       window.show();
     splash.finish(&window);
    return a.exec();
    }

    return 0;
}

 

#include <QtGui>
#include "processImage.h"
#include "videodevice.h"
extern "C"
{
#include <stdio.h>
#include <stdlib.h>
}
ProcessImage::ProcessImage(QWidget *parent):QWidget(parent)
{
    socket=new QTcpSocket(this);
    server=new QTcpServer(this);
  if(!server->listen(QHostAddress::Any,666))
    {
   qDebug()<<"can't listen boys";
    return ;
    }
  check=0;
  pp = (unsigned char *)malloc(320 * 240/*QWidget::width()*QWidget::height()*/* 3 * sizeof(char));
  painter = new QPainter(this);
  frame = new QImage(pp,320,240,QImage::Format_RGB888);
 // frame = new QPixmap(640,320);
  label = new QLabel();
  vd = new VideoDevice(tr("/dev/video0"));

  connect(vd, SIGNAL(display_error(QString)), this,SLOT(display_error(QString)));
  rs = vd->open_device();
  if(-1==rs)
  {
      QMessageBox::warning(this,tr("error"),tr("open /dev/dsp error"),QMessageBox::Yes);
      vd->close_device();
  }

  rs = vd->init_device();
  if(-1==rs)
  {
      QMessageBox::warning(this,tr("error"),tr("init failed"),QMessageBox::Yes);
      vd->close_device();
  }

  rs = vd->start_capturing();
  if(-1==rs)
  {
      QMessageBox::warning(this,tr("error"),tr("start capture failed"),QMessageBox::Yes);
      vd->close_device();
  }

  if(-1==rs)
  {
      QMessageBox::warning(this,tr("error"),tr("get frame failed"),QMessageBox::Yes);
      vd->stop_capturing();
  }

  timer = new QTimer(this);
  connect(timer,SIGNAL(timeout()),this,SLOT(update()));
  timer->start(30);

  QHBoxLayout *hLayout = new QHBoxLayout();
  hLayout->addWidget(label);
  setLayout(hLayout);
  setWindowTitle(tr("Capture"));

    connect(server,SIGNAL(newConnection()),this,SLOT(sendMessage()));

}

ProcessImage::~ProcessImage()
{
    rs = vd->stop_capturing();
    rs = vd->uninit_device();
    rs = vd->close_device();
}

void ProcessImage::paintEvent(QPaintEvent *)
{

    if(check==1)
    {
    rs = vd->get_frame((void **)&p,&len);
    convert_yuv_to_rgb_buffer(p,pp,320,240/*QWidget::width(),QWidget::height()*/);
    frame->loadFromData((uchar *)pp,/*len*/320 * 240 * 3 * sizeof(char));


QByteArray data;
QBuffer buffer;
frame->save(&buffer,"BMP");

QDataStream out(&data,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
out<<(quint64)buffer.data().size();
data.append(buffer.data());
socket->write(data);
socket->flush();

data.resize(0);




//    painter->begin(this);
//    painter->drawImage(0,0,*frame);
//    painter->end();
//    rs = vd->unget_frame();
   // frame->load("./img3.jpg");

    label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor));
   // label->show();
    rs = vd->unget_frame();
   // label->drawFrame();

    //    QPixmap *pixImage = new QPixmap();
//    pixImage->loadFromData((uchar *)pp,sizeof(pp),0,Qt::AutoColor);
//    QPainter painter(this);
//    painter.begin(this);
//    painter.drawPixmap(0,0,QWidget::width(),QWidget::height(),*pixImage);
//    painter.end();
}
 }
void ProcessImage::display_error(QString err)
{
    QMessageBox::warning(this,tr("error"), err,QMessageBox::Yes);
}

/*yuv*/
int ProcessImage::convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
 unsigned int in, out = 0;
 unsigned int pixel_16;
 unsigned char pixel_24[3];
 unsigned int pixel32;
 int y0, u, y1, v;
 for(in = 0; in < width * height * 2; in += 4) {
  pixel_16 =
   yuv[in + 3] << 24 |
   yuv[in + 2] << 16 |
   yuv[in + 1] <<  8 |
   yuv[in + 0];
  y0 = (pixel_16 & 0x000000ff);
  u  = (pixel_16 & 0x0000ff00) >>  8;
  y1 = (pixel_16 & 0x00ff0000) >> 16;
  v  = (pixel_16 & 0xff000000) >> 24;
  pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
  pixel_24[0] = (pixel32 & 0x000000ff);
  pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
  pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
  rgb[out++] = pixel_24[0];
  rgb[out++] = pixel_24[1];
  rgb[out++] = pixel_24[2];
  pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
  pixel_24[0] = (pixel32 & 0x000000ff);
  pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
  pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
  rgb[out++] = pixel_24[0];
  rgb[out++] = pixel_24[1];
  rgb[out++] = pixel_24[2];
 }
 return 0;
}

int ProcessImage::convert_yuv_to_rgb_pixel(int y, int u, int v)
{
 unsigned int pixel32 = 0;
 unsigned char *pixel = (unsigned char *)&pixel32;
 int r, g, b;
 r = y + (1.370705 * (v-128));
 g = y - (0.698001 * (v-128)) - (0.337633 * (u-128));
 b = y + (1.732446 * (u-128));
 if(r > 255) r = 255;
 if(g > 255) g = 255;
 if(b > 255) b = 255;
 if(r < 0) r = 0;
 if(g < 0) g = 0;
 if(b < 0) b = 0;
 pixel[0] = r * 220 / 256;
 pixel[1] = g * 220 / 256;
 pixel[2] = b * 220 / 256;
 return pixel32;
}

 

#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;
}

 

#ifndef PROCESSIMAGE_H
#define PROCESSIMAGE_H
#include<QTcpServer>
#include<QTcpSocket>
#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;
    QTcpServer *server;
    QTcpSocket *socket;
    int check;
    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);
    void sendMessage();

};

#endif
#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

 

ARM端程序是在linux下开发的,需要在Linux下才能编译通过,不过建议先使用X11编译看到效果后,

之后在交叉编译,这样能更好的查错。因为交叉编译是看不到界面效果的。

 

 

https://files.cnblogs.com/li-zi/cap2.rar  ARM端源码

https://files.cnblogs.com/li-zi/Client.rar  PC端源码

posted @ 2012-12-01 14:23  桥段、  阅读(3141)  评论(3编辑  收藏  举报