当前位置:   article > 正文

Qt 6多媒体(Multimedia)模块变动:重塑与创新_qt6 qmediaplayer

qt6 qmediaplayer

一、Qt 6多媒体模块的转变与升级

Qt 6 是一个有意识地努力使框架更有效和易于使用的结果。尽管我们试图在每个版本中维持所有公共API的二进制和源代码兼容性,但为了使Qt成为一个更好的框架,一些改变是不可避免的。

Qt 6的Qt Multimedia模块替换了Qt 5.x的Qt Multimedia模块。使用Qt 5的Qt Multimedia的现有代码可以通过有限的努力进行移植。

Qt 6的新功能包括:

  • QMediaCaptureSession类是媒体捕获的中心对象。
  • QMediaRecorder类现在是一个仅限于录制音频和视频的类。它处理在捕获会话中产生的数据的编码。
  • 使用QMediaFormat和QMediaRecorder,设置录制时所需的编码已经发生了显著的变化。
  • 现在你也可以监控捕获会话录制的音频。
  • 当播放媒体文件时,已经添加了选择音频、视频和字幕轨道的支持。
  • QAudioDecoder现在在所有平台上都得到支持。

被移除的功能包括:

  • QMediaPlayer中的播放列表:Qt 6中的QMediaPlayer不再处理任何播放列表。
  • QMediaPlayList:这个类已经从API中移除。然而,它仍然作为媒体播放器示例的一部分存在。
  • QAudioProbe和QVideoProbe:音频和视频探测API已经被移除。
  • QAudioRecorder:使用QMediaCaptureSession或CaptureSession QML类型。
  • Audio QML类型:使用MediaPlayer QML类型。
  • QMediaObject和QMediaBindableInterface:这些类已经被移除,以支持使用例如setVideoOutput和QMediaCaptureSession的更直接的API来设置对象之间的连接。
  • QCameraViewFinderSettings:这个类已经被移除。使用QCameraFormat来定义相机应该使用的分辨率和帧率。
  • QMediaContent:这个类已经被移除。对于单个媒体文件,使用QUrl代替。
  • QSound:使用QSoundEffect代替。
  • QVideoFilterRunnable:在QML中使用着色器效果,或者在C++中访问QVideoFrame的内容。
  • 公共后端API:Qt 6的Qt Multimedia的后端API是私有的。这提高了支持新的多媒体用例的响应时间。在Qt 5中,任何包含“Control”或“Abstract”这些词的类名的类在Qt 6中现在都是私有的。
  • 后端插件:Qt 6的Qt Multimedia不再使用插件基础设施来处理其后端。这意味着用户不再需要将这些后端与他们的应用程序一起发布。相反,正在使用的后端是在编译时基于底层操作系统确定

QVideoSink类代表了视频数据的通用接收器。QVideoSink可以用来从Qt Multimedia逐帧检索视频数据。

QVideoSink将通过videoFrameChanged()信号向应用程序开发者提供单个视频帧。然后可以使用视频帧来读取这些帧的数据并进一步处理它们。当使用QPainter时,可以使用QVideoSink中的paint()方法绘制QVideoFrame。

QVideoFrame对象可能会消耗大量的内存或系统资源,因此应用程序不应该比所需的时间更长地保留它们。

QVideoSink类的属性包括:

  • subtitleText:返回当前的字幕文本。
  • videoSize:返回当前正在播放的视频的大小。如果没有视频正在播放,此方法返回一个无效的大小。

QVideoSink类的成员函数包括:

  • QVideoSink::QVideoSink(QObject *parent = nullptr):构造一个新的QVideoSink对象,带有parent。
  • [virtual] QVideoSink::~QVideoSink():销毁对象。
  • void QVideoSink::setSubtitleText(const QString &subtitle):设置当前的字幕文本。
  • void QVideoSink::setVideoFrame(const QVideoFrame &frame):设置当前的视频帧。
  • QVideoFrame QVideoSink::videoFrame() const:返回当前的视频帧。

QVideoSink类的信号包括:

  • [signal] void QVideoSink::videoFrameChanged(const QVideoFrame &frame) const:当视频帧改变时发出信号。

1.1 Qt 6多媒体模块的分类变化

在Qt 6中,多媒体模块的分类发生了显著的变化。在Qt 5.x中,多媒体模块被视为基础模块,而在Qt 6中,它被重新分类为附加模块。这种变化是Qt团队为了提高框架的效率和易用性而做出的有意识的努力的结果。

在Qt 5.x中,多媒体模块是一个基础模块,它提供了一套完整的多媒体功能,包括音频和视频的播放、录制、处理等。然而,这种设计在一些情况下可能会导致不必要的复杂性和冗余。例如,对于一些只需要基本音频功能的应用,可能不需要视频相关的功能,但在Qt 5.x中,这些功能仍然会被包含在内,这可能会导致应用的体积过大和性能下降。

为了解决这个问题,Qt 6将多媒体模块重新分类为附加模块。这意味着,开发者现在可以根据自己的需求选择是否使用多媒体模块,而不是像在Qt 5.x中那样,无论是否需要,都必须包含多媒体模块。这种变化使得Qt 6更加灵活,也更加符合实际开发需求。

此外,Qt 6的多媒体模块也进行了大规模的重构,使其更加高效和易用。例如,Qt 6引入了新的QMediaCaptureSession类,这是媒体捕获的中心对象。而在Qt 5.x中,媒体捕获的功能分散在多个类中,如QAudioRecorder和QVideoRecorder等,这可能会导致开发者在使用时感到困惑。而在Qt 6中,所有的媒体捕获功能都集中在QMediaCaptureSession类中,这使得开发者可以更加方便地进行媒体捕获相关的操作。

以下是一个使用QMediaCaptureSession进行媒体捕获的简单示例:

QMediaCaptureSession session;
QCamera camera;
QMediaRecorder recorder;

// 设置相机
session.setCamera(&camera);
// 设置录制器
session.setRecorder(&recorder);
// 开始捕获
session.start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这个示例展示了如何使用QMediaCaptureSession进行媒体捕获。

1.2 从Qt 5到Qt 6的迁移

Qt 6的多媒体模块是对Qt 5的多媒体模块的替代。尽管在这个过程中,一些API发生了变化,但是大部分的代码都可以通过有限的努力进行迁移。

例如,如果你在Qt 5中使用了QMediaPlayer类,那么在Qt 6中,你可以使用新的QMediaCaptureSession类来替代。虽然这两个类的名称和一些方法有所不同,但是它们的功能和用法是非常相似的。你只需要对你的代码进行一些小的修改,就可以完成从Qt 5到Qt 6的迁移。

// Qt 5
QMediaPlayer *player = new QMediaPlayer;
player->setMedia(QUrl("http://example.com/myfile.mp3"));
player->play();

// Qt 6
QMediaCaptureSession *session = new QMediaCaptureSession;
QMediaPlayer *player = new QMediaPlayer;
session->setPlayer(player);
player->setSource(QUrl("http://example.com/myfile.mp3"));
player->play();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

以上代码示例展示了如何从Qt 5迁移到Qt 6。在Qt 5中,我们创建了一个QMediaPlayer对象,并设置了媒体源,然后播放。而在Qt 6中,我们首先创建了一个QMediaCaptureSession对象,然后创建了一个QMediaPlayer对象,并将其设置为session的播放器,然后设置媒体源,最后播放。可以看到,虽然Qt 6的代码稍微复杂一些,但是它提供了更多的

控制和灵活性。

此外,Qt 6的多媒体模块还提供了一些新的特性,比如QMediaFormat和QMediaRecorder,这些新的特性使得设置和控制媒体的编码变得更加方便和高效。

// Qt 6
QMediaCaptureSession *session = new QMediaCaptureSession;
QMediaRecorder *recorder = new QMediaRecorder;
session->setRecorder(recorder);

QMediaFormat format = recorder->audioSettings().format();
format.setCodec(QMediaFormat::AAC);
recorder->audioSettings().setFormat(format);

recorder->setOutputLocation(QUrl("file:///home/user/myfile.aac"));
recorder->record();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在上述代码示例中,我们首先创建了一个QMediaCaptureSession对象和一个QMediaRecorder对象,并将recorder设置为session的录音机。然后,我们获取recorder的音频设置的格式,并将编码设置为AAC。最后,我们设置了输出位置,并开始录音。这个例子展示了如何使用Qt 6的新特性来控制媒体的编码。

总的来说,从Qt 5迁移到Qt 6虽然需要一些工作,但是Qt 6提供了更多的特性和更大的灵活性,这使得这个迁移过程是值得的。

1.3 Qt 6多媒体模块的重构

在Qt 6中,多媒体模块经过了大规模的重构。这个重构的目的是为了使Qt成为一个更好的框架,提供更高效和易用的API。

在重构过程中,一些类和方法被移除,一些新的类和方法被引入。例如,QMediaObject和QMediaBindableInterface这两个类被移除,取而代之的是更直接的API,如setVideoOutput和QMediaCaptureSession。这些变化使得在Qt 6中设置对象之间的连接变得更加直接和简单。

此外,Qt 6的多媒体模块不再使用插件架构。这意味着用户不再需要将这些后端插件与他们的应用程序一起发布。相反,正在使用的后端是在编译时根据底层操作系统确定的。例如,Qt在Linux上使用gstreamer,在Windows上使用WMF,在macOS和iOS上使用AVFoundation,在Android上使用Android多媒体API。

这个重构使得Qt 6的多媒体模块更加高效,更加易用,也更加符合实际的应用需求。虽然这个重构带来了一些变化,但是这些变化都是为了使Qt成为一个更好的框架


二、Qt 6多媒体模块的新特性(New Features in Qt 6 Multimedia Module)

2.1 QMediaCaptureSession类的引入(Introduction of QMediaCaptureSession Class)

在Qt 6多媒体模块中,引入了一个新的类:QMediaCaptureSession。这个类是媒体捕捉的中心对象,它为开发者提供了一个统一的接口,用于管理和控制媒体捕捉的过程。

在Qt 5中,媒体捕捉的过程需要通过多个不同的类进行管理,如QCamera、QAudioRecorder等。这种设计虽然灵活,但也使得代码的复杂度增加,对于开发者来说,需要花费更多的精力去理解和使用这些类。

而在Qt 6中,QMediaCaptureSession类的引入,使得媒体捕捉的过程变得更加简洁和直观。开发者只需要创建一个QMediaCaptureSession对象,然后通过其提供的方法,就可以轻松地进行媒体捕捉。

Qt 6的QMediaCaptureSession类中,并没有直接提供start方法。实际上,开启捕捉的操作是通过设置好各个组件(如QCamera、QMediaRecorder等),然后调用这些组件自身的start方法来实现的。我在这里向您道歉,对此造成的误解表示歉意。

在Qt 6中,QMediaCaptureSession类主要的作用是提供一个统一的接口,用于管理和控制媒体捕捉的过程。具体的媒体捕捉操作,如开启和停止捕捉,还是需要通过各个组件自身的方法来进行。

例如,如果我们想要进行视频捕捉,我们可以先创建一个QCamera对象和一个QMediaRecorder对象,然后通过QMediaCaptureSession的setCamera和setRecorder方法,将这两个对象关联到QMediaCaptureSession上。然后,我们可以调用QCamera的start方法来开启摄像头,调用QMediaRecorder的start方法来开始录制视频。

以下是一个简单的示例:

QMediaCaptureSession session;
QCamera camera;
QMediaRecorder recorder;

// 设置摄像头
session.setCamera(&camera);

// 设置媒体记录器
session.setRecorder(&recorder);

// 开启摄像头
camera.start();

// 开始录制
recorder.record();

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.2 QMediaRecorder类的变化与应用(Changes and Applications of QMediaRecorder Class)

在Qt 6的多媒体模块中,QMediaRecorder类经历了一些重要的变化。在Qt 5中,QMediaRecorder类的功能相对复杂,它不仅负责录制音频和视频,还负责处理数据的编码。然而,在Qt 6中,QMediaRecorder类的功能被限制为仅录制音频和视频,数据的编码工作则由QMediaCaptureSession类负责。

这种变化使得QMediaRecorder类的职责更加明确,也使得代码的结构更加清晰。开发者可以更加方便地使用QMediaRecorder类进行音频和视频的录制。

QMediaRecorder类是用于对QMediaCaptureSession中生成的媒体进行编码和录制的类。:

QMediaCaptureSession session;
QAudioInput audioInput;
session.setAudioInput(&input);
QMediaRecorder recorder;
session.setRecorder(&recorder);
recorder.setQuality(QMediaRecorder::HighQuality);
recorder.setOutputLocation(QUrl::fromLocalFile("test.mp3"));
recorder.record();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

可以看到,通过QMediaRecorder类,我们可以更加方便地进行音频和视频的录制。这是Qt 6多媒体模块的一个重要新特性,它将帮助开发者更加高效地开发媒体相关的应用。

2.3 QMediaFormat和QMediaRecorder的新应用(New Applications of QMediaFormat and QMediaRecorder)

在Qt 6的多媒体模块中,QMediaFormat和QMediaRecorder的使用方式发生了重大变化。在Qt 5中,设置录制的编码格式需要通过字符串来指定,这种方式虽然灵活,但也容易出错。而在Qt 6中,设置编码格式的方式变得更加直观和安全,我们可以通过枚举值来指定编码格式,这大大减少了出错的可能性。

QMediaFormat类在Qt 6中被引入,它提供了一种统一的方式来表示媒体的格式。通过QMediaFormat,我们可以方便地设置和获取媒体的编码格式、采样率、比特率等信息。

以下是一个使用QMediaFormat和QMediaRecorder进行录制设置的示例:

QMediaCaptureSession session;
QCamera camera;
QMediaRecorder recorder;

// 设置摄像头
session.setCamera(&camera);

// 设置媒体记录器
session.setRecorder(&recorder);

// 创建一个媒体格式对象
QMediaFormat format(QMediaFormat::MP4);

// 设置音频编码格式为AAC
format.setAudioCodec(QMediaFormat::AAC);

// 设置视频编码格式为H264
format.setVideoCodec(QMediaFormat::H264);

// 将媒体格式应用到记录器
recorder.setEncodingFormat(format);

// 开始录制
recorder.record();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这个示例中,我们首先创建了一个QMediaFormat对象format,并设置其文件格式为MP4。然后,我们通过setAudioCodecsetVideoCodec方法,设置了音频编码格式为AAC和视频编码格式为H264。接着,我们通过setEncodingFormat方法,将这个媒体格式应用到了记录器。最后,调用record方法,开始进行录制。

可以看到,通过QMediaFormat和QMediaRecorder,我们可以更加方便和安全地进行录制设置。这是Qt 6多媒体模块的一个重要新特性,它将帮助开发者更加高效地开发媒体相关的应用。

三、 Qt 6多媒体模块的移除特性(Removed Features in Qt 6 Multimedia Module)

3.1 QMediaPlayer的播放列表助手QMediaPlayList类移除

QMediaPlayer并不是Qt6新加的类,它在早期的Qt版本中就已经存在。这个类主要用于播放音频和视频文件,它提供了播放、暂停、停止等基本的媒体播放控制,以及获取媒体信息(如时长、状态等)的功能。

然而,QMediaPlayer本身并不直接支持播放列表(playlist)功能,这在Qt5中是由QMediaPlaylist类提供的。在Qt6中,QMediaPlaylist类已经被移除,Qt6并没有直接提供一个替代的类来支持播放列表功能。

如果你需要在Qt6中实现播放列表功能,你可能需要自己管理一个媒体URL列表,并在当前媒体播放结束后,通过QMediaPlayersetMedia()setSource()方法来设置下一个要播放的媒体。你可以通过连接QMediaPlayermediaStatusChanged信号,并在媒体状态变为QMediaPlayer::EndOfMedia时切换到下一个媒体,以实现播放列表的功能。

以下是一个简单的示例,说明你可能如何做到这一点:

#include <QMediaPlayer>
#include <QMediaContent>
#include <QList>

class MyPlayer : public QObject
{
    Q_OBJECT

public:
    MyPlayer(QObject *parent = nullptr)
        : QObject(parent)
        , m_player(new QMediaPlayer(this))
    {
        connect(m_player, &QMediaPlayer::stateChanged, this, &MyPlayer::onStateChanged);
    }

    void setPlaylist(const QList<QUrl> &urls)
    {
        m_playlist = urls;
    }

    void play()
    {
        if (!m_playlist.isEmpty())
        {
            m_player->setMedia(QMediaContent(m_playlist.first()));
            m_player->play();
        }
    }

private slots:
    void onStateChanged(QMediaPlayer::State state)
    {
        if (state == QMediaPlayer::StoppedState && !m_playlist.isEmpty())
        {
            m_playlist.removeFirst();
            if (!m_playlist.isEmpty())
            {
                m_player->setMedia(QMediaContent(m_playlist.first()));
                m_player->play();
            }
        }
    }

private:
    QMediaPlayer *m_player;
    QList<QUrl> m_playlist;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

在这个例子中,我们创建了一个新的类MyPlayer,用于管理媒体文件的播放列表。setPlaylist方法用于设置播放列表。play方法开始播放播放列表中的第一个媒体文件。当QMediaPlayer对象将其状态更改为StoppedState时,意味着当前媒体文件已经播放完毕。在这种情况下,我们从播放列表中移除第一个媒体文件,并开始播放下一个。

请注意,这只是一个非常基础的例子。根据你的需求,你可能想要添加更多的功能,如随机播放、重复播放等。


3.2 QAudioProbe和QVideoProbe的移除(Removal of QAudioProbe and QVideoProbe)

在Qt 6中,QAudioProbeQVideoProbe被移除了。根据Qt 6的多媒体变化文档,这两个类的功能已经被其他方式替代:

  • QAudioProbe:在Qt 6中,你可以使用QMediaCaptureSessionCaptureSession QML类型来替代QAudioProbe。你现在也可以监控捕获会话录制的音频。

  • QVideoProbe:在Qt 6中,QVideoProbe的功能可以通过使用QMediaCaptureSessionCaptureSession QML类型,或者通过在C++中访问QVideoFrame的内容来实现。

这些变化是为了使Qt成为一个更高效、易于使用的框架。虽然在每个版本中都试图保持所有公共API的二进制和源代码的兼容性,但为了使Qt成为一个更好的框架,一些变化是不可避免的。

QAudioProbe替代方案

在Qt 6中,QAudioProbeQVideoProbe被移除了。取而代之的是QMediaCaptureSession类,它是媒体捕获的中心对象。下面是一个使用QMediaCaptureSession的简单示例:

#include <QMediaCaptureSession>
#include <QMediaRecorder>
#include <QCamera>

// 创建一个媒体捕获会话
QMediaCaptureSession *captureSession = new QMediaCaptureSession;

// 创建一个媒体录制器
QMediaRecorder *recorder = new QMediaRecorder;

// 将录制器添加到捕获会话
captureSession->setRecorder(recorder);

// 创建一个摄像头对象
QCamera *camera = new QCamera;

// 将摄像头添加到捕获会话
captureSession->setCamera(camera);

// 开始摄像头
camera->start();

// 开始录制
recorder->record();

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

在这个示例中,我们创建了一个QMediaCaptureSession对象,然后创建了一个QMediaRecorder对象和一个QCamera对象。我们将这两个对象添加到了捕获会话中,然后分别启动了摄像头和录制器。

QVideoProbe替代方案

在Qt 6中,QVideoProbe的功能可以通过使用QMediaCaptureSessionCaptureSession QML类型,或者通过在C++中访问QVideoFrame的内容来实现。以下是一个使用QMediaCaptureSessionQVideoSink来访问视频帧的示例:

#include <QMediaCaptureSession>
#include <QCamera>
#include <QVideoSink>
#include <QVideoFrame>

// 创建一个媒体捕获会话
QMediaCaptureSession *captureSession = new QMediaCaptureSession;

// 创建一个摄像头对象
QCamera *camera = new QCamera;

// 将摄像头添加到捕获会话
captureSession->setCamera(camera);

// 创建一个视频接收器
QVideoSink *videoSink = new QVideoSink;

// 将视频接收器添加到捕获会话
captureSession->setVideoOutput(videoSink);

// 连接视频接收器的帧接收信号
QObject::connect(videoSink, &QVideoSink::videoFrame, [=](const QVideoFrame &frame){
    // 在这里处理视频帧
    // ...
});

// 开始摄像头
camera->start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这个示例中,我们创建了一个QMediaCaptureSession对象和一个QCamera对象,并将摄像头添加到了捕获会话中。然后我们创建了一个QVideoSink对象,并将其添加到了捕获会话中。我们连接了QVideoSinkvideoFrame信号,这样每当有新的视频帧时,我们就可以在槽函数中处理这个帧。最后,我们启动了摄像头。

四、Qt 6多媒体模块的变化特性(Changed Features in Qt 6 Multimedia Module)

4.1相机分辨率和帧率的处理变化(Changes in Handling of Camera Resolutions and Frame Rates)

在Qt 6中,相机分辨率和帧率的处理发生了变化。这些变化已经被简化,新的QCameraFormat类有助于选择相机的正确分辨率和帧率。

在Qt 5中,QCameraViewFinderSettings类被用来定义相机应使用的分辨率和帧率。然而,在Qt 6中,这个类已经被移除,取而代之的是使用QCameraFormat来定义相机应使用的分辨率和帧率。

这意味着在Qt 6中,你需要使用QCameraFormat类来设置和处理相机的分辨率和帧率,而不再使用QCameraViewFinderSettings类。这个改变可能会影响到之前使用Qt 5编写的代码,需要进行相应的修改和调整。
你可以在这里查看:QCameraFormat Class

一般来说,你可以创建一个QCameraFormat对象,然后使用其方法来设置你想要的分辨率和帧率。例如:

QCameraFormat format;
format.setResolution(1920, 1080);
format.setFrameRate(30.0);
  • 1
  • 2
  • 3

然后,你可以将这个格式应用到你的相机对象上:

camera->setViewfinderFormat(format);
  • 1

请注意,这只是一个基本的示例,实际使用时可能需要根据具体需求进行更多的设置和处理。

4.2 QAbstractVideoSurface到QVideoSink的变化(Changes in Handling of Camera Resolutions and Frame Rates)

在Qt 6中,QAbstractVideoSurface已被QVideoSink替代,这是一个重大的API变化。QVideoSink可以用来从Qt Multimedia逐帧检索视频数据。QVideoSink将通过videoFrameChanged()信号向应用程序开发者提供单个视频帧。然后可以使用视频帧来读取这些帧的数据并进一步处理它们。

在Qt 5中,你可能会使用QAbstractVideoSurface来处理视频帧。但在Qt 6中,你需要使用QVideoSink来接收视频帧。以下是一个简单的示例,说明如何在Qt 6中使用QVideoSink:

QMediaPlayer player;
QVideoSink videoSink;

// Connect the videoFrameChanged signal to a lambda function
QObject::connect(&videoSink, &QVideoSink::videoFrameChanged,
                 [&](QVideoFrame frame) {
                     // Process the video frame here
                 });

player.setVideoOutput(&videoSink);
player.setSource(QUrl::fromLocalFile("/path/to/your/video.mp4"));
player.play();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4.2.1 Qt 6中的QCamera和QVideoSink的代码示例

这是一个使用Qt 6中的QCamera和QVideoSink的代码示例,你可以在这个链接中找到完整的代码。以下是一些主要的代码片段:

// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "frames.hpp"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<Frames>("Frames", 1, 0, "Frames");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
// frames.hpp
#ifndef FRAMES_HPP_INCLUDED
#define FRAMES_HPP_INCLUDED

#include <QObject>
#include <QCamera>
#include <QVideoSink>

class Frames : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged)
    Q_PROPERTY(QVideoSink *videoSink READ videoSink CONSTANT)

public:
    explicit Frames(QObject *parent = nullptr);
    ~Frames();

    QCamera *camera() const;
    void setCamera(QCamera *camera);

    QVideoSink *videoSink() const;

signals:
    void cameraChanged();

private:
    QCamera *m_camera;
    QVideoSink *m_videoSink;
};

#endif // FRAMES_HPP_INCLUDED
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
// frames.cpp
#include "frames.hpp"
#include <QCameraInfo>
#include <QCameraFormat>
#include <QVideoFrame>

Frames::Frames(QObject *parent)
    : QObject(parent)
    , m_camera(new QCamera(QCameraInfo::defaultCamera(), this))
    , m_videoSink(new QVideoSink(this))
{
    m_videoSink->setSource(m_camera);

    QObject::connect(m_videoSink, &QVideoSink::videoFrame, [this](const QVideoFrame &frame) {
        // 在这里处理视频帧
    });

    m_camera->start();
}

Frames::~Frames()
{
    m_camera->stop();
}

QCamera *Frames::camera() const
{
    return m_camera;
}

void Frames::setCamera(QCamera *camera)
{
    if (m_camera == camera)
        return;

    m_camera = camera;
    emit cameraChanged();
}

QVideoSink *Frames::videoSink() const
{
    return m_videoSink;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

这个示例中,Frames类包含一个QCamera对象和一个QVideoSink对象。QCamera对象用于获取摄像头的视频流,QVideoSink对象用于接收和处理这个视频流。在Frames类的构造函数中,我们设置了QVideoSink的源为QCamera对象,并连接了QVideoSinkvideoFrame信号,这样每当有新的视频帧时,我们就可以在槽函数中处理这个视频帧。

注意,这只是一个基本的示例,实际使用时可能需要根据具体需求进行更多的设置和处理。

4.3 QMediaMetaData的元数据类型变化(Metadata Type Changes in QMediaMetaData)

在这个示例中,我们创建了一个QMediaPlayer和一个QVideoSink。我们将QVideoSink的videoFrameChanged信号连接到一个lambda函数,这个函数将处理每一个视频帧。然后,我们将QVideoSink设置为QMediaPlayer的视频输出,并设置视频源为一个本地文件。最后,我们调用play()方法来开始播放视频。

这个示例展示了如何在Qt 6中使用QVideoSink来处理视频帧,这是一个替代QAbstractVideoSurface的方法。

在Qt 6中,QMediaMetaData的元数据类型发生了显著的变化。主要的变化是从基于字符串的键转向基于枚举的键,以及减少支持的键的集合,只保留在大多数平台上可以支持的键。

在Qt 5中,QMediaMetaData使用字符串作为键来存储和检索元数据。这意味着你可以使用任何字符串作为键来存储元数据。然而,这种方法的问题是,不同的开发者可能会使用不同的字符串来表示相同的元数据,这可能会导致混淆和不一致。

为了解决这个问题,Qt 6的QMediaMetaData改为使用枚举作为键。这意味着你现在需要使用预定义的枚举值来存储和检索元数据。这种方法的优点是,所有的开发者都会使用相同的枚举值来表示相同的元数据,这可以确保一致性。

此外,Qt 6的QMediaMetaData减少了支持的键的集合。在Qt 5中,QMediaMetaData支持大量的键,但并非所有的键都可以在所有平台上使用。在Qt 6中,QMediaMetaData只支持那些可以在大多数平台上使用的键。这可以确保你的代码在不同的平台上有一致的行为。

这些变化可能会影响到已经使用QMediaMetaData的代码。如果你的代码依赖于使用字符串作为键,或者依赖于那些在Qt 6中不再支持的键,那么你可能需要修改你的代码以适应这些变化。

在Qt 5中,你可能会这样使用QMediaMetaData:

QMediaPlayer player;
player.setMedia(QUrl::fromLocalFile("/path/to/your/audio.mp3"));
player.play();

// Wait for the player to load the media and read the metadata
// ...

QVariant title = player.metaData("Title");
QVariant album = player.metaData("Album");
QVariant artist = player.metaData("Artist");
// ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在Qt 6中,你需要使用预定义的枚举值来存储和检索元数据,如下所示:

QMediaPlayer player;
player.setSource(QUrl::fromLocalFile("/path/to/your/audio.mp3"));
player.play();

// Wait for the player to load the media and read the metadata
// ...

QVariant title = player.metaData(QMediaMetaData::Title);
QVariant album = player.metaData(QMediaMetaData::Album);
QVariant artist = player.metaData(QMediaMetaData::Artist);
// ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这个示例中,我们使用QMediaMetaData::Title,QMediaMetaData::Album和QMediaMetaData::Artist这些预定义的枚举值来检索元数据。这些枚举值在所有的平台上都是一致的,这可以确保你的代码在不同的平台上有一致的行为。

五、被移除的功能原因以及替代方案

被移除的功能移除原因Qt 6中的替代方案
QMediaPlayer中的播放列表Qt 6中的QMediaPlayer不再处理任何播放列表
QMediaPlayList这个类已经从API中移除仍然作为媒体播放器示例的一部分存在
QAudioProbe和QVideoProbe音频和视频探测API已经被移除
QAudioRecorder使用QMediaCaptureSession或CaptureSession QML类型
Audio QML类型使用MediaPlayer QML类型
QMediaObject和QMediaBindableInterface这些类已经被移除使用例如setVideoOutput和QMediaCaptureSession的更直接的API来设置对象之间的连接
QCameraViewFinderSettings这个类已经被移除使用QCameraFormat来定义相机应该使用的分辨率和帧率
QMediaContent这个类已经被移除对于单个媒体文件,使用QUrl代替
QSound使用QSoundEffect代替
QVideoFilterRunnable在QML中使用着色器效果,或者在C++中访问QVideoFrame的内容
公共后端APIQt 6的Qt Multimedia的后端API是私有的
后端插件Qt 6的Qt Multimedia不再使用插件基础设施来处理其后端正在使用的后端是在编译时基于底层操作系统确定
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/376579
推荐阅读
相关标签
  

闽ICP备14008679号