|
|
下面是一个简单的使用Qt Creator和OpenCV搭建可以播放RTSP视频的界面的示例。本例中为了展示更多读者可能需要的部分,比例较为详细:
|
|
|
|
|
|
首先,在Qt Creator中创建一个新的Qt Widgets应用程序。
|
|
|
|
|
|
添加QLabel作为显示视频图像的容器,并将该标签放置在MainWindow的UI界面上。
|
|
|
|
|
|
使用信号/槽机制连接QPushButton控件以提供“Play”和“Stop”按钮的功能。
|
|
|
|
|
|
在窗口的构造函数中,初始化OpenCV中的VideoCapture对象。此处调用set函数配置FrameRingBuffer的长度,从而满足读取较慢反应不够,其余只调用isOpened方法判断是否可正常读入即可。
|
|
|
|
|
|
稍后,你可以编写一个槽函数来读取视频流并将帧显示在QLabel中。
|
|
|
|
|
|
mainwindow.h文件:
|
|
|
|
|
|
cpp
|
|
|
#ifndef MAINWINDOW_H
|
|
|
#define MAINWINDOW_H
|
|
|
|
|
|
#include <QMainWindow>
|
|
|
#include <opencv2/core/mat.hpp>
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
namespace Ui { class MainWindow; }
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
|
class MainWindow : public QMainWindow
|
|
|
{
|
|
|
Q_OBJECT
|
|
|
|
|
|
public:
|
|
|
MainWindow(QWidget *parent = nullptr);
|
|
|
~MainWindow();
|
|
|
|
|
|
private slots:
|
|
|
void on_playButton_clicked();
|
|
|
|
|
|
void on_stopButton_clicked();
|
|
|
|
|
|
void readFrame();
|
|
|
|
|
|
private:
|
|
|
Ui::MainWindow *ui;
|
|
|
cv::VideoCapture mCapture; // Video capture object for reading RTSP stream
|
|
|
cv::Mat mFrame; // Mat object to store the video frame
|
|
|
bool mPlaying; // Flag to indicate if video playback is in progress
|
|
|
};
|
|
|
|
|
|
#endif // MAINWINDOW_H
|
|
|
mainwindow.cpp文件:
|
|
|
|
|
|
cpp
|
|
|
#include "mainwindow.h"
|
|
|
#include "ui_mainwindow.h"
|
|
|
|
|
|
#include <QDebug>
|
|
|
#include <QTimer>
|
|
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
|
: QMainWindow(parent)
|
|
|
, ui(new Ui::MainWindow)
|
|
|
{
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
// Set up VideoCapture object for reading RTSP stream
|
|
|
//调节参数 取决于对视频流带宽要求以及本机性能 适点即可
|
|
|
mCapture.set(cv::CAP_PROP_BUFFERSIZE,5);
|
|
|
mCapture.open("rtsp://localhost:8554/unicast"); //修改RTSP地址
|
|
|
|
|
|
if (!mCapture.isOpened())
|
|
|
{
|
|
|
qCritical() << "Failed to open RTSP stream.";
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//初始化mFrame和mPlaying标记
|
|
|
mPlaying = false;
|
|
|
|
|
|
//设置Paly按钮为不可用状态
|
|
|
ui->playButton->setEnabled(true);
|
|
|
ui->stopButton->setEnabled(false);
|
|
|
}
|
|
|
|
|
|
MainWindow::~MainWindow()
|
|
|
{
|
|
|
delete ui;
|
|
|
}
|
|
|
|
|
|
void MainWindow::on_playButton_clicked()
|
|
|
{
|
|
|
if (!mPlaying)
|
|
|
{
|
|
|
mPlaying = true;
|
|
|
|
|
|
// 每20毫秒读取一帧并在QLabel显示该帧图像
|
|
|
QTimer *timer = new QTimer(this);
|
|
|
connect(timer, &QTimer::timeout, this, &MainWindow::readFrame);
|
|
|
timer->start(20);
|
|
|
|
|
|
//设置控件状态
|
|
|
ui->playButton->setEnabled(false);
|
|
|
ui->stopButton->setEnabled(true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void MainWindow::readFrame()
|
|
|
{
|
|
|
if (mCapture.read(mFrame))
|
|
|
{
|
|
|
QImage frameImage((uchar*)mFrame.data, mFrame.cols, mFrame.rows, QImage::Format_RGB888);
|
|
|
QPixmap framePixmap = QPixmap::fromImage(frameImage.rgbSwapped());
|
|
|
// .rgbSwapped()因为OpenCV默认使用BGR,而Qt使用RGB,必须交换颜色通道才能正确地显示
|
|
|
|
|
|
ui->videoLabel->setPixmap(framePixmap.scaled(ui->videoLabel->size(), Qt::KeepAspectRatio));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void MainWindow::on_stopButton_clicked()
|
|
|
{
|
|
|
if (mPlaying)
|
|
|
{
|
|
|
mPlaying = false;
|
|
|
|
|
|
//停止计时器,断开信号/槽连接
|
|
|
QObject::disconnect(this, &MainWindow::readFrame, nullptr, nullptr);
|
|
|
|
|
|
//设置控件状态
|
|
|
ui->playButton->setEnabled(true);
|
|
|
ui->stopButton->setEnabled(false);
|
|
|
|
|
|
//清除QLabel
|
|
|
ui->videoLabel->clear();
|
|
|
}
|
|
|
}
|
|
|
注意,上述代码中的RTSP地址需要根据实际情况进行修改。在这里只是将RTSP的地址写为本机地址从而获得源不被限制的可播放视频。
|
|
|
|
|
|
此示例仅演示了如何从RTSP流读取一帧并在QLabel中显示该帧图像。你可以使用QSpinBox或QSlider等Qt控件来添加FPS和播放进度条的功能。以及像界面美化,异常处理,带宽控制和多线程优化等其余实现可能 Related Post 中可能会涉及。
|
|
|
|