前言

最近一直在尝试制作一个,网络摄像头,先后分别尝试了使用QT包装的UDP类TCP类,和LINUX中的socket编程等方式,但是非常遗憾,都没有取得非常好的播放效果。以为只要一帧一帧的传输视频数据就没有问题了,但是非常遗憾的是效果都不是非常好。因为对于数据的处理方法太过简单,不会写一些对于数据预先处理来减少数据的丢包,倒是播放出来的视频出现了如下的现象。
在这里插入图片描述
非常明显应为每一帧的图像之间出现了严重的粘连现象。搞了很久都没有找到解决问题的方法。最后还是选择了使用现成的开源框架mjpeg-streamer,并修改一些源码来实现自己功能。
网上很多的方法都是在浏览器中直接播放视频。但是项目需要一个上位机软件,然后我尝试了官方源码包中的那个QT上位机程序,但是好像应为版本的原因导致不能正常的编译。后来又在网上找了一些,拼拼凑凑总算搞定了。

软件部分

工程文件:

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
头文件:

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

源文件:

mainwindow.cpp

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


/* 构造和析构 */
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("客户端");
    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)
    {
      //获取服务器
       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="暂停";
    while(1)
    {
        if(isPicOnLabel==false)
        break;
        PicConnect(PU);
        //用作延时
        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="开始";
   isPicOnLabel=false;
}



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

    /* 取到当前显示的pixmap指针 */
    const QPixmap *pixmap = ui->label->pixmap();
    if(pixmap){
      /* 保存为jpg文件,并保证名字不相同 */
      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();
}

运行效果:

LINUX下:
在这里插入图片描述

Windows下

在这里插入图片描述

总结:

到目前为止视频的采集与播放基本已经搞定,下面我需要研究一些图像的编码与解码,包括使用ARM自身的硬编解码来对于图片快速的处理。同时还要进一步熟悉mjpeg-streamer源码。

工程源码:

mjpeg-clint

Logo

更多推荐