本文內容截止Qt5.14版本。
Qt應該很早就提供了MultiMedia 這樣一個多媒體開發框架用於開發常見的音視頻處理。
比如音樂,視頻的播放。 做個簡單的音樂視頻播放器,在規定的平臺,用規定的格式,比如mp3 mac平臺播放mp4都沒什麼問題。
在linux平臺,Multimedia需要安裝 libpulse-dev依賴庫。
所以說,做個簡單的有限的格式的播放器,沒有什麼問題。
做pcm音頻採集,在windows linux平臺都沒什麼問題。mac 最好用原生的AVFoundation.
pcm音頻播放,windows沒什麼問題。mac最好還是用原生的API或者OpenAL播放pcm。
但是做視頻採集的時候,比如採集攝像頭,就有問題了。尤其是windows。
在macOS平臺,通過QVideoProbe 回調出來的QVideoFrame是ARGB32格式的。
在windows平臺,是不支持QVideoProbe 回調出YUV 或者RGB的。
在Linux上,通過QVideoProbe 回調出來的QVideoFrame是YV12格式的。
爲啥在windows上不支持視頻採集,官方給出了答案:
翻譯過來就是:
Windows的Qt Multimedia能是通過兩個插件實現的。一個使用Microsoft DirectShow API,另一個使用WMF(Windows Media Foundation)框架。 DirectShow API在Windows 98中引入,從Windows XP開始逐漸棄用。 Windows Vista中引入了Media Foundation框架,以替代DirectShow和其他多媒體API。因此,僅Windows Vista和更高版本的操作系統才支持Qt中的WMF插件。
限制:
Qt中的WMF插件當前不提供Camera後端。相反,DirectShow插件僅提供對Camera功能的有限支持。支持顯示取景器和捕獲靜止圖像等基本功能,但是,大多數Camera控制未實現。
當前不支持視頻錄製。此外,DirectShow插件不支持任何低級視頻功能,例如監視使用QVideoProbe或相關類播放或錄製的視頻幀。
綜上所述,如果我們需要實時採集攝像頭的圖像,進一步用x264編碼。想使用Qt,來偷懶做跨平臺開發,目前是做不到的,不同平臺還存在很多差異性。所以攝像頭採集,可以用OpenCV去做,跨平臺,簡單。
考慮到Qt良好的跨平臺性,在開發項目過程中,可以使用部分穩定可靠的一些簡單的功能,比如pcm音頻實時採集。其餘的功能,都是雞肋。做音視頻開發,還是用更專業的方式吧。需要學習 FFmpeg x264 OpenGL OpenCV 各個平臺原生的音視頻硬件編解碼等。
小廣告:
專業音視頻開發學習: https://edu.csdn.net/course/detail/2314
快速輕鬆學習Qt開發: https://edu.csdn.net/course/detail/24587 https://edu.csdn.net/course/detail/27479
附: QtMultiMedia 採集攝像頭源碼 只支持macOS Linux windows上會報錯,原因上面已經說清楚。
#ifndef USBCAMCAPTURE_H
#define USBCAMCAPTURE_H
#include <QWidget>
#include <QCamera>
#include <QVideoProbe>
#include <QVideoWidget>
class USBCamCapture : public QWidget
{
Q_OBJECT
public:
USBCamCapture(QWidget *parent = 0);
~USBCamCapture();
private:
QCamera* m_pUSBCamera;
QVideoWidget* m_pPreviewWidget;
QVideoProbe* m_pVideoProbe;
private:
void releaseCameraResources();
private slots:
void onCameraVideoFrameProbed(QVideoFrame frame);
};
#endif // USBCAMCAPTURE_H
#include "USBCamCapture.h"
#include<QHBoxLayout>
#include <QDebug>
USBCamCapture::USBCamCapture(QWidget *parent)
: QWidget(parent)
{
this->setWindowTitle("USBCamera Capture");
this->resize(640,400);
m_pUSBCamera = new QCamera("",NULL); //input usb cam name or default no name is ok
m_pPreviewWidget = new QVideoWidget(this);
QHBoxLayout* mainlayout = new QHBoxLayout();
mainlayout->addWidget(m_pPreviewWidget);
m_pUSBCamera->setViewfinder(m_pPreviewWidget);
m_pUSBCamera->start();
QCameraViewfinderSettings viewfinderSettings;
viewfinderSettings.setResolution(640,360);
viewfinderSettings.setPixelFormat(QVideoFrame::Format_YV12);
viewfinderSettings.setMaximumFrameRate(30);
m_pUSBCamera->setViewfinderSettings(viewfinderSettings);
m_pVideoProbe = new QVideoProbe(m_pUSBCamera);
connect(m_pVideoProbe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(onCameraVideoFrameProbed(QVideoFrame)));
m_pVideoProbe->setSource(m_pUSBCamera);
this->setLayout(mainlayout);
}
USBCamCapture::~USBCamCapture()
{
releaseCameraResources();
}
void USBCamCapture::releaseCameraResources()
{
if(m_pVideoProbe != NULL)
{
delete m_pVideoProbe;
m_pVideoProbe = NULL;
}
if(m_pUSBCamera != NULL)
{
m_pUSBCamera->stop();
delete m_pUSBCamera;
m_pUSBCamera = NULL;
}
}
void USBCamCapture::onCameraVideoFrameProbed(QVideoFrame videoFrame)
{
if (!videoFrame.map(QAbstractVideoBuffer::ReadOnly)){
return;
}
qDebug()<<"VideoFrame::"<<videoFrame.pixelFormat()<<videoFrame.width()<<videoFrame.height();
}
#include "USBCamCapture.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
USBCamCapture w;
w.show();
return a.exec();
}
#-------------------------------------------------
#
# Project created by QtCreator 2020-01-17T13:14:27
#
#-------------------------------------------------
QT += core gui multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = QtUSBCamera
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
USBCamCapture.cpp
HEADERS += \
USBCamCapture.h