當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Qt 5.6以上版本的MJPG-STREAMER視頻播放實現(xiàn)
主機(jī):Windows 7
Qt:5.9.1
MJPG-streamer是一款免費(fèi)基于IP地址的視頻流服務(wù)器,它的輸入插件從攝像頭讀取視頻數(shù)據(jù),這個輸入插件產(chǎn)生視頻數(shù)據(jù)并將視頻數(shù)據(jù)復(fù)制到內(nèi)存中,它有多個輸出插件將這些視頻數(shù)據(jù)經(jīng)過處理,其中重要的輸出插件是網(wǎng)站服務(wù)器插件,它將視頻數(shù)據(jù)傳送到用戶瀏覽器中,MJPG-streamer的工作就是將其中的一個輸入插件和多個輸出插件綁定在一起,所有的工作都是通過它的各個插件完成的。如果攝像頭直接支持MJPEG格式的話,MJPG-streamer可以快速獲得圖片,并發(fā)送給Web客戶端進(jìn)行顯示。整個過程中不涉及到圖片格式轉(zhuǎn)換,視頻壓縮處理方面工作,僅僅涉及到數(shù)據(jù)轉(zhuǎn)發(fā)的工作,所以在性能較低的嵌入式Linux平臺上也可以比較流暢的工作。
因為MJPG-streamer是基于HTTP協(xié)議的,所以只需要有一個Web瀏覽器,輸入正確的網(wǎng)址就能觀看到視頻。但如果要將視頻顯示在一個桌面應(yīng)用的話,則需要進(jìn)行一些編碼操作。在Qt5.4到Qt5.6的版本中繼承了Web Kit,可以很方便地請求網(wǎng)頁數(shù)據(jù)并進(jìn)行顯示。如果要播放MJPG-streamer視頻的話,則可以通過連續(xù)不斷地請求單張JPEG圖片并進(jìn)行顯示即可。對圖片的請求和顯示的典型代碼如下:
ui->webView->setUrl(QUrl("//192.168.1.1:8080/?action=snapshot"));
ui->webView->update();
但是在Qt 5.6之后,Web Kit被刪除了,取而代之的是更強(qiáng)大的WebEngine。要實現(xiàn)上面的功能,可以通過下面的代碼來實現(xiàn)。
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected slots:
void showPicture();
private:
Ui::Widget *ui;
// 用于發(fā)送請求并獲得響應(yīng)
QNetworkAccessManager manager;
// 響應(yīng)的內(nèi)容
QNetworkReply *reply;
};
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
// 發(fā)起獲取單張圖片的請求
QUrl url("//127.0.0.1:8080/?action=snapshot");
reply = manager.get(QNetworkRequest(url));
// 完整接收到響應(yīng)的數(shù)據(jù)后調(diào)用showPicture槽函數(shù)
connect(reply, SIGNAL(finished()), this, SLOT(showPicture()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::showPicture()
{
// 從響應(yīng)中獲取圖片數(shù)據(jù),并顯示在QLabel上
QByteArray jpegData = reply->readAll();
QPixmap pixmap;
pixmap.loadFromData(jpegData);
ui->labelPic->setPixmap(pixmap);
delete reply;
// 繼續(xù)發(fā)起請求,以便以快速度刷新圖片
QUrl url("//127.0.0.1:8080/?action=snapshot");
reply = manager.get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(showPicture()));
}
注意,上面的代碼對圖片連續(xù)顯示形成視頻的核心在于:顯示完圖片后立即發(fā)起下一次請求。另外,因為reply每次都不一樣,所以要對新的對象建立信號和槽的連接。