‏הצגת רשומות עם תוויות qt. הצג את כל הרשומות
‏הצגת רשומות עם תוויות qt. הצג את כל הרשומות

יום שבת, 26 באפריל 2014

Displaying video and annotations using QT

The following code demonstrates displaying video and annotations using QT .
Capture.PNG3
The project is based on QT and libv4l2 library.

The QT project structure in the QT designer :
Capture3
The code :
capturethread.h

class CaptureThread : public QThread
{
public:
    explicit CaptureThread(QWidget *parent = 0);
    ~CaptureThread();
    bool devam;
    videowidget *parent;
    struct v4l2_format              fmt;
    struct v4l2_buffer              buf;
    struct v4l2_requestbuffers      req;
    enum v4l2_buf_type              type;
    fd_set                          fds;
    struct timeval                  tv;
    int                             r, fd;
    unsigned int                    n_buffers;
    char                            *dev_name;
    char                            out_name[256];
    FILE                            *fout;
    struct buffer {
            void   *start;
            size_t length;
    };
    static void xioctl(int fh, int request, void *arg)
    {
            int r;
            do {
                    r = v4l2_ioctl(fh, request, arg);
            } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
            if (r == -1) {
                    fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
                    return;
            }
    };
    void run();
    struct buffer  *buffers;
    void stopUlan();
    void startUlan();
};
#endif // CAPTURETHREAD_H

mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
    void on_pushButton_clicked();
private:
    Ui::MainWindow *ui;
    void pushButtonClicked();
};
#endif // MAINWINDOW_H

videowidget.h


#ifndef VIDEOWIDGET_H
#define VIDEOWIDGET_H
#include <QWidget>
#include <QPainter>
class videowidget : public QWidget
{
Q_OBJECT
public:
    explicit videowidget(QWidget *parent = 0);
    QImage img;
protected:
    void paintEvent(QPaintEvent *event);
signals:
public slots:
};
#endif // VIDEOWIDGET_H

capturethread.cpp


#include <QApplication>
#include <QDataStream>
#include <QString>
#include <QDebug>
#include <QBuffer>
#include <typeinfo>
#include <iostream>
#include <QFile>
#include "videowidget.h"
#include "capturethread.h"
CaptureThread::CaptureThread(QWidget *parent) :
    QThread()
{
    //qDebug()<<parent->objectName();
    this->parent=(videowidget*)parent;
    devam=false;
    fd = -1;
}
void CaptureThread::run(){
//do real stuff
fd = -1;
dev_name = "/dev/video0";
    fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
    if (fd < 0) {
           qDebug("Cannot open device");
           //exit(EXIT_FAILURE);
           return;
    }
    static struct v4lconvert_data *v4lconvert_data;
    static struct v4l2_format src_fmt;
    static unsigned char *dst_buf;
    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_RGB24;
    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
    xioctl(fd, VIDIOC_S_FMT, &fmt);
    if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
           printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
           //exit(EXIT_FAILURE);
           return;
    }
    if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
           printf("Warning: driver is sending image at %dx%d\n",
                   fmt.fmt.pix.width, fmt.fmt.pix.height);
    v4lconvert_data = v4lconvert_create(fd);
    if (v4lconvert_data == NULL)
        qDebug("v4lconvert_create");
    if (v4lconvert_try_format(v4lconvert_data, &fmt, &src_fmt) != 0)
        qDebug("v4lconvert_try_format");
    xioctl(fd, VIDIOC_S_FMT, &src_fmt);
    dst_buf = (unsigned char*)malloc(fmt.fmt.pix.sizeimage);
    CLEAR(req);
    req.count = 2;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;
    xioctl(fd, VIDIOC_REQBUFS, &req);
    buffers = (buffer*)calloc(req.count, sizeof(*buffers));
    for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
           CLEAR(buf);
           buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
           buf.memory      = V4L2_MEMORY_MMAP;
           buf.index       = n_buffers;
           xioctl(fd, VIDIOC_QUERYBUF, &buf);
           buffers[n_buffers].length = buf.length;
           buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
                         PROT_READ | PROT_WRITE, MAP_SHARED,
                         fd, buf.m.offset);
           if (MAP_FAILED == buffers[n_buffers].start) {
                   qDebug("mmap");
                   //exit(EXIT_FAILURE);
                   return;
           }
    }
    for (int i = 0; i < n_buffers; ++i) {
           CLEAR(buf);
           buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
           buf.memory = V4L2_MEMORY_MMAP;
           buf.index = i;
           xioctl(fd, VIDIOC_QBUF, &buf);
    }
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    xioctl(fd, VIDIOC_STREAMON, &type);
    int di=0;
    char header[]="P6\n640 480 255\n";
    devam = true ;
    while(devam){
        /* bu döngü datanın birikmesini sağlıyor */
        do {
                FD_ZERO(&fds);
                FD_SET(fd, &fds);
                /* Timeout. */
                tv.tv_sec = 2;
                tv.tv_usec = 0;
                r = select(fd + 1, &fds, NULL, NULL, &tv);
        } while ((r == -1 && (errno = EINTR)));
        if (r == -1) {
                qDebug("select");
                //exit(1) ;
                return;
        }
        CLEAR(buf);
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        xioctl(fd, VIDIOC_DQBUF, &buf);
        try{
            
        if (v4lconvert_convert(v4lconvert_data,
                                &src_fmt,
                                &fmt,
                                (unsigned char*)buffers[buf.index].start, buf.bytesused,
                                dst_buf, fmt.fmt.pix.sizeimage) < 0) {
                if (errno != EAGAIN)
                        qDebug("v4l_convert");
        }
        unsigned char* asil=(unsigned char*)malloc(fmt.fmt.pix.sizeimage+qstrlen(header));
        memmove(asil, dst_buf, fmt.fmt.pix.sizeimage);
        memmove(asil+qstrlen(header), asil, fmt.fmt.pix.sizeimage);
        memcpy(asil,header,qstrlen(header));
        QImage qq;//=new QImage(dst_buf,640,480,QImage::Format_RGB32);
        if(qq.loadFromData(asil,fmt.fmt.pix.sizeimage+qstrlen(header),"PPM")){
            if(parent->isVisible()){
                QImage q1(qq);
                parent->img=q1;
                parent->update();
              //this->msleep(50);
            }
        //qApp->processEvents();
            if(asil)
                free(asil);
        }
        }catch(...){}
        xioctl(fd, VIDIOC_QBUF, &buf);
        di++;
   }
    try{
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    xioctl(fd, VIDIOC_STREAMOFF, &type);
    for (int i = 0; i < n_buffers; ++i)
           v4l2_munmap(buffers[i].start, buffers[i].length);
        v4l2_close(fd);
    }catch(...){}
}
CaptureThread::~CaptureThread()
{
    try{
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    xioctl(fd, VIDIOC_STREAMOFF, &type);
    /*for (int i = 0; i < n_buffers; ++i)
           v4l2_munmap(buffers[i].start, buffers[i].length);*/
        v4l2_close(fd);
    }catch(...){}
    fd = -1;
}
void CaptureThread::stopUlan()
{
    devam=false;
    try{
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    xioctl(fd, VIDIOC_STREAMOFF, &type);
    /*for (int i = 0; i < n_buffers; ++i)
           v4l2_munmap(buffers[i].start, buffers[i].length);*/
        v4l2_close(fd);
    }catch(...){}
    fd = -1;
}
void CaptureThread::startUlan()
{
    this->start();
}
/*
void CaptureThread::onStopCapture()
{
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    xioctl(fd, VIDIOC_STREAMOFF, &type);
    for (int i = 0; i < n_buffers; ++i)
           v4l2_munmap(buffers[i].start, buffers[i].length);
    v4l2_close(fd);
}*/

main.cpp


#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    
    return a.exec();
}

mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "videowidget.h"
#include "capturethread.h"
#include <QtGui>
#include <QtGui/QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->pushButton->connect( ui->pushButton, SIGNAL( clicked() ), this, SLOT( pushButtonClicked() )  );
    connect ( ui->pushButton, SIGNAL( clicked() ), this, SLOT( pushButtonClicked() ) );
    QVBoxLayout* layout = new QVBoxLayout();
         layout->addWidget(new videowidget (ui->myFrame));
         ui->myFrame ->setLayout(layout);
         ui->myFrame->show();
}
void MainWindow::pushButtonClicked() // defined in .h under public/private slots:
{
    QMessageBox::information( this, "Information", "Just clicked Ui PushButton" ); // #include <QtGui/QMessageBox>
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_pushButton_clicked()
{
    QMessageBox::information( this, "Information", "Just clicked Ui PushButton" ); // #include <QtGui/QMessageBox>
}

videowidget.cpp


#include "videowidget.h"
#include "capturethread.h"
videowidget::videowidget(QWidget *parent) :
    QWidget(parent)
{
    setAutoFillBackground(true);
    //setObjectName("video göstergeci");
    CaptureThread * theCaptureThread = new CaptureThread (this);
    theCaptureThread->start ();
}
void videowidget::paintEvent(QPaintEvent *event) {
     try{
    QPainter painter(this);
        if(!img.isNull()){
            painter.drawImage(QPoint(0,0), img);
            painter.setPen(Qt::blue);
            painter.setFont(QFont("Arial", 30));
            painter.drawText(rect(), Qt::AlignCenter, "Qt");
        }
    }catch(...){}
}

The layout file :
Capture4
Note in order to capture the screen in linux ubuntu use the :
gnome-screenshot
command in bash shell‏



 


יום רביעי, 5 ביוני 2013

Create custom QT Widget

Define the main module that shows the widget

  1: #include <QtGui>
  2: #include "CustomWidget.h"
  3:  
  4: int main( int argc, char **argv )
  5: {
  6:   QApplication app( argc, argv );
  7:  
  8:   CustomWidget theCustomWidget;
  9:   CustomWidget.show();
 10:  
 11:   return app.exec();
 12: }

The custom widget header file  define a slot allows other modules to connect  in order to get mouse clicking events from the widget .


  1: #include <QtGui>
  2: #include <QWidget>
  3:  
  4: class CustomWidget : public QWidget
  5: {
  6:     Q_OBJECT
  7: public:
  8:    CustomWidget();
  9:  
 10: protected:
 11:     void paintEvent(QPaintEvent *event);
 12:   void mouseReleaseEvent ( QMouseEvent * e );
 13:     void mousePressEvent ( QMouseEvent * e );  
 14: private:
 15:   QPoint m_lastPoint;  
 16:     // member variable - flag of click beginning
 17:     bool mWasMouseClicking; 
 18:   
 19: signals:
 20:    void OnMouseClick(QPoint pPos);
 21: public slots:
 22: 
 23: private:
 24:   bool CheckIfPointInWidget (QPoint pPos);
 25:   int DistanceBetweenpoints (QPoint pFirstPt , QPoint pSecondPt);  
 26: };

The custom widget implementation cpp file.


  1: #include "CustomWidget.h"
  2:  
  3: void CustomWidget::paintEvent(QPaintEvent *event)
  4: {
  5:     //create a QPainter and pass a pointer to the device.
  6:     QPainter painter(this);
  7:  
  8:      painter.drawPolygon(polygon);
  9:  
 10:      //draw the widget for an example an ellipse
 11:      //Enables antialiasing, 
 12:    //set QPainter to use different
 13:      //color intensities on the edges to reduce the visual distortion that normally
 14:      //occurs when the edges of a shape are converted into pixels 
 15:      painter.setRenderHint(QPainter::Antialiasing, true);
 16:    
 17:    //Set the inner and the outer colors
 18:      painter.setPen(QPen(Qt::pink, 4, Qt::DashLine, Qt::RoundCap));
 19:      painter.setBrush(QBrush(Qt::blue, Qt::Dense5Pattern));
 20:      
 21:    painter.drawEllipse(200, 50, 250, 100);
 22:    }
 23:    
 24:    void CustomWidget::mousePressEvent ( QMouseEvent * e )
 25:   {
 26:     if ( CheckIfPointInWidget (e->pos()) == false )
 27:     {
 28:       return ;
 29:     }
 30:   
 31:     m_lastPoint = e->pos();
 32:     // set the flag meaning "click begin"
 33:     mWasMouseClicking = true;
 34:   }
 35:   void CustomWidget::mouseReleaseEvent ( QMouseEvent * e )
 36:   {
 37:     if (!mWasMouseClicking) )
 38:     {
 39:       return ;
 40:     }
 41:     
 42:     if ( CheckIfPointInWidget (e->pos()) == false )
 43:     {
 44:       mWasMouseClicking = false ;
 45:       return ;
 46:     }
 47:     
 48:     if ( Abs ( DistanceBetweenpoints (e->pos() , m_lastPoint) > 4 == true )
 49:     {
 50:       mWasMouseClicking = false ;
 51:       return ;
 52:     }  
 53:     emit OnMouseClick (e->pos());    
 54:   }

Sources:
http://www.youtube.com/watch?v=ScZn-cQiVFs&list=SP2D1942A4688E9D63
http://www.developer.nokia.com/Community/Wiki/MouseClick_event_in_Qt's_custom_widget
http://www.qtcentre.org/threads/19493-creating-custom-signa
http://harmattan-dev.nokia.com/docs/library/html/qt4/qbrush.html