[USB webcam] video acquisition and playback based on MJPEG streamer [QT upper computer software]

Preface

Recently, I've been trying to make a webcam. I've tried to use the UDP class of QT packaging and the socket programming in LINUX, but unfortunately, I haven't achieved a very good playback effect. I thought that as long as one frame of video data transmission is no problem, but unfortunately the effect is not very good. Because the data processing method is too simple to write some data pre-processing to reduce data packet loss, but the video played out has the following phenomenon.

It is obvious that there is serious adhesion between the images of each frame. I haven't found a solution to the problem for a long time. Finally, I choose to use the existing open source framework MJPEG streamer, and modify some source code to achieve their own functions.
Many methods on the Internet are to play the video directly in the browser. But the project needs a host computer software, and then I tried the QT host computer program in the official source package, but it seems that due to the version, it can not be compiled normally. Later, I found some on the Internet, and finally I got it.

Software part

Engineering documents:

mjpeg-clint.pro

#-------------------------------------------------
#
# Project created by QtCreator 2020-03-08T18:33:52
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = mjpeg-clint
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui
Head file:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QUrl>
#include <QPixmap>
#include <QFile>
#include <QPicture>
#include <QMessageBox>
#include <QMainWindow>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include<QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:

    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void PicConnect(QString p);
    void SetWindow();
    void ShowPic();
    void StopPic();

private slots:
    void on_buttonstart_clicked();

    void on_buttonsnapshot_clicked();

    void on_buttonclose_clicked();


public slots:

    void slot_replyFinished(QNetworkReply* reply);

private:
    Ui::MainWindow *ui;
    //connect to picture
    QNetworkAccessManager *manager;
    bool isPicOnLabel;
    QImage* img=new QImage,* scaledimg=new QImage;
    QNetworkRequest request;
    QString ip;
    qint16 port;
    QString PU;

};

#endif // MAINWINDOW_H

Source files:

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"


/* Structure and analysis */
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("Client");
    PU="http://192.168.0.18:8080/?action=snapshot";
    manager = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slot_replyFinished(QNetworkReply*)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::PicConnect(QString PicUrl)
{
    request.setUrl(QUrl(PicUrl));
    manager->get(request);
}

void MainWindow::slot_replyFinished(QNetworkReply* reply)
{
     QByteArray data = reply->readAll();
     img->loadFromData(data, "JPG");
}



void MainWindow::on_buttonstart_clicked()
{
    if(isPicOnLabel==false)
    {
      //Get server
       ip=ui->lineEditIP->text();
       port=ui->lineEditPORT->text().toInt();
       PU=QString("http://"+ip+":"+tr("%1").arg(port)+"/?action=snapshot");
      ShowPic();
    }
    else
    {
      StopPic();
    }
}

void MainWindow::ShowPic()
{
    isPicOnLabel=true;
    QString name="suspend";
    while(1)
    {
        if(isPicOnLabel==false)
        break;
        PicConnect(PU);
        //Used as time delay
        QEventLoop eventloop;
        QTimer::singleShot(10, &eventloop, SLOT(quit()));
        eventloop.exec();
         *scaledimg=img->scaled(640,480,Qt::KeepAspectRatio);
         ui->label->setPixmap(QPixmap::fromImage(*scaledimg));
     }
}


void MainWindow::StopPic()
{
   QString name="start";
   isPicOnLabel=false;
}



void MainWindow::on_buttonsnapshot_clicked()
{
    QDate date;
    QTime time;

    /* Get pixmap pointer to current display */
    const QPixmap *pixmap = ui->label->pixmap();
    if(pixmap){
      /* Save as a jpg file and make sure the names are different */
      pixmap->save("./"+date.currentDate().toString("yyyy,MM,dd")+"-"+
                     time.currentTime().toString("hh;mm;ss")+".jpg");
      QMessageBox::about(this, " ", "Save Successed!");
    }
}

void MainWindow::on_buttonclose_clicked()
{
     this->close();
}

Operation effect:

LINUX:

Under Windows

Conclusion:

So far, video acquisition and playback have been basically completed. Next, I need to study some image coding and decoding, including the use of ARM's own hard coding and decoding to process images quickly. At the same time, I need to be more familiar with MJPEG streamer source code.

Project source code:

mjpeg-clint

64 original articles published, 62 praised, 10000 visitors+
Private letter follow

Tags: Qt Linux snapshot socket

Posted on Wed, 11 Mar 2020 03:29:25 -0400 by cahamilton