關於Qt6中QtMultimedia多媒體模塊的重大改變分析
一、前言
1.Qt 6.2 的第一個測試版剛剛發佈,並在多個其他新附加組件中加入瞭全新的 Qt 多媒體模塊。Qt Multimedia 是一個模塊,它在 Qt 6 中發生瞭一些相當大的變化。
2.在很多方面,它是一個新的 API 和實現,即使我們重新使用瞭 Qt 5.15 中的一些代碼。雖然我們試圖為我們的大多數模塊保持 Qt 5 和 Qt 6 之間盡可能多的源代碼兼容性,但我們不得不在此處進行大量更改以使 API 和實現適合未來,最終決定以最好的為目標API 而不是最大的兼容性。
二、目標
Qt 5 中的 Qt 多媒體有一個相當松散定義的范圍
1.不同後端對 API 不同部分的支持並不一致,而且 API 本身的部分也不容易跨平臺使用。
2.對於 Qt 6,我們嘗試在一定程度上縮小范圍,並致力於開發一組一致的功能,這些功能適用於所有支持的平臺。我們還沒有達到這個目標,但希望通過 Qt 6.2.0 的發佈填補大部分實施空白。
3.據我們所知,這些功能涵蓋瞭我們用戶過去使用 Qt 多媒體的大部分用例。我們的目標是首先關註那些核心用例,並確保它們在我們的所有平臺上一致工作,然後再使用新功能擴展模塊。
我們希望在 Qt 6.2 中支持的主要用例是:
- 音頻和視頻播放
- 音頻和視頻錄制(來自相機和麥克風)
- 低級(基於 PCM)音頻和音頻解碼
- 與 Qt Quick 和小部件集成
- 盡量使用硬件加速
三、內部架構變化
Qt 5 中的 Qt 多媒體具有復雜的基於插件的架構
1.使用多個插件來實現不同的前端功能。一個完整的多媒體後端實現將包含不少於 4 個插件。用於實現這些插件的後端 API 是公開的,很難調整和改進這些後端的功能。
2.構建的架構非常難以維護和開發模塊。在 Qt6 中,我們選擇顯著簡化這一過程並移除插件基礎設施。現在在編譯時選擇後端並編譯到 Qt Multimedia 的共享庫中。現在隻有一個後端 API 涵蓋瞭所有多媒體,消除瞭我們在 Qt 5 中人為拆分成多個後端的問題。最後,我們選擇將後端 API 設為私有,以便我們將來可以輕松調整和擴展它。
3.完成後,我們可以仔細查看平臺相關後端代碼所需的 API 和接口。我們設法將實現多媒體後端所需的類集從 40 個減少到 15 個,並減少瞭純虛擬方法的數量,為許多非必要功能提供瞭後備實現。
4.新的後端 API 在某種程度上模仿瞭我們在 Qt Gui 中用於窗口系統集成的 QPA 架構,並且新的QPlatformMediaIntegration類現在確實作為一個通用的入口點和工廠類來實例化平臺相關的後端對象。在大多數情況下,我們現在的目標是在公共 API 中的類和實現該功能的類之間建立一對一的關系。因此,公共QMediaPlayer API 有一個QPlatformMediaPlayer類實現平臺相關功能。
5.通過這些更改,我們還可以刪除大量在前端和後端之間重復的代碼,並避免它們之間的大量呼叫轉移。有瞭這個,我們還可以將許多跨平臺功能和驗證移到代碼的共享、平臺獨立部分中。
6.總而言之,這極大地簡化瞭我們的代碼庫,並在不丟失大量功能的情況下大大減少瞭代碼大小。5.15 中的 Qt Multimedia 大約有 140.000 行代碼,而我們目前在 Qt 6 中減少到大約 74.000 行代碼。
四、支持的後端
在 Qt 6 中,我們還重新審視瞭支持的後端
1.並將其縮減為我們認為將來可以支持的一組。例如,在 Qt 5 中,我們在 Windows 上有三個完全不同的後端實現,使用 DirectShow、WMF 和一個單獨的基於 WMF 的 WinRT 實現。
2.Qt 6.3 計劃支持 QNX。我們可能還會在 6.2 中及時在 WebAssembly 上使用低級音頻。此外,我們仍有使用 PulseAudio 或 ALSA 在 Linux 上支持低級音頻的代碼,但目前尚未測試或支持這些代碼。根據需求,我們可能會在以後的版本中將它們帶回來。
在 Qt 6 中,當前支持的集合是:
- Linux,使用 GStreamer
- 使用 AVFoundation 的 macOS 和 iOS
- 使用 WMF 的 Windows
- 使用 MediaPlayer 和 Camera Java API 的 Android
五、公共API接口
Qt Multimedia的公共 API由 5 個大型功能塊組成
其中三個塊已經存在於 Qt 5 中,但是這些塊中的 API 發生瞭重大變化。功能塊是:
- 設備發現
- 低電平音頻
- 播放和解碼
- 捕獲和記錄
- 視頻輸出管道
在做新的 API 的時候,我們也希望在 C++ 和 QML 之間有一個統一的 API。這使我們可以刪除大量代碼,這些代碼隻是簡單地包裝瞭 C++ API 並以稍微不同的方式將其暴露給 QML。對於大多數公共 C++ 類,現在有一個相應的同名 QML 項。所以QMediaPlayer並例如具有相應QML MediaPlayer的具有相同的API作為C ++類的項目。
(一)設備發現
讓我們從設備發現開始。新的QMediaDevices 類旨在為您提供有關可用音頻和視頻設備的信息。它將允許您列出可用的音頻輸入(通常是麥克風)、音頻輸出(揚聲器和耳機)和攝像頭。您可以檢索默認設備,類還會通知您有關配置的任何更改,例如,當用戶連接外部耳機時。
QMediaDevices devices; connect(&devices, &QMediaDevices::audioInputsChanged, []() { qDebug() << “available audio inputs have changed”; }
(二)低電平音頻
1. 此功能塊有助於使用原始 PCM 數據處理低電平音頻,並直接從音頻設備讀取或寫入該數據。
2.這個塊在架構上仍然與我們在 Qt 5 中的非常相似,但很多細節都發生瞭變化。最值得註意的是,讀取或寫入音頻設備的低級類已更改名稱。它們現在稱為QAudioSource 和QAudioSink。命名反映瞭它們的低級性質,並釋放瞭我們在 Qt 5 中的舊名稱(QAudioInput和QAudioOutput)以用於播放和捕獲 API。
3.所述QAudioFormat API已被清理和簡化,現在支撐4最常用的PCM數據格式(8位無符號整型,16和32位有符號整數和浮點數據)。QAudioFormat還獲得瞭新的 API 來處理音頻通道的定位信息,但目前後端尚未完全支持。
4.我們還刪除瞭已棄用的QSound類。QSoundEffect是它以低延遲播放短聲音的替代品。QSoundEffect目前仍要求您使用 WAV 作為效果格式,但我們計劃擴展此格式,並允許在 6.2 之後通過類播放壓縮的音頻數據。
(三)回放
1.處理媒體文件播放的主要類是QMediaPlayer。該QMediaPlayer API已經從我們在Qt5簡化瞭我們必須從現在模塊去掉瞭所有的播放列表功能,這在過去是內置瞭Qt 5媒體播放器,但其復雜的API和實現。我們計劃在 6.2 之後將播放列表功能作為一個單獨的獨立類帶回來,然後您可以在需要時連接到QMediaPlayer。現在,如果需要,您可以在“播放器”示例中找到一些處理播放列表的代碼。
2.另一方面,QMediaPlayer獲得瞭渲染字幕的能力,您現在可以使用setActiveAudioTrack()、setActiveVideoTrack()和setActiveSubtitleTrack()方法檢查和選擇所需的音頻、視頻或字幕軌道。
3.Qt 6 中的 QMediaPlayer 要求您使用setAudioOutput()和setVideoOutput()方法將其主動連接到音頻和視頻輸出。不設置音頻輸出將意味著媒體播放器不播放音頻。這是對 Qt 5 的更改,在 Qt 5 中始終選擇默認音頻輸出。進行瞭更改以允許音頻和視頻之間的對稱 API 並簡化與 QML 的集成
4.除瞭QMediaPlayer 之外,Qt 6 還具有跨平臺支持,可以使用QAudioDecoder類將音頻文件解碼為原始 PCM 數據。該功能存在於 Qt 5 的某些平臺上,但並未在所有平臺上實現。
用 C++ 實現的最小媒體播放器如下所示:
//widget示例 QMediaPlayer player; QAudioOutput audioOutput; // chooses the default audio routing player.setAudioOutput(&audioOutput); QVideoWidget *videoOutput = new QVideoWidget; player.setVideoOutput(videoOutput); player.setSource(“mymediafile.mp4”); player.play(); //qml示例 Window { MediaPlayer { id: mediaPlayer audioOutput: AudioOutput {} // use default audio routing videoOutput: videoOutput source: “mymediafile.mp4” } VideoOutput { id: videoOutput anchors.fill: parent } Component.onCompleted: mediaPlayer.play() }
(四)捕獲和記錄
1.捕獲和記錄功能在 Qt 6 中經歷瞭最大的 API 更改。在 Qt 5 中,您必須神奇地將相機連接到記錄器,而 Qt 6 現在帶有更明確的 API 來設置捕獲管道。
2.Qt 6 中的中心類是QMediaCaptureSession。錄制音頻/視頻或捕獲圖像時始終需要此類。要設置錄音會話,您可以使用setAudioInput()將音頻輸入連接到會話,如果您想從相機錄制,請使用setCamera()將相機連接到它。
3.這裡要註意的一件事是QAudioInput和QCamera充當兩個輸入通道。使用QAudioInput::setDevice()或QCamera::setCameraDevice()選擇要使用的物理設備。選擇設備後,QAudioInput和QCamera允許您更改該設備的屬性,例如設置音量或相機的分辨率和幀速率。
4.QMediaCaptureSession允許將音頻和視頻輸出連接到它以進行預覽和監視。要拍攝靜止圖像,請使用setImageCapture()將QImageCapture對象連接到它。
5.要錄制音頻和視頻,請將QMediaRecorder連接到會話。QMediaRecorder允許通過指定一個請求記錄特定的文件格式和編解碼器QMediaFormat。在 Qt 6 中,我們沒有在此處提供跨平臺 API,使用不同格式和編解碼器的枚舉。
6.由於編解碼器支持取決於平臺,您還可以查詢QMediaFormat以獲取支持的文件格式和編解碼器集。後端也將始終嘗試將請求的格式解析為支持的格式。
7.因此,例如,如果您請求帶有 H265 視頻編解碼器的 MPEG4 文件,但不支持 H265,則它可能會回退到 H264 或其他受支持的編解碼器。
8.除瞭設置格式之外,您還可以在編碼器上設置其他屬性,例如質量、分辨率和幀率。
QMediaCaptureSession session; QCamera camera; session.addCamera(&camera); QImageCapture imageCapture; session.addImageCapture(&imageCapture); camera.start(); imageCapture.captureToFile(“myimage.jpg”); QMediaRecorder recorder; session.setRecorder(&recorder); QMediaFormat format(QMediaFormat::MPEG4); format.setAudioCodec(QMediaFormat::AudioCodec::AAC); format.setVideoCodec(QMediaFormat::VideoCodec::H265); recorder.setMediaFormat(format); recorder.setOutputLocation(“mycapture.mp4”); recorder.record();
(五)視頻管道
- 視頻管道已使用 Qt 6 完全重寫,試圖使其更易於用於自定義用例,並允許解碼和渲染的完整硬件加速以及在軟件中接收原始視頻數據。
- 這個 API 的大部分隻能從 C++ 訪問,在 QML 端,有一個VideoOutput QML 元素,但是可以很容易地連接到著色器效果之類的東西,或者可以用作 Qt Quick 3D 中材質的 sourceItem。
- 如果您使用 Qt Widgets,則QVideoWidget類可用作那裡視頻的輸出表面。
- 對於更底層的訪問,C++ 端的中心類是QVideoSink。QVideoSink可用於從媒體播放器或捕獲會話接收單個視頻幀。 然後可以將單個QVideoFrame對象映射到內存中,用戶必須準備好處理各種 YUV 和 RGB 格式,可以使用QPainter渲染或可以轉換為QImage。
六、未來的工作
在 6.2 之後,我們將研究待辦事項中的幾個項目
這些想法的優先級尚未完成,關於您的需求的反饋將在這裡幫助我們。我們的想法包括:
- 支持多視頻輸出
- 支持多攝像頭
- 支持多個音頻輸入
- 流媒體音頻/視頻
- 截屏
- 音頻混合
然而,目前,我們的大部分工作都集中在錯誤修復和為 Qt 6.2 做好一切準備上。由於較大的變化,在實現中仍然存在許多粗糙的邊緣,並且某些功能可能存在錯誤或缺少功能。我們的目標是在 6.2.0 中修復這些問題,但需要您的反饋才能這樣做。
最近發佈的 Qt 6.2 測試版確實有 Qt 多媒體的二進制文件,您可以輕松地嘗試和使用它們。我們非常感謝任何反饋,無論是在博客上還是在 bugreports.qt.io。
以上就是關於Qt6中QtMultimedia多媒體模塊的重大改變分析的詳細內容,更多關於QtMultimedia多媒體模塊改變的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- C++ Qt實現音視頻播放功能
- Python實現B站UP主自動監控功能詳解
- Android SurfaceView與TextureView使用方法詳細講解
- Python 流媒體播放器的實現(基於VLC)
- 如何利用Python實現簡易的音頻播放器