关于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();

(五)视频管道

  1. 视频管道已使用 Qt 6 完全重写,试图使其更易于用于自定义用例,并允许解码和渲染的完整硬件加速以及在软件中接收原始视频数据。
  2. 这个 API 的大部分只能从 C++ 访问,在 QML 端,有一个VideoOutput QML 元素,但是可以很容易地连接到着色器效果之类的东西,或者可以用作 Qt Quick 3D 中材质的 sourceItem。
  3. 如果您使用 Qt Widgets,则QVideoWidget类可用作那里视频的输出表面。
  4. 对于更底层的访问,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多媒体模块改变的资料请关注我们其它相关文章!

(0)

相关推荐

  • 将Qt项目升级到Qt6吐血经验总结

    Qt的版本发布越来越频繁,Qt6发布已经有一段时间了,越来越多的人咨询之前的代码是否可以增加对Qt6的支持,包括开源的项目QWidgetDemo(一年时间超过2.6K star),近期百忙之中,对所有项目进行了Qt6的兼容升级,自此所有项目从Qt4兼容到了Qt6,耗时一个多月,总计更新调整代码行数一万多行.虽然更新工作量不是很大,但还是废了九牛二虎之力,毕竟项目数太多,光几十个项目作品中的其中之一自定义控件就188个子项目,为了方便自己也为了总结分享经验,特意整理了从Qt4兼容到Qt6的一些经验

  • 教你如何使用qt quick-PathView实现好看的home界面

    PathView ,顾名思义,沿着特定的路径显示 Model 内的数据. Model 能够是 QML 内建的 ListModel . XmlListModel ,也能够是在 C++ 中实现的 QAbstractListModel 的派生类. PathView 恐怕是 Qt Quick 提供的 Model-View 类库中最复杂也最灵活的一个了. 要使用一个 PathView ,至少须要设置 model . delegate . path 三个属性.     model . delegate 假设

  • pyqt5简介及安装方法介绍

    本文研究的主要是pyqt5简介及安装方法介绍的有关内容,具体如下. pyqt5介绍 pyqt5是一套Python绑定Digia QT5应用的框架.它可用于Python 2和3.本教程使用Python 3.Qt库是最强大的GUI库之一.pyqt5的官方网站 http://www.riverbankcomputing.co.uk/news pyqt5做为Python的一个模块,它有620多个类和6000个函数和方法.这是一个跨平台的工具包,它可以运行在所有主要的操作系统,包括UNIX,Windows

  • Qt 使用Poppler实现pdf阅读器的示例代码

    开发环境 Qt5.5.1.Qt Creator 3.5.1 Qt实现pdf阅读器和MFC实现pdf阅读器,其实原理都是差不多的. 需要用到Poppler开源库,下载地址如下 https://poppler.freedesktop.org/ 如果只是要在window的gcc下运行的话,可以下载已经编译好的库 https://sourceforge.net/projects/poppler-win32/ 注意:这个是MinGW版本的Qt,也就是运行在GCC环境下的库,里面只包含 *.dll 和 *.

  • 关于Qt6中QtMultimedia多媒体模块的重大改变分析

    一.前言 1.Qt 6.2 的第一个测试版刚刚发布,并在多个其他新附加组件中加入了全新的 Qt 多媒体模块.Qt Multimedia 是一个模块,它在 Qt 6 中发生了一些相当大的变化. 2.在很多方面,它是一个新的 API 和实现,即使我们重新使用了 Qt 5.15 中的一些代码.虽然我们试图为我们的大多数模块保持 Qt 5 和 Qt 6 之间尽可能多的源代码兼容性,但我们不得不在此处进行大量更改以使 API 和实现适合未来,最终决定以最好的为目标API 而不是最大的兼容性. 二.目标 Q

  • Qt6中重大改变的QtMultimedia多媒体模块实现

    目录 一.前言 二.目标 三.内部架构变化 四.支持的后端 五.公共API接口 (一)设备发现 (二)低电平音频 (三)回放 (四)捕获和记录 (五)视频管道 六.未来的工作 一.前言 Qt 6.2 的第一个测试版刚刚发布,并在多个其他新附加组件中加入了全新的 Qt 多媒体模块.Qt Multimedia 是一个模块,它在 Qt 6 中发生了一些相当大的变化. 在很多方面,它是一个新的 API 和实现,即使我们重新使用了 Qt 5.15 中的一些代码.虽然我们试图为我们的大多数模块保持 Qt 5

  • Nodejs中使用captchapng模块生成图片验证码

    Nodejs项目,在做图片验证码的时候遇到了难题.Nodejs没有图片库,以后会有,但是现在没有. 网络上搜索一圈,有几个解决方案: 1.采用第三方验证码程序,有的时候,项目可能不允许: 2.使用Java或者PHP生成图片,Nodejs调用,中间采用Redies共享: 这两种方式都不太理想,好在终于找到了可以支持Nodejs图片验证码的一个库,虽然只支持数字,但是也还不错.原理是使用Base64的图片编码方式. 这个库的Gighub地址是:https://github.com/GeorgeCha

  • 在Python中使用itertools模块中的组合函数的教程

    理解新概念 Python V2.2 中引入了迭代器的思想.唔,这并不十分正确:这种思想的"苗头"早已出现在较老的函数 xrange() 以及文件方法 .xreadlines() 中了.通过引入 yield 关键字,Python 2.2 在内部实现的许多方面推广了这一概念,并使编程定制迭代器变得更为简单( yield 的出现使函数转换成生成器,而生成器反过来又返回迭代器). 迭代器背后的动机有两方面.将数据作为序列处理通常是最简单的方法,而以线性顺序处理的序列通常并不需要都同时实际 存在

  • 详解python时间模块中的datetime模块

    Python提供了多个内置模块用于操作日期时间,像calendar,time,datetime.time模块我在之前的文章已经有所介绍,它提供的接口与C标准库time.h基本一致.相比于time模块,datetime模块的接口则更直观.更容易调用. 1.datetime中包含三个类date ,time,datetime 函数datetime.combine(date,time)可以得到dateime,datetime.date().datetime.time()可以获得date和time 2.d

  • Python中使用select模块实现非阻塞的IO

    Socket的英文原义是"孔"或"插座".作为BSD UNIX的进程通信机制,取后一种意思.通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务.Socket正如其英文原意那样,像一个多孔插座.一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110

  • 深入理解python中的select模块

    简介 Python中的select模块专注于I/O多路复用,提供了select  poll  epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统) select方法 进程指定内核监听哪些文件描述符(最多监听1024个fd)的哪些事件,当没有文件描述符事件发生时,进程被阻塞:当一个或者多个文件描述符事件发生时,进程被唤醒. 当我们调用select()时: 1.上下文切换转换为内核态 2.将fd从用户空间复制到内核空

  • 使用Python中的tkinter模块作图的方法

    python简述: Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.自从20世纪90年代初Python语言诞生至今,它逐渐被广泛应用于处理系统管理任务和Web编程.Python[1]已经成为最受欢迎的程序设计语言之一.2011年1月,它被TIOBE编程语言排行榜评为2010年度语言.自从2004年以后,python的使用率是呈线性增长. tkinter模块介绍 tkinter模块("Tk 接口")是Python的标准Tk GUI工具包的接口.Tk和Tkinter可以

  • 使用Python标准库中的wave模块绘制乐谱的简单教程

    在本文中,我们将探讨一种简洁的方式,以此来可视化你的MP3音乐收藏.此方法最终的结果将是一个映射你所有歌曲的正六边形网格地图,其中相似的音轨将处于相邻的位置.不同区域的颜色对应不同的音乐流派(例如:古典.嘻哈.重摇滚).举个例子来说,下面是我所收藏音乐中三张专辑的映射图:Paganini的<Violin Caprices>.Eminem的<The Eminem Show>和Coldplay的<X&Y>. 为了让它更加有趣(在某些情况下更简单),我强加了一些限制.

  • 解析Nginx中的日志模块及日志基本的初始化和过滤配置

    无论在任何项目中,日志都是一个非常重要的模块,无论是问题定位还是日常信息的管理,都离不开他 在nginx中,ngx_errlog_module模块专门用于处理nginx日志信息,是nginx的core模块之一 在 main 函数中,时间初始化结束后马上进行的就是日志模块的初始化 日志结构: 日志模块的初始化主要做的事情就是初始化全局变量 ngx_log,并创建 errlog 文件 ngx_log_s 结构 ngx_log 变量是一个 ngx_log_s 结构体,定义在 core/ngx_log.

随机推荐