diff options
author | Val Doroshchuk <valentyn.doroshchuk@qt.io> | 2019-08-30 12:59:29 +0200 |
---|---|---|
committer | VaL Doroshchuk <valentyn.doroshchuk@qt.io> | 2019-09-09 12:33:18 +0200 |
commit | cb06ede8ba9a33adbbfdc690faa1a83be4e70b55 (patch) | |
tree | 2c3da763347405210683bbb860726214d69a8714 /src/plugins/directshow/dsserviceplugin.cpp | |
parent | 97177277a2fcca974d7599ab8ea12ad80ab30efc (diff) |
DirectShow: Allow QMediaPlayer in secondary thread
Since using of any COM objects must be only after CoInitialize(),
otherwise CoCreateInstance() returns nothing which causes a crash.
If QMediaPlayer is moved to another thread, loading of any content will
also cause a crash because of COM is not initialized.
Proposing to use thread_local ref counter to keep each thread
initialized and avoid double initialization.
Fixes: QTBUG-77163
Change-Id: I81c67d6407b853c824edd3b42454fddf792fd90c
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
Diffstat (limited to 'src/plugins/directshow/dsserviceplugin.cpp')
-rw-r--r-- | src/plugins/directshow/dsserviceplugin.cpp | 32 |
1 files changed, 10 insertions, 22 deletions
diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp index f92e37c00..cc25e35b7 100644 --- a/src/plugins/directshow/dsserviceplugin.cpp +++ b/src/plugins/directshow/dsserviceplugin.cpp @@ -54,6 +54,7 @@ #include "directshowplayerservice.h" #include <qmediaserviceproviderplugin.h> +#include "directshowutils.h" extern const CLSID CLSID_VideoInputDeviceCategory; @@ -74,28 +75,15 @@ extern const CLSID CLSID_VideoInputDeviceCategory; QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(qtDirectShowPlugin, "qt.multimedia.plugins.directshow") -static int g_refCount = 0; -void addRefCount() -{ - if (++g_refCount == 1) - CoInitialize(nullptr); -} - -void releaseRefCount() -{ - if (--g_refCount == 0) - CoUninitialize(); -} - QMediaService* DSServicePlugin::create(QString const& key) { if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) { - addRefCount(); + DirectShowUtils::CoInitializeIfNeeded(); return new DSCameraService; } if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) { - addRefCount(); + DirectShowUtils::CoInitializeIfNeeded(); return new DirectShowPlayerService; } @@ -105,7 +93,7 @@ QMediaService* DSServicePlugin::create(QString const& key) void DSServicePlugin::release(QMediaService *service) { delete service; - releaseRefCount(); + DirectShowUtils::CoUninitializeIfNeeded(); } QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures( @@ -119,9 +107,9 @@ QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures( QByteArray DSServicePlugin::defaultDevice(const QByteArray &service) const { if (service == Q_MEDIASERVICE_CAMERA) { - addRefCount(); + DirectShowUtils::CoInitializeIfNeeded(); const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices(); - releaseRefCount(); + DirectShowUtils::CoUninitializeIfNeeded(); if (!devs.isEmpty()) return devs.first().first; } @@ -133,9 +121,9 @@ QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const QList<QByteArray> result; if (service == Q_MEDIASERVICE_CAMERA) { - addRefCount(); + DirectShowUtils::CoInitializeIfNeeded(); const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices(); - releaseRefCount(); + DirectShowUtils::CoUninitializeIfNeeded(); for (const DSVideoDeviceInfo &info : devs) result.append(info.first); } @@ -146,9 +134,9 @@ QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) { if (service == Q_MEDIASERVICE_CAMERA) { - addRefCount(); + DirectShowUtils::CoInitializeIfNeeded(); const QList<DSVideoDeviceInfo> &devs = DSVideoDeviceControl::availableDevices(); - releaseRefCount(); + DirectShowUtils::CoUninitializeIfNeeded(); for (const DSVideoDeviceInfo &info : devs) { if (info.first == device) return info.second; |