【USB网络摄像头】基于mjpeg-streamer的视频采集与播放【QT上位机软件】
前言最近一直在尝试制作一个,网络摄像头,先后分别尝试了使用QT包装的UDP类TCP类,和LINUX中的socket编程等方式,但是非常遗憾,都没有取得非常好的播放效果。以为只要一帧一帧的传输视频数据就没有问题了,但是非常遗憾的是效果都不是非常好。因为对于数据的处理方法太过简单,不会写一些对于数据预先处理来减少数据的丢包,倒是播放出来的视频出现了如下的现象。非常明显应为每一帧的图像之间出现了严...
前言
最近一直在尝试制作一个,网络摄像头,先后分别尝试了使用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源码。
工程源码:
更多推荐
所有评论(0)