阅读 1464

Qt 6中的Qt多媒体(Qt Multimedia in Qt 6)

Qt 6.2的第一个测试版刚刚发布,在其他多个新插件中,有一个全新的Qt多媒体模块。

Qt多媒体模块在Qt 6中经历了一些相当大的变化。在许多方面,它是一个新的API和实现,尽管我们重新使用了Qt 5.15中的一些代码。

虽然我们试图在Qt 5和Qt 6之间为我们的大多数模块保持尽可能多的源兼容性,但我们不得不在这里做大的改变,以使API和实现适合未来,最后决定以最好的API为目标,而不是最大的兼容性。如果你一直在Qt 5中使用Qt多媒体,你将需要对你的实现做一些改变。

这篇博文将试图引导你了解最大的变化,同时关注API和内部结构。

目标

Qt 5中的Qt多媒体有一个相当松散的定义范围。对API的不同部分的支持在不同的后端并不一致,而且API本身的某些部分也不容易以跨平台的方式使用。

对于Qt 6,我们试图在某种程度上缩小范围,并且正在努力建立一套在所有支持的平台上都能使用的一致的功能。我们还没有完全达到这个目标,但希望在Qt 6.2.0发布时能填补大部分的实现空白。

我们希望在Qt 6.2中支持的主要用例是。

  • 音频和视频播放

  • 音频和视频录制(从相机和麦克风)。

  • 低水平(基于PCM)音频和音频解码

  • 与Qt Quick和Widgets集成

  • 尽可能地使用硬件加速

据我们所知,这些功能涵盖了我们的用户在过去使用Qt多媒体的大部分用例。我们的目标是首先关注这些核心用例,并确保它们在我们所有的平台上运行一致,然后再扩展模块的新功能。

内部架构变化

Qt 5中的Qt多媒体有一个复杂的基于插件的架构,使用多个插件实现不同的前端功能。一个完整的多媒体后端实现将由不少于4个插件组成。用于实现这些插件的后端API是公开的,因此很难调整和改进这些后端的功能。

这种结构使得维护和开发模块非常困难。在Qt6中,我们选择了大幅简化,并删除了插件的基础设施。现在,后端在编译时被选择,并被编译到Qt多媒体的共享库中。现在只有一个涵盖所有多媒体的后端API,消除了我们在Qt 5中人为地分割成多个后端的情况。最后,我们选择了使后端API私有化,这样我们就可以在未来轻松地调整和扩展它。

一旦这样做了,我们就可以仔细看看我们需要的API和接口,以适应依赖于平台的后端代码。我们成功地将实现多媒体后端所需的类集从40个减少到15个,并减少了纯虚拟方法的数量,为许多非必要的功能提供了后备实现。

新的后端API在某种程度上是以我们在Qt Gui中用于窗口系统集成的QPA架构为模型的,新的QPlatformMediaIntegration类现在确实作为一个共同的入口点和工厂类来实例化依赖于平台的后端对象。在大多数情况下,我们现在的目标是在公共API中的类和实现该功能的类之间建立1对1的关系。因此,公共的QMediaPlayer API有一个QPlatformMediaPlayer类来实现平台依赖的功能。

通过这些改变,我们还可以删除大量在前端和后端之间重复的代码,并避免它们之间大量的调用转发。这样一来,我们也可以把很多跨平台的功能和验证转移到共享的、独立于平台的代码部分。

总的来说,这大大简化了我们的代码库,在不损失大量功能的情况下,大大减少了代码量。5.15版的Qt多媒体大约有140.000行代码,而我们目前在Qt 6中已经减少到大约74.000行代码。

支持的后端

在Qt 6中,我们也重新审视了支持的后端,并将这些后端减少到我们认为可以在未来支持的一组。在Qt 5中,我们在Windows上有三个完全不同的后端实现,使用DirectShow、WMF和一个单独的基于WMF的WinRT实现。

在Qt 6中,目前支持的集合是。

  • Linux,使用GStreamer

  • macOS和iOS使用AVFoundation

  • Windows使用WMF

  • 安卓系统使用MediaPlayer和Camera Java APIs

计划在Qt 6.3中对QNX提供支持。我们也可能在6.2版本的WebAssembly上实现低级别的音频工作。此外,我们还有使用PulseAudio或ALSA在Linux上支持低水平音频的代码,但这些代码目前还没有测试或支持。根据需求,我们可能会在以后的版本中把它们带回来。

公共API

Qt多媒体的公共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”; }复制代码

低电平音频

这个功能块有助于使用原始PCM数据进行低级别的音频,并直接向音频设备读写。

这个功能块在结构上仍然与我们在Qt 5中的功能相当相似,但很多细节已经改变。最值得注意的是,从音频设备中读取或写入的低级类已经改变了名称。它们现在被称为QAudioSource和QAudioSink。这个命名反映了它们的低级性质,并释放了我们在Qt 5中的旧名称(QAudioInput和QAudioOutput),用于播放和捕获API。

QAudioFormat API已经被清理和简化,现在支持4种最常用的PCM数据格式(8位无符号int,16和32位有符号int和浮点数据)。QAudioFormat还获得了新的API来处理音频通道的定位信息,但目前后端还没有完全支持。

我们还删除了被废弃的QSound类。QSoundEffect是它的替代品,用于播放低延迟的短声音。QSoundEffect目前仍然要求你使用WAV作为效果的格式,但我们计划在6.2之后对其进行扩展,允许通过该类播放压缩的音频数据。

播放

处理媒体文件播放的主要类是QMediaPlayer。QMediaPlayer的API已经比Qt 5简化了。 我们现在已经从该模块中删除了所有的播放列表功能,这些功能是内置于Qt 5媒体播放器的,但使其API和实现变得复杂。我们计划在6.2之后将播放列表功能作为一个单独的独立类,如果需要,你可以将其连接到QMediaPlayer。目前,如果需要,你可以在 "播放器 "的例子中找到一些处理播放列表的代码。

另一方面,QMediaPlayer获得了渲染字幕的能力,你现在可以使用setActiveAudioTrack()、setActiveVideoTrack()和setActiveSubtitleTrack()方法来检查和选择想要的音频、视频或字幕轨道。

Qt 6中的QMediaPlayer要求你使用setAudioOutput()和setVideoOutput()方法主动连接到音频和视频输出。不设置音频输出将意味着该媒体播放器不播放音频。这是对Qt 5的改变,在Qt 5中,默认的音频输出总是被选中。这个改变是为了让音频和视频之间有一个对称的API,并简化与QML的整合。

一个用C++实现的最小的媒体播放器看起来像这样。

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();复制代码

基于C++/Widgets的播放器例子有一个更完整的实现,它还具有支持字幕和音频语言选择以及显示与媒体文件相关的元数据的功能。

image.png

或使用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()
}复制代码

还有一个全新的基于QML的mediaplayer例子,使用Qt Quick控制,你可以玩一玩。

image.png

捕获和录制

捕捉和录制功能在Qt 6中经历了最大的API变化。在Qt 5中,你必须神奇地将相机连接到录音机上,而Qt 6现在提供了一个更明确的API来设置一个捕获的管道。

Qt 6中的核心类是QMediaCaptureSession。在录制音频/视频或捕捉图像时,总是需要这个类。为了设置音频录制的会话,你可以使用setAudioInput()将音频输入连接到会话中,如果你想从相机中录制,可以使用setCamera()将相机连接到会话中。

这里需要注意的一点是,QAudioInput和QCamera作为两个输入通道。要使用的物理设备是用QAudioInput::setDevice()或QCamera::setCameraDevice()选择的。一旦设备被选中,QAudioInput和QCamera允许你改变该设备的属性,如设置音量或相机的分辨率和帧率。

QMediaCaptureSession允许同时连接音频和视频输出,以达到预览和监控的目的。要拍摄静止图像,可以使用setImageCapture()将一个QImageCapture对象连接到它。

QMediaCaptureSession session;
QCamera camera;
session.addCamera(&camera);
QImageCapture imageCapture;
session.addImageCapture(&imageCapture);
camera.start();
imageCapture.captureToFile(“myimage.jpg”);复制代码

要录制音频和视频,需要将一个QMediaRecorder连接到会话。QMediaRecorder允许通过指定QMediaFormat来请求某种文件格式和编解码器进行录制。在Qt 6中,我们没有为不同的格式和编解码器提供一个跨平台的API,而是使用枚举。由于编解码器的支持与平台有关,你也可以查询QMediaFormat,了解支持的文件格式和编解码器的集合。后台也会一直尝试将请求的格式解析为被支持的格式。因此,如果你请求一个带有H265视频编解码器的MPEG4文件,但H265不被支持,它可能会退回到H264或其他被支持的编解码器。

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。


作者:jasper2021
链接:https://juejin.cn/post/7023969646596325383


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐