当前位置:   article > 正文

Qt 视频播放_qt中视频播放

qt中视频播放

一、简介

  Qt对音视频的播放和控制,相机拍照,收音机等多媒体应用提供了强大的支持。Qt5使用了全新的Qt Multimedia模块来实现多媒体应用,而原来Qt4中用于实现多媒体功能的Phonon模块已经被移除。

  新的Qt Multimedia模块提供了丰富的接口,使读者可以轻松地使用平台的多媒体功能,例如,进行多媒体播放,使用相机和收音机等。该模块还分别提供了一组QML类型和一组C++类来处理多媒体内容。

C++ 中多媒体模块可以实现的功能,对应的示例程序以及需要使用的C++类如:

  Qt的多媒体接口建立在底层平台的多媒体框架之上,这就意味着对于各种编解码器的支持依赖于使用的平台。如果要访问一些平台相关的设置,或者将Qt多媒体接口移植到新的平台,则可以参考Qt帮助中的Multimedia Backend Development文档。

  另外,如果要使用多媒体模块中的内容,则需要在.pro项目文件中添加如下代码,引入多媒体模块:

QT += multimedia

二、几个主要类介绍

QMediaPlayer

提供给外部应用程序的主要API,应用程序可以通过调用其成员函数play,setVolume,setPosition等控制视频文件的播放。大部分成员函数都是通过调用QMediaPlayerControl类型指针的方法来实现的。

QMediaControl

控制媒体的抽象类,包含大量控制媒体的成员函数。

QMediaServiceProvider

提供媒体服务的抽象类,主要功能是requestService得到QMediaService对象。

QPluginServiceProvider

QPluginServiceProvider继承QMediaServiceProvider类,通过requestService方法给QMediaPlayer提供QMediaService

QMediaService

媒体服务的抽象类,主要功能是requestControl得到QMediaControl对象。

QMediaServiceProviderPlugin

所有提供媒体服务的plugin都必须继承这个抽象类。create成员函数用来得到实现后的QMediaService派生类实例的指针,key成员函数用来得到一个QStringList,里面包含这个plugin中能提供的所有媒体服务的id。

注:由于一个plugin可能包含几个QMediaServiceProvider的实现,一个QMediaServiceProvider的实现又可能提供几个QMediaService的实现,一个QMediaService的实现也可能提供几个QMediaControl的实现...所以他们的每个派生类都有一个id来识别。

名字

QMediaServiceProviderPlugin

QMediaService

directshow

DSServicePlugin

DSCameraService、DirectShowPlayerService

windowsmediafoundation

WMFServicePlugin

MFPlayerService/MFAudioDecoderService

gstreamer

QGstreamerPlayerServicePlugin

QGstreamerPlayerService

三、QMediaServiceProvider

提供媒体服务的抽象类,主要功能是requestService得到QMediaService对象

  1. class QMediaService;
  2. class Q_MULTIMEDIA_EXPORT QMediaServiceProvider : public QObject
  3. {
  4. Q_OBJECT
  5. public:
  6. virtual QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint = QMediaServiceProviderHint()) = 0;
  7. virtual void releaseService(QMediaService *service) = 0;
  8. virtual QMediaServiceProviderHint::Features supportedFeatures(const QMediaService *service) const;
  9. virtual QMultimedia::SupportEstimate hasSupport(const QByteArray &serviceType,
  10. const QString &mimeType,
  11. const QStringList& codecs,
  12. int flags = 0) const;
  13. virtual QStringList supportedMimeTypes(const QByteArray &serviceType, int flags = 0) const;
  14. virtual QByteArray defaultDevice(const QByteArray &serviceType) const;
  15. virtual QList<QByteArray> devices(const QByteArray &serviceType) const;
  16. virtual QString deviceDescription(const QByteArray &serviceType, const QByteArray &device);
  17. virtual QCamera::Position cameraPosition(const QByteArray &device) const;
  18. virtual int cameraOrientation(const QByteArray &device) const;
  19. static QMediaServiceProvider* defaultServiceProvider();
  20. static void setDefaultServiceProvider(QMediaServiceProvider *provider);
  21. };

四、QPluginServiceProvider

QPluginServiceProvider继承QMediaServiceProvider类,在requestService方法中相应的加载QMediaServiceProviderPlugin实现类(windows下的DSServicePlugin、WMFServicePlugin、Linux下的QGstreamerPlayerServicePlugin),在QMediaServiceProviderPlugin实现类中会创建对应的QMediaService

  1. class QPluginServiceProvider : public QMediaServiceProvider
  2. {
  3. struct MediaServiceData {
  4. QByteArray type;
  5. QMediaServiceProviderPlugin *plugin;
  6. MediaServiceData() : plugin(nullptr) { }
  7. };
  8. QMap<const QMediaService*, MediaServiceData> mediaServiceData;
  9. public:
  10.     // type: "org.qt-project.qt.mediaplayer"
  11. QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) override {
  12. // ...
  13.         // 选择合适的QMediaServiceProviderPlugin,有DSServicePlugin、WMFServicePlugin、QGstreamerPlayerServicePlugin
  14. // 相应的Plugin中创建对应的QMediaService
  15. }
  16. void releaseService(QMediaService *service) override {
  17. // ...
  18. }
  19. QMediaServiceProviderHint::Features supportedFeatures(const QMediaService *service) const override {
  20. // ...
  21. }
  22. QMultimedia::SupportEstimate hasSupport(const QByteArray &serviceType,
  23. const QString &mimeType,
  24. const QStringList& codecs,
  25. int flags) const override {
  26. // ...
  27. }
  28. QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const override {
  29. // ...
  30. }
  31. QByteArray defaultDevice(const QByteArray &serviceType) const override {
  32. // ...
  33. }
  34. QList<QByteArray> devices(const QByteArray &serviceType) const override {
  35. // ...
  36. }
  37. QString deviceDescription(const QByteArray &serviceType, const QByteArray &device) override {
  38. // ...
  39. }
  40. QCamera::Position cameraPosition(const QByteArray &device) const override {
  41. // ...
  42. }
  43. int cameraOrientation(const QByteArray &device) const override {
  44. // ...
  45. }
  46. };

五、QMediaServiceProviderPlugin

  1. class Q_MULTIMEDIA_EXPORT QMediaServiceProviderPlugin : public QObject, public QMediaServiceProviderFactoryInterface
  2. {
  3. Q_OBJECT
  4. Q_INTERFACES(QMediaServiceProviderFactoryInterface)
  5. public:
  6. QMediaService* create(const QString& key) override = 0;
  7. void release(QMediaService *service) override = 0;
  8. };

5.1 DSServicePlugin

  1. class DSServicePlugin
  2. : public QMediaServiceProviderPlugin
  3. , public QMediaServiceSupportedDevicesInterface
  4. , public QMediaServiceDefaultDeviceInterface
  5. , public QMediaServiceFeaturesInterface
  6. {
  7. #if QT_CONFIG(directshow_player)
  8. Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "directshow.json")
  9. #else
  10. Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "directshow_camera.json")
  11. #endif
  12.     // ...
  13. }

5.2 WMFServicePlugin

  1. class WMFServicePlugin
  2. : public QMediaServiceProviderPlugin
  3. , public QMediaServiceSupportedDevicesInterface
  4. , public QMediaServiceDefaultDeviceInterface
  5. , public QMediaServiceFeaturesInterface
  6. {
  7. #if QT_CONFIG(wmf_player)
  8. Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "wmf.json")
  9. #else
  10. Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "wmf_audiodecode.json")
  11. #endif
  12. // ...
  13. }

5.3 QGstreamerPlayerServicePlugin

  1. class QGstreamerPlayerServicePlugin
  2. : public QMediaServiceProviderPlugin
  3. , public QMediaServiceFeaturesInterface
  4. , public QMediaServiceSupportedFormatsInterface
  5. {
  6. Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mediaplayer.json")
  7. // ...
  8. }

六 gstreamer

gstreamer,其插件类为QGstreamerPlayerServicePlugin,其Service类为QGstreamerPlayerService

  1. #linux下播放插件为libgstmediaplayer.so,其链接到了libgstreamer-1.0.so.0上,最终使用了gstreamer
  2. ldd libgstmediaplayer.so | grep libgstreamer*
  3. libgstreamer-1.0.so.0 => /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0 (0x00007f66d65b6000)

ubuntu下的qt和gstreamer1.0环境报错问题解决

ubuntu16.04 18.04 Qt5.11安装Gstreamer

gstreamer官网

gstreamer(一)入门和概述

gstramer(二) 重要工具

gstreamer(三) 常用命令集锦

ubuntu系统下安装gstreamer的ffmpeg支持

【FFMPEG】gstreamer插件调用ffmpeg 详解

gstreamer源码

Gstreamer编译

Gstreamer安装与编译文档 官网

GStreamer插件编译(Windows平台)

Ubuntu中的PPA源

七 ffmpeg

gstreamer插件调用ffmpeg 详解

Linux下ffmpeg安装教程(亲测有效)

在linux下使用ffmpeg方法

Linux上的ffmpeg完全使用指南

官网源码

FFmpeg官网

编译 ffmpeg 方法

FFMPEG详解(完整版)

八 QMediaPlayer初始化过程

liunx qt编译调试

1、QMediaPlayer实例化

  1. // playerService
  2. QMediaPlayer::QMediaPlayer(QObject *parent, QMediaPlayer::Flags flags):
  3. QMediaObject(*new QMediaPlayerPrivate,
  4. parent,
  5. playerService(flags))    // 详见1.1
  6. {
  7. Q_D(QMediaPlayer);
  8. d->provider = QMediaServiceProvider::defaultServiceProvider();
  9. if (d->service == nullptr) {
  10. d->error = ServiceMissingError;
  11. } else {
  12.         // 此处control为QGstreamerPlayerService中创建的QGstreamerPlayerControl
  13. d->control = qobject_cast<QMediaPlayerControl*>(d->service->requestControl(QMediaPlayerControl_iid));
  14. #ifndef QT_NO_BEARERMANAGEMENT
  15. QT_WARNING_PUSH
  16. QT_WARNING_DISABLE_DEPRECATED
  17. d->networkAccessControl = qobject_cast<QMediaNetworkAccessControl*>(d->service->requestControl(QMediaNetworkAccessControl_iid));
  18. QT_WARNING_POP
  19. #endif
  20. if (d->control != nullptr) {
  21. connect(d->control, SIGNAL(mediaChanged(QMediaContent)), SLOT(_q_handleMediaChanged(QMediaContent)));
  22. connect(d->control, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(_q_stateChanged(QMediaPlayer::State)));
  23. connect(d->control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
  24. SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus)));
  25. connect(d->control, SIGNAL(error(int,QString)), SLOT(_q_error(int,QString)));
  26. connect(d->control, &QMediaPlayerControl::durationChanged, this, &QMediaPlayer::durationChanged);
  27. connect(d->control, &QMediaPlayerControl::positionChanged, this, &QMediaPlayer::positionChanged);
  28. connect(d->control, &QMediaPlayerControl::audioAvailableChanged, this, &QMediaPlayer::audioAvailableChanged);
  29. connect(d->control, &QMediaPlayerControl::videoAvailableChanged, this, &QMediaPlayer::videoAvailableChanged);
  30. connect(d->control, &QMediaPlayerControl::volumeChanged, this, &QMediaPlayer::volumeChanged);
  31. connect(d->control, &QMediaPlayerControl::mutedChanged, this, &QMediaPlayer::mutedChanged);
  32. connect(d->control, &QMediaPlayerControl::seekableChanged, this, &QMediaPlayer::seekableChanged);
  33. connect(d->control, &QMediaPlayerControl::playbackRateChanged, this, &QMediaPlayer::playbackRateChanged);
  34. connect(d->control, &QMediaPlayerControl::bufferStatusChanged, this, &QMediaPlayer::bufferStatusChanged);
  35. d->state = d->control->state();
  36. d->status = d->control->mediaStatus();
  37. if (d->state == PlayingState)
  38. addPropertyWatch("position");
  39. if (d->status == StalledMedia || d->status == BufferingMedia)
  40. addPropertyWatch("bufferStatus");
  41. d->hasStreamPlaybackFeature = d->provider->supportedFeatures(d->service).testFlag(QMediaServiceProviderHint::StreamPlayback);
  42. d->audioRoleControl = qobject_cast<QAudioRoleControl*>(d->service->requestControl(QAudioRoleControl_iid));
  43. if (d->audioRoleControl) {
  44. connect(d->audioRoleControl, &QAudioRoleControl::audioRoleChanged,
  45. this, &QMediaPlayer::audioRoleChanged);
  46. d->customAudioRoleControl = qobject_cast<QCustomAudioRoleControl *>(
  47. d->service->requestControl(QCustomAudioRoleControl_iid));
  48. if (d->customAudioRoleControl) {
  49. connect(d->customAudioRoleControl,
  50. &QCustomAudioRoleControl::customAudioRoleChanged,
  51. this,
  52. &QMediaPlayer::customAudioRoleChanged);
  53. }
  54. }
  55. }
  56. #ifndef QT_NO_BEARERMANAGEMENT
  57. if (d->networkAccessControl != nullptr) {
  58. QT_WARNING_PUSH
  59. QT_WARNING_DISABLE_DEPRECATED
  60. connect(d->networkAccessControl, &QMediaNetworkAccessControl::configurationChanged,
  61. this, &QMediaPlayer::networkConfigurationChanged);
  62. QT_WARNING_POP
  63. }
  64. #endif
  65. }
  66. }

1.1 playerService

  1. // 通过静态方法获取QMediaService
  2. static QMediaService *playerService(QMediaPlayer::Flags flags)
  3. {
  4. // 获取默认的QMediaServiceProvider ==> 1.1.1
  5. QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
  6. if (flags) {
  7. QMediaServiceProviderHint::Features features;
  8. if (flags & QMediaPlayer::LowLatency)
  9. features |= QMediaServiceProviderHint::LowLatencyPlayback;
  10. if (flags & QMediaPlayer::StreamPlayback)
  11. features |= QMediaServiceProviderHint::StreamPlayback;
  12. if (flags & QMediaPlayer::VideoSurface)
  13. features |= QMediaServiceProviderHint::VideoSurface;
  14. return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER,
  15. QMediaServiceProviderHint(features));
  16. }
  17.     // ==> 1.1.2 QPluginServiceProvider->requestService
  18. return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER);
  19. }

1.1.1 defaultServiceProvider

  1. QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
  2. {
  3. // qt_defaultMediaServiceProvider默认为空,
  4. // pluginProvider()是由Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider)定义,
  5. // 返回类型为QPluginServiceProvider类型的对象
  6. return qt_defaultMediaServiceProvider != nullptr
  7. ? qt_defaultMediaServiceProvider
  8. : static_cast<QMediaServiceProvider *>(pluginProvider());
  9. }
  10. // 定义命名空间为pluginProvider的QPluginServiceProvider对象 ?
  11. Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider);

1.1.2 QPluginServiceProvider::requestService

  1. class QPluginServiceProvider : public QMediaServiceProvider
  2. {
  3. struct MediaServiceData {
  4. QByteArray type;
  5. QMediaServiceProviderPlugin *plugin;
  6. MediaServiceData() : plugin(nullptr) { }
  7. };
  8. QMap<const QMediaService*, MediaServiceData> mediaServiceData;
  9. public:
  10. QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) override
  11. {
  12. // key 的值为 "org.qt-project.qt.mediaplayer"
  13. QString key(QLatin1String(type.constData()));
  14. QList<QMediaServiceProviderPlugin *>plugins;
  15. // loader()是由Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, loader,(QMediaServiceProviderFactoryInterface_iid, QLatin1String("mediaservice"), Qt::CaseInsensitive))定义,
  16.         // 其类型是QMediaPluginLoader对象, ==> 1.1.2.1 , 1.1.2.2
  17.         // instances值在linux下为QGstreamerPlayerServicePlugin
  18. const auto instances = loader()->instances(key);
  19. for (QObject *obj : instances) {
  20. QMediaServiceProviderPlugin *plugin =
  21. qobject_cast<QMediaServiceProviderPlugin*>(obj);
  22. if (plugin)
  23. plugins << plugin;
  24. }
  25. if (!plugins.isEmpty()) {
  26. QMediaServiceProviderPlugin *plugin = nullptr;
  27.             // 此处hint.type()值为QMediaServiceProviderHint::Null
  28. switch (hint.type()) {
  29. case QMediaServiceProviderHint::Null:
  30. plugin = plugins[0];
  31. //special case for media player, if low latency was not asked,
  32. //prefer services not offering it, since they are likely to support
  33. //more formats
  34. if (type == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) {
  35. for (QMediaServiceProviderPlugin *currentPlugin : qAsConst(plugins)) {
  36. QMediaServiceFeaturesInterface *iface =
  37. qobject_cast<QMediaServiceFeaturesInterface*>(currentPlugin);
  38. if (!iface || !(iface->supportedFeatures(type) &
  39. QMediaServiceProviderHint::LowLatencyPlayback)) {
  40. plugin = currentPlugin;
  41. break;
  42. }
  43. }
  44. }
  45. break;
  46. case QMediaServiceProviderHint::SupportedFeatures:
  47. // ...
  48. break;
  49. case QMediaServiceProviderHint::Device:
  50.                 // ...
  51. break;
  52. case QMediaServiceProviderHint::CameraPosition: {
  53. // ...
  54. }
  55. break;
  56. case QMediaServiceProviderHint::ContentType: {
  57. // ...
  58. }
  59. break;
  60. }
  61. if (plugin != nullptr) {
  62.                 // 返回类型为QGstreamerPlayerService ==> 1.1.2.3
  63. QMediaService *service = plugin->create(key);
  64. if (service != nullptr) {
  65. MediaServiceData d;
  66. d.type = type;
  67. d.plugin = plugin;
  68. mediaServiceData.insert(service, d);
  69. }
  70. return service;
  71. }
  72. }
  73. qWarning() << "defaultServiceProvider::requestService(): no service found for -" << key;
  74. return nullptr;
  75. }
  76. // ...
  77. }
1.1.2.1 loader()->instances(key)
1.1.2.1.1 QMediaPluginLoader
  1. Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, loader,
  2. (QMediaServiceProviderFactoryInterface_iid, QLatin1String("mediaservice"), Qt::CaseInsensitive))

相应的宏为:

  1. # define Q_GLOBAL_STATIC_INTERNAL_DECORATION Q_DECL_HIDDEN inline
  2. #define Q_GLOBAL_STATIC_INTERNAL(ARGS) \
  3. Q_GLOBAL_STATIC_INTERNAL_DECORATION Type *innerFunction() \
  4. { \
  5. struct HolderBase { \
  6. ~HolderBase() noexcept \
  7. { if (guard.loadRelaxed() == QtGlobalStatic::Initialized) \
  8. guard.storeRelaxed(QtGlobalStatic::Destroyed); } \
  9. }; \
  10. static struct Holder : public HolderBase { \
  11. Type value; \
  12. Holder() \
  13. noexcept(noexcept(Type ARGS)) \
  14. : value ARGS \
  15. { guard.storeRelaxed(QtGlobalStatic::Initialized); } \
  16. } holder; \
  17. return &holder.value; \
  18. }
  19. // this class must be POD, unless the compiler supports thread-safe statics
  20. template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard>
  21. struct QGlobalStatic
  22. {
  23. typedef T Type;
  24. bool isDestroyed() const { return guard.loadRelaxed() <= QtGlobalStatic::Destroyed; }
  25. bool exists() const { return guard.loadRelaxed() == QtGlobalStatic::Initialized; }
  26. operator Type *() { if (isDestroyed()) return nullptr; return innerFunction(); }
  27. Type *operator()() { if (isDestroyed()) return nullptr; return innerFunction(); }
  28. Type *operator->()
  29. {
  30. Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
  31. return innerFunction();
  32. }
  33. Type &operator*()
  34. {
  35. Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
  36. return *innerFunction();
  37. }
  38. };
  39. #define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
  40. namespace { namespace Q_QGS_ ## NAME { \
  41. typedef TYPE Type; \
  42. QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized); \
  43. Q_GLOBAL_STATIC_INTERNAL(ARGS) \
  44. } } \
  45. static QGlobalStatic<TYPE, \
  46. Q_QGS_ ## NAME::innerFunction, \
  47. Q_QGS_ ## NAME::guard> NAME;
  48. #define Q_GLOBAL_STATIC(TYPE, NAME) \
  49. Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())

其扩展后变成:

  1. namespace {
  2.     namespace Q_QGS_loader {
  3. typedef QMediaPluginLoader Type;
  4.         // 初始化 guard 原子性变量
  5. QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized);
  6. //Q_GLOBAL_STATIC_INTERNAL(ARGS)
  7.     inline QMediaPluginLoader *innerFunction() { \
  8.     struct HolderBase {
  9.     ~HolderBase() noexcept
  10.     { if (guard.loadRelaxed() == QtGlobalStatic::Initialized)
  11.     guard.storeRelaxed(QtGlobalStatic::Destroyed); }
  12.     };
  13.     static struct Holder : public HolderBase {
  14.     QMediaPluginLoader value;
  15.     Holder()
  16.     noexcept(noexcept(QMediaPluginLoader(QMediaServiceProviderFactoryInterface_iid, QLatin1String("mediaservice"), Qt::CaseInsensitive)))
  17.     : value(QMediaServiceProviderFactoryInterface_iid, QLatin1String("mediaservice"), Qt::CaseInsensitive)
  18.     { guard.storeRelaxed(QtGlobalStatic::Initialized); }
  19.     } holder;
  20.     return &holder.value;
  21.     }
  22.     }
  23. }
  24. //static QGlobalStatic<QMediaPluginLoader, Q_QGS_loader::innerFunction,
  25. // Q_QGS_loader::guard> loader;
  26. static struct QGlobalStatic<QMediaPluginLoader, Q_QGS_loader::innerFunction,
  27.         Q_QGS_loader::guard> {
  28. typedef QMediaPluginLoader Type;
  29. bool isDestroyed() const { return Q_QGS_loader::guard.loadRelaxed() <= QtGlobalStatic::Destroyed; }
  30. bool exists() const { return Q_QGS_loader::guard.loadRelaxed() == QtGlobalStatic::Initialized; }
  31. operator Type *() { if (isDestroyed()) return nullptr; return Q_QGS_loader::innerFunction(); }
  32. Type *operator()() { if (isDestroyed()) return nullptr; return Q_QGS_loader::innerFunction(); }
  33. Type *operator->() {
  34. Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
  35. return Q_QGS_loader::innerFunction();
  36. }
  37. Type &operator*() {
  38. Q_ASSERT_X(!isDestroyed(), "Q_GLOBAL_STATIC", "The global static was used after being destroyed");
  39. return *Q_QGS_loader::innerFunction();
  40. }
  41. } loader;

从上可知loader()operator()()的重载,其返回QMediaPluginLoader*对象

1.1.2.1.2 QMediaPluginLoader实例化
  1. /* 实例化的时,传入的参数
  2. * iid: QMediaServiceProviderFactoryInterface_iid, 值为
  3. * "org.qt-project.qt.mediaserviceproviderfactory/5.0"
  4. * location: QLatin1String("mediaservice")
  5. * caseSensitivity: Qt::CaseInsensitive
  6. */
  7. QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity caseSensitivity):
  8. m_iid(iid)
  9. {
  10. #if defined(Q_OS_ANDROID)
  11. m_location = QString(location).replace(QLatin1Char('/'), QLatin1Char('_'));
  12. #else
  13. m_location = QString::fromLatin1("/%1").arg(location);
  14. #endif
  15. m_factoryLoader = new QFactoryLoader(m_iid, m_location, caseSensitivity);
  16. loadMetadata();
  17. }
1.1.2.1.2.1 QFactoryLoader实例化

QMediaPluginLoader实例化时,会创建QFactoryLoader对象,其里面调用update方法更新Metadata信息,然后通过loadMetadata()中使用。

update方法中会查找Qt plugins/mediaservice下的插件,并加载成QLibraryPrivate对象,

然后读取QLibraryPrivate中元数据(qt plugins 插件框架),通过元数据判断是否是想要的插件,是则放入把QLibraryPrivate放入到QFactoryLoaderPrivate->libraryList中,以供loadMetadata()读取。

  1. QFactoryLoader::QFactoryLoader(const char *iid,
  2. const QString &suffix,
  3. Qt::CaseSensitivity cs)
  4. : QObject(*new QFactoryLoaderPrivate)
  5. {
  6. moveToThread(QCoreApplicationPrivate::mainThread());
  7. Q_D(QFactoryLoader);
  8. d->iid = iid;
  9. #if QT_CONFIG(library)
  10. d->cs = cs;
  11. d->suffix = suffix;
  12. # ifdef Q_OS_ANDROID
  13. if (!d->suffix.isEmpty() && d->suffix.at(0) == QLatin1Char('/'))
  14. d->suffix.remove(0, 1);
  15. # endif
  16. QMutexLocker locker(qt_factoryloader_mutex());
  17. update();
  18. qt_factory_loaders()->append(this);
  19. #else
  20. Q_UNUSED(suffix);
  21. Q_UNUSED(cs);
  22. #endif
  23. }
  24. // 查找Qt plugins/mediaservice下的插件,并加载成QLibraryPrivate对象,
  25. // 读取QLibraryPrivate中元数据,如果是想要的插件,则放入QFactoryLoaderPrivate->libraryList中,
  26. // 以供loadMetadata()读取
  27. void QFactoryLoader::update()
  28. {
  29. #ifdef QT_SHARED
  30. Q_D(QFactoryLoader);
  31.     // paths的值为:
  32.     // "/home/Qt/5.15.2/gcc_64/plugins"
  33.     // "/home/Qt/Examples/Qt-5.15.2/multimediawidgets/build-player-Desktop_Qt_5_15_2_GCC_64bit-Debug"
  34. QStringList paths = QCoreApplication::libraryPaths();
  35. for (int i = 0; i < paths.count(); ++i) {
  36. const QString &pluginDir = paths.at(i);
  37. // Already loaded, skip it...
  38. if (d->loadedPaths.contains(pluginDir))
  39. continue;
  40. d->loadedPaths << pluginDir;
  41. QString path = pluginDir + d->suffix;
  42. if (!QDir(path).exists(QLatin1String(".")))
  43. continue;
  44. QStringList plugins = QDir(path).entryList(
  45. #if defined(Q_OS_WIN)
  46. QStringList(QStringLiteral("*.dll")),
  47. #elif defined(Q_OS_ANDROID)
  48. QStringList(QLatin1String("libplugins_%1_*.so").arg(d->suffix)),
  49. #endif
  50. QDir::Files);
  51. QLibraryPrivate *library = nullptr;
  52. for (int j = 0; j < plugins.count(); ++j) {
  53. QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
  54. #ifdef Q_OS_MAC
  55. const bool isDebugPlugin = fileName.endsWith(QLatin1String("_debug.dylib"));
  56. const bool isDebugLibrary =
  57. #ifdef QT_DEBUG
  58. true;
  59. #else
  60. false;
  61. #endif
  62. // Skip mismatching plugins so that we don't end up loading both debug and release
  63. // versions of the same Qt libraries (due to the plugin's dependencies).
  64. if (isDebugPlugin != isDebugLibrary)
  65. continue;
  66. #elif defined(Q_PROCESSOR_X86)
  67. if (fileName.endsWith(QLatin1String(".avx2")) || fileName.endsWith(QLatin1String(".avx512"))) {
  68. // ignore AVX2-optimized file, we'll do a bait-and-switch to it later
  69. continue;
  70. }
  71. #endif
  72. if (qt_debug_component()) {
  73. qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
  74. }
  75. Q_TRACE(QFactoryLoader_update, fileName);
  76.            
  77. library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
  78. // ==> 1.1.2.1.2.1.1
  79.             if (!library->isPlugin()) {
  80. if (qt_debug_component()) {
  81. qDebug() << library->errorString << Qt::endl
  82. << " not a plugin";
  83. }
  84. library->release();
  85. continue;
  86. }
  87. QStringList keys;
  88. bool metaDataOk = false;
  89. QString iid = library->metaData.value(QLatin1String("IID")).toString();
  90. if (iid == QLatin1String(d->iid.constData(), d->iid.size())) {
  91. QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject();
  92. metaDataOk = true;
  93. QJsonArray k = object.value(QLatin1String("Keys")).toArray();
  94. for (int i = 0; i < k.size(); ++i)
  95. keys += d->cs ? k.at(i).toString() : k.at(i).toString().toLower();
  96. }
  97. if (qt_debug_component())
  98. qDebug() << "Got keys from plugin meta data" << keys;
  99. if (!metaDataOk) {
  100. library->release();
  101. continue;
  102. }
  103. int keyUsageCount = 0;
  104. for (int k = 0; k < keys.count(); ++k) {
  105. // first come first serve, unless the first
  106. // library was built with a future Qt version,
  107. // whereas the new one has a Qt version that fits
  108. // better
  109. const QString &key = keys.at(k);
  110. QLibraryPrivate *previous = d->keyMap.value(key);
  111. int prev_qt_version = 0;
  112. if (previous) {
  113. prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble();
  114. }
  115. int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble();
  116. if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) {
  117. d->keyMap[key] = library;
  118. ++keyUsageCount;
  119. }
  120. }
  121. if (keyUsageCount || keys.isEmpty()) {
  122. library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload
  123. QMutexLocker locker(&d->mutex);
  124. d->libraryList += library;
  125. } else {
  126. library->release();
  127. }
  128. }
  129. }
  130. #else
  131. Q_D(QFactoryLoader);
  132. if (qt_debug_component()) {
  133. qDebug() << "QFactoryLoader::QFactoryLoader() ignoring" << d->iid
  134. << "since plugins are disabled in static builds";
  135. }
  136. #endif
  137. }

1.1.2.1.2.1.1 library->isPlugin()

  1. bool QLibraryPrivate::isPlugin()
  2. {
  3. if (pluginState == MightBeAPlugin)
  4. updatePluginState();
  5. return pluginState == IsAPlugin;
  6. }
  7. void QLibraryPrivate::updatePluginState()
  8. {
  9. QMutexLocker locker(&mutex);
  10. errorString.clear();
  11. if (pluginState != MightBeAPlugin)
  12. return;
  13. bool success = false;
  14. #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
  15. if (fileName.endsWith(QLatin1String(".debug"))) {
  16. // refuse to load a file that ends in .debug
  17. // these are the debug symbols from the libraries
  18. // the problem is that they are valid shared library files
  19. // and dlopen is known to crash while opening them
  20. // pretend we didn't see the file
  21. errorString = QLibrary::tr("The shared library was not found.");
  22. pluginState = IsNotAPlugin;
  23. return;
  24. }
  25. #endif
  26. if (!pHnd.loadRelaxed()) {
  27. // scan for the plugin metadata without loading
  28.         // 没有加载,则读入文件内容进行分析 ==> 1.1.2.1.2.1.1.1
  29. success = findPatternUnloaded(fileName, this);
  30. } else {
  31. // library is already loaded (probably via QLibrary)
  32. // simply get the target function and call it.
  33.         // 有加载则直接调用qt_plugin_query_metadata函数 ==> 1.1.2.1.2.1.1.2
  34. success = qt_get_metadata(this, &errorString);
  35. }
  36. if (!success) {
  37. if (errorString.isEmpty()){
  38. if (fileName.isEmpty())
  39. errorString = QLibrary::tr("The shared library was not found.");
  40. else
  41. errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
  42. }
  43. pluginState = IsNotAPlugin;
  44. return;
  45. }
  46. pluginState = IsNotAPlugin; // be pessimistic
  47. uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble();
  48. bool debug = metaData.value(QLatin1String("debug")).toBool();
  49. if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
  50. if (qt_debug_component()) {
  51. qWarning("In %s:\n"
  52. " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
  53. QFile::encodeName(fileName).constData(),
  54. (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
  55. debug ? "debug" : "release");
  56. }
  57. errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
  58. .arg(fileName)
  59. .arg((qt_version&0xff0000) >> 16)
  60. .arg((qt_version&0xff00) >> 8)
  61. .arg(qt_version&0xff)
  62. .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
  63. #ifndef QT_NO_DEBUG_PLUGIN_CHECK
  64. } else if(debug != QLIBRARY_AS_DEBUG) {
  65. //don't issue a qWarning since we will hopefully find a non-debug? --Sam
  66. errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
  67. " (Cannot mix debug and release libraries.)").arg(fileName);
  68. #endif
  69. } else {
  70. pluginState = IsAPlugin;
  71. }
  72. }

1.1.2.1.2.1.1.1 findPatternUnloaded

没有加载,则读入文件内容进行分析

  1. static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
  2. {
  3. QFile file(library);
  4. if (!file.open(QIODevice::ReadOnly)) {
  5. return false;
  6. }
  7. // Files can be bigger than the virtual memory size on 32-bit systems, so
  8. // we limit to 512 MB there. For 64-bit, we allow up to 2^40 bytes.
  9. constexpr qint64 MaxMemoryMapSize =
  10. Q_INT64_C(1) << (sizeof(qsizetype) > 4 ? 40 : 29);
  11. QByteArray data;
  12. qsizetype fdlen = qMin(file.size(), MaxMemoryMapSize);
  13. const char *filedata = reinterpret_cast<char *>(file.map(0, fdlen));
  14. if (filedata == nullptr) {
  15. // Try reading the data into memory instead (up to 64 MB).
  16. data = file.read(64 * 1024 * 1024);
  17. filedata = data.constData();
  18. fdlen = data.size();
  19. }
  20. /*
  21. ELF and Mach-O binaries with GCC have .qplugin sections.
  22. */
  23. bool hasMetaData = false;
  24. qsizetype pos = 0;
  25. char pattern[] = "qTMETADATA ";
  26. pattern[0] = 'Q'; // Ensure the pattern "QTMETADATA" is not found in this library should QPluginLoader ever encounter it.
  27. const ulong plen = qstrlen(pattern);
  28. #if defined (Q_OF_ELF) && defined(Q_CC_GNU)
  29. int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
  30. if (r == QElfParser::Corrupt || r == QElfParser::NotElf) {
  31. if (lib && qt_debug_component()) {
  32. qWarning("QElfParser: %ls", qUtf16Printable(lib->errorString));
  33. }
  34. return false;
  35. } else if (r == QElfParser::QtMetaDataSection) {
  36. qsizetype rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
  37. if (rel < 0)
  38. pos = -1;
  39. else
  40. pos += rel;
  41. hasMetaData = true;
  42. }
  43. #elif defined (Q_OF_MACH_O)
  44. {
  45. QString errorString;
  46. int r = QMachOParser::parse(filedata, fdlen, library, &errorString, &pos, &fdlen);
  47. if (r == QMachOParser::NotSuitable) {
  48. if (qt_debug_component())
  49. qWarning("QMachOParser: %ls", qUtf16Printable(errorString));
  50. if (lib)
  51. lib->errorString = errorString;
  52. return false;
  53. }
  54. // even if the metadata section was not found, the Mach-O parser will
  55. // at least return the boundaries of the right architecture
  56. qsizetype rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
  57. if (rel < 0)
  58. pos = -1;
  59. else
  60. pos += rel;
  61. hasMetaData = true;
  62. }
  63. #else
  64. pos = qt_find_pattern(filedata, fdlen, pattern, plen);
  65. if (pos > 0)
  66. hasMetaData = true;
  67. #endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
  68. bool ret = false;
  69. if (pos >= 0 && hasMetaData) {
  70. const char *data = filedata + pos;
  71. QString errMsg;
  72. QJsonDocument doc = qJsonFromRawLibraryMetaData(data, fdlen, &errMsg);
  73. if (doc.isNull()) {
  74. qWarning("Found invalid metadata in lib %ls: %ls",
  75. qUtf16Printable(library), qUtf16Printable(errMsg));
  76. } else {
  77. lib->metaData = doc.object();
  78. if (qt_debug_component())
  79. qWarning("Found metadata in lib %s, metadata=\n%s\n",
  80. library.toLocal8Bit().constData(), doc.toJson().constData());
  81. ret = !doc.isNull();
  82. }
  83. }
  84. if (!ret && lib)
  85. lib->errorString = QLibrary::tr("Failed to extract plugin meta data from '%1'").arg(library);
  86. file.close();
  87. return ret;
  88. }

1.1.2.1.2.1.1.2 qt_get_metadata

有加载则直接调用qt_plugin_query_metadata函数

  1. static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
  2. {
  3. #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
  4. auto getMetaData = [](QFunctionPointer fptr) {
  5. auto f = reinterpret_cast<const char * (*)()>(fptr);
  6. return qMakePair<const char *, size_t>(f(), INT_MAX);
  7. };
  8. #else
  9. auto getMetaData = [](QFunctionPointer fptr) {
  10. auto f = reinterpret_cast<QPair<const char *, size_t> (*)()>(fptr);
  11. return f();
  12. };
  13. #endif
  14. QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata");
  15. if (!pfn)
  16. return false;
  17. auto metaData = getMetaData(pfn);
  18. QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg);
  19. if (doc.isNull())
  20. return false;
  21. priv->metaData = doc.object();
  22. return true;
  23. }

最终获取到的metaData数据为:

QFactoryLoader::QFactoryLoader() looking at "/home/xx/Qt/5.15.2/gcc_64/plugins/mediaservice/libgstmediaplayer.so"
Found metadata in lib /home/xx/Qt/5.15.2/gcc_64/plugins/mediaservice/libgstmediaplayer.so, metadata=
{
"IID": "org.qt-project.qt.mediaserviceproviderfactory/5.0",
"MetaData": {
"Keys": [
"gstreamermediaplayer"
],
"Services": [
"org.qt-project.qt.mediaplayer"
]
},
"archreq": 0,
"className": "QGstreamerPlayerServicePlugin",
"debug": false,
"version": 331520
}
1.1.2.1.2.2 loadMetadata() 加载Metadata到m_metadata中
  1. void QMediaPluginLoader::loadMetadata()
  2. {
  3. if (!m_metadata.isEmpty()) {
  4. return;
  5. }
  6. // QFactoryLoader::metaData() ==> 1.1.2.1.2.2.1
  7. QList<QJsonObject> meta = m_factoryLoader->metaData();
  8. for (int i = 0; i < meta.size(); i++) {
  9. QJsonObject jsonobj = meta.at(i).value(QStringLiteral("MetaData")).toObject();
  10. jsonobj.insert(QStringLiteral("index"), i);
  11. #if !defined QT_NO_DEBUG
  12. if (showDebug)
  13. qDebug() << "QMediaPluginLoader: Inserted index " << i << " into metadata: " << jsonobj;
  14. #endif
  15. QJsonArray arr = jsonobj.value(QStringLiteral("Services")).toArray();
  16. // Preserve compatibility with older plugins (made before 5.1) in which
  17. // services were declared in the 'Keys' property
  18. if (arr.isEmpty())
  19. arr = jsonobj.value(QStringLiteral("Keys")).toArray();
  20. for (const QJsonValue &value : qAsConst(arr)) {
  21. QString key = value.toString();
  22. if (!m_metadata.contains(key)) {
  23. #if !defined QT_NO_DEBUG
  24. if (showDebug)
  25. qDebug() << "QMediaPluginLoader: Inserting new list for key: " << key;
  26. #endif
  27. m_metadata.insert(key, QList<QJsonObject>());
  28. }
  29. m_metadata[key].append(jsonobj);
  30. }
  31. }
  32. }

1.1.2.1.2.2.1 m_factoryLoader->metaData()

  1. QList<QJsonObject> QFactoryLoader::metaData() const
  2. {
  3. Q_D(const QFactoryLoader);
  4. QList<QJsonObject> metaData;
  5. #if QT_CONFIG(library)
  6. QMutexLocker locker(&d->mutex);
  7. for (int i = 0; i < d->libraryList.size(); ++i)
  8. metaData.append(d->libraryList.at(i)->metaData);
  9. #endif
  10. const auto staticPlugins = QPluginLoader::staticPlugins();
  11. for (const QStaticPlugin &plugin : staticPlugins) {
  12. const QJsonObject object = plugin.metaData();
  13. if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size()))
  14. continue;
  15. metaData.append(object);
  16. }
  17. return metaData;
  18. }
1.1.2.2 QMediaPluginLoader::instances(key)

参数key值为"org.qt-project.qt.mediaplayer",m_metadata.value(key)值为下图:

  1. QList<QObject*> QMediaPluginLoader::instances(QString const &key)
  2. {
  3. if (!m_metadata.contains(key))
  4. return QList<QObject*>();
  5. QList<QString> keys;
  6. QList<QObject *> objects;
  7. const auto list = m_metadata.value(key);
  8. for (const QJsonObject &jsonobj : list) {
  9. int idx = jsonobj.value(QStringLiteral("index")).toDouble();
  10. if (idx < 0)
  11. continue;
  12.         // 此处idx为3, ==> 1.1.2.2.1
  13. QObject *object = m_factoryLoader->instance(idx);
  14. if (!objects.contains(object)) {
  15. QJsonArray arr = jsonobj.value(QStringLiteral("Keys")).toArray();
  16. keys.append(!arr.isEmpty() ? arr.at(0).toString() : QStringLiteral(""));
  17. objects.append(object);
  18. }
  19. }
  20.     // 运行到此处 keys 值为"gstreamermediaplayer"
  21.     // objects值为QGstreamerPlayerServicePlugin对象
  22. static const bool showDebug = qEnvironmentVariableIntValue("QT_DEBUG_PLUGINS");
  23. // preferredPlugins 默认为空
  24.     static const QStringList preferredPlugins =
  25. qEnvironmentVariable("QT_MULTIMEDIA_PREFERRED_PLUGINS").split(QLatin1Char(','), Qt::SkipEmptyParts);
  26. for (int i = preferredPlugins.size() - 1; i >= 0; --i) {
  27. auto name = preferredPlugins[i];
  28. bool found = false;
  29. for (int j = 0; j < keys.size(); ++j) {
  30. if (!keys[j].startsWith(name))
  31. continue;
  32. auto obj = objects[j];
  33. objects.removeAt(j);
  34. objects.prepend(obj);
  35. auto k = keys[j];
  36. keys.removeAt(j);
  37. keys.prepend(k);
  38. found = true;
  39. break;
  40. }
  41. }
  42. return objects;
  43. }
1.1.2.2.1 m_factoryLoader->instance(idx)
  1. // 此处index为3
  2. QObject *QFactoryLoader::instance(int index) const
  3. {
  4. Q_D(const QFactoryLoader);
  5. if (index < 0)
  6. return nullptr;
  7. #if QT_CONFIG(library)
  8. QMutexLocker lock(&d->mutex);
  9. if (index < d->libraryList.size()) {
  10.         // library 为 "plugins/mediaservice/libgstmediaplayer.so"
  11. QLibraryPrivate *library = d->libraryList.at(index);
  12. // library->pluginInstance() 实例化libgstmediaplayer.so,
  13.         // 其类型为QGstreamerPlayerServicePlugin
  14. if (QObject *obj = library->pluginInstance()) {
  15. if (!obj->parent())
  16. obj->moveToThread(QCoreApplicationPrivate::mainThread());
  17. return obj;
  18. }
  19. return nullptr;
  20. }
  21. index -= d->libraryList.size();
  22. lock.unlock();
  23. #endif
  24. QVector<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins();
  25. for (int i = 0; i < staticPlugins.count(); ++i) {
  26. const QJsonObject object = staticPlugins.at(i).metaData();
  27. if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size()))
  28. continue;
  29. if (index == 0)
  30. return staticPlugins.at(i).instance();
  31. --index;
  32. }
  33. return nullptr;
  34. }
1.1.2.3 plugin->create(key)

QGstreamerPlayerServicePlugin插件其原信息为:Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mediaplayer.json")

mediaplayer.json在Src/qtmultimedia/src/plugins/gstreamer/mediaplayer下,文件内容为:

  1. {
  2. "Keys": ["gstreamermediaplayer"],
  3. "Services": ["org.qt-project.qt.mediaplayer"]
  4. }
  1. // Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mediaplayer.json")
  2. // key 为 "org.qt-project.qt.mediaplayer"
  3. QMediaService* QGstreamerPlayerServicePlugin::create(const QString &key)
  4. {
  5.     // 初始化gsstreamer库?
  6. QGstUtils::initializeGst();
  7. if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
  8. return new QGstreamerPlayerService;
  9. qWarning() << "Gstreamer service plugin: unsupported key:" << key;
  10. return 0;
  11. }
1.1.2.3.1 QGstreamerPlayerService
  1. QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent)
  2. : QMediaService(parent)
  3. {
  4. m_session = new QGstreamerPlayerSession(this);
  5. m_control = new QGstreamerPlayerControl(m_session, this);
  6. m_metaData = new QGstreamerMetaDataProvider(m_session, this);
  7. m_streamsControl = new QGstreamerStreamsControl(m_session,this);
  8. m_availabilityControl = new QGStreamerAvailabilityControl(m_control->resources(), this);
  9. m_videoRenderer = new QGstreamerVideoRenderer(this);
  10. m_videoWindow = new QGstreamerVideoWindow(this);
  11. // If the GStreamer video sink is not available, don't provide the video window control since
  12. // it won't work anyway.
  13. if (!m_videoWindow->videoSink()) {
  14. delete m_videoWindow;
  15. m_videoWindow = 0;
  16. }
  17. #if defined(HAVE_WIDGETS)
  18. m_videoWidget = new QGstreamerVideoWidgetControl(this);
  19. // If the GStreamer video sink is not available, don't provide the video widget control since
  20. // it won't work anyway.
  21. // QVideoWidget will fall back to QVideoRendererControl in that case.
  22. if (!m_videoWidget->videoSink()) {
  23. delete m_videoWidget;
  24. m_videoWidget = 0;
  25. }
  26. #endif
  27. }
1.1.2.3.1.1 QGstreamerPlayerSession

其位于:qtmultimedia/src/gsttools/qgstreamerplayersession.cpp

  1. #include <gst/gst.h>
  2. QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
  3. : QObject(parent)
  4. {
  5. initPlaybin();
  6. }

从上面可见,其引用了GStreamer头文件。

编写一个GStreamer应用

1.1.2.3.1.2 QGstreamerPlayerControl

其位于:qtmultimedia/src/gsttools/qgstreamerplayercontrol.cpp

  1. QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent)
  2. : QMediaPlayerControl(parent)
  3. , m_session(session)
  4. {
  5. m_resources = QMediaResourcePolicy::createResourceSet<QMediaPlayerResourceSetInterface>();
  6. Q_ASSERT(m_resources);
  7. connect(m_session, &QGstreamerPlayerSession::positionChanged, this, &QGstreamerPlayerControl::positionChanged);
  8. connect(m_session, &QGstreamerPlayerSession::durationChanged, this, &QGstreamerPlayerControl::durationChanged);
  9. connect(m_session, &QGstreamerPlayerSession::mutedStateChanged, this, &QGstreamerPlayerControl::mutedChanged);
  10. connect(m_session, &QGstreamerPlayerSession::volumeChanged, this, &QGstreamerPlayerControl::volumeChanged);
  11. connect(m_session, &QGstreamerPlayerSession::stateChanged, this, &QGstreamerPlayerControl::updateSessionState);
  12. connect(m_session, &QGstreamerPlayerSession::bufferingProgressChanged, this, &QGstreamerPlayerControl::setBufferProgress);
  13. connect(m_session, &QGstreamerPlayerSession::playbackFinished, this, &QGstreamerPlayerControl::processEOS);
  14. connect(m_session, &QGstreamerPlayerSession::audioAvailableChanged, this, &QGstreamerPlayerControl::audioAvailableChanged);
  15. connect(m_session, &QGstreamerPlayerSession::videoAvailableChanged, this, &QGstreamerPlayerControl::videoAvailableChanged);
  16. connect(m_session, &QGstreamerPlayerSession::seekableChanged, this, &QGstreamerPlayerControl::seekableChanged);
  17. connect(m_session, &QGstreamerPlayerSession::error, this, &QGstreamerPlayerControl::error);
  18. connect(m_session, &QGstreamerPlayerSession::invalidMedia, this, &QGstreamerPlayerControl::handleInvalidMedia);
  19. connect(m_session, &QGstreamerPlayerSession::playbackRateChanged, this, &QGstreamerPlayerControl::playbackRateChanged);
  20. connect(m_resources, &QMediaPlayerResourceSetInterface::resourcesGranted, this, &QGstreamerPlayerControl::handleResourcesGranted);
  21. //denied signal should be queued to have correct state update process,
  22. //since in playOrPause, when acquire is call on resource set, it may trigger a resourcesDenied signal immediately,
  23. //so handleResourcesDenied should be processed later, otherwise it will be overwritten by state update later in playOrPause.
  24. connect(m_resources, &QMediaPlayerResourceSetInterface::resourcesDenied,
  25. this, &QGstreamerPlayerControl::handleResourcesDenied, Qt::QueuedConnection);
  26. connect(m_resources, &QMediaPlayerResourceSetInterface::resourcesLost, this, &QGstreamerPlayerControl::handleResourcesLost);
  27. }
1.1.2.3.1.3 QGstreamerMetaDataProvider

其位于:qtmultimedia/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp

1.1.2.3.1.4 QGstreamerStreamsControl

其位于:qtmultimedia/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp

1.1.2.3.1.5 QGStreamerAvailabilityControl

其位于:qtmultimedia/src/plugins/gstreamer/mediaplayer/qgstreameravailabilitycontrol.cpp

1.1.2.3.1.6 QGstreamerVideoRenderer

其位于:qtmultimedia/src/gsttools/qgstreamervideorenderer.cpp

1.1.2.3.1.7 QGstreamerVideoWindow

其位于:qtmultimedia/src/gsttools/qgstreamervideowindow.cpp

1.1.2.3.1.8 QGstreamerVideoWidgetControl

其位于:qtmultimedia/src/gsttools/qgstreamervideowidget.cpp

参考

Qt Mobility videoplayer 源码剖析

Qt Multimedia::QMediaPlayer框架源码分析

QMediaServiceProviderPlugin 参考手册

qt 插件机制

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/806873
推荐阅读
相关标签
  

闽ICP备14008679号