summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPavel Dubsky <pavel.dubsky@qt.io>2023-05-31 12:28:02 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-06-06 20:49:35 +0000
commit188d92cd2c21e6e32a6c512c447341e28037cbd2 (patch)
tree58deb68d5860000aaf8b8d3b7c4344273a9731e2 /src
parent565950c5c24e5867f49e077bd720999d6a191273 (diff)
Replace calls to CoTaskMemFree via RAII wrapper
This change replaces all uses of task memory object that should be freed with CoTaskMemFree (typically COM-related) with a wrapper class that handles all memory deallocation and provides pointer semantic. Change-Id: I73fe53eaa8ca37eb2ac6c6c05142e10e5a5615e9 Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io> Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Lars Knoll <lars@knoll.priv.no> (cherry picked from commit e988214e3e3f0e9f9005b8be1266a60255eef011) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/multimedia/windows/qcomtaskresource_p.h123
-rw-r--r--src/multimedia/windows/qwindowsaudiosink.cpp17
-rw-r--r--src/multimedia/windows/qwindowsaudiosource.cpp9
-rw-r--r--src/multimedia/windows/qwindowsmediadevices.cpp15
-rw-r--r--src/plugins/multimedia/windows/qwindowsformatinfo.cpp12
-rw-r--r--src/plugins/multimedia/windows/qwindowsvideodevices.cpp18
6 files changed, 137 insertions, 57 deletions
diff --git a/src/multimedia/windows/qcomtaskresource_p.h b/src/multimedia/windows/qcomtaskresource_p.h
index 7d3fd46ba..90554da5e 100644
--- a/src/multimedia/windows/qcomtaskresource_p.h
+++ b/src/multimedia/windows/qcomtaskresource_p.h
@@ -18,40 +18,135 @@
#include <QtCore/qassert.h>
#include <objbase.h>
+#include <algorithm>
+#include <type_traits>
#include <utility>
-template<typename T>
-class QComTaskResource final
+class QEmptyDeleter final
{
public:
- QComTaskResource() = default;
- explicit QComTaskResource(T *resource) : m_resource(resource) { }
- ~QComTaskResource() { reset(); }
+ template<typename T>
+ void operator()(T /*element*/) const
+ {
+ }
+};
- QComTaskResource(const QComTaskResource<T> &source) = delete;
- QComTaskResource &operator=(const QComTaskResource<T> &right) = delete;
+class QComDeleter final
+{
+public:
+ template<typename T>
+ void operator()(T element) const
+ {
+ element->Release();
+ }
+};
+
+template<typename T>
+class QComTaskResourceBase
+{
+public:
+ QComTaskResourceBase(const QComTaskResourceBase<T> &source) = delete;
+ QComTaskResourceBase &operator=(const QComTaskResourceBase<T> &right) = delete;
explicit operator bool() const { return m_resource != nullptr; }
+
+ T *get() const { return m_resource; }
+
+protected:
+ QComTaskResourceBase() = default;
+ explicit QComTaskResourceBase(T *const resource) : m_resource(resource) { }
+
+ T *release() { return std::exchange(m_resource, nullptr); }
+
+ void reset(T *const resource = nullptr)
+ {
+ if (m_resource != resource) {
+ if (m_resource)
+ CoTaskMemFree(m_resource);
+ m_resource = resource;
+ }
+ }
+
+ T *m_resource = nullptr;
+};
+
+template<typename T, typename TElementDeleter = QEmptyDeleter>
+class QComTaskResource final : public QComTaskResourceBase<T>
+{
+ using Base = QComTaskResourceBase<T>;
+
+public:
+ using Base::QComTaskResourceBase;
+
+ ~QComTaskResource() { reset(); }
+
T *operator->() const { return m_resource; }
+ T &operator*() const { return *m_resource; }
T **address()
{
Q_ASSERT(m_resource == nullptr);
return &m_resource;
}
- T *get() const { return m_resource; }
- T *release() { return std::exchange(m_resource, nullptr); }
- void reset(T *resource = nullptr)
+
+ using Base::release;
+ using Base::reset;
+
+private:
+ using Base::m_resource;
+};
+
+template<typename T, typename TElementDeleter>
+class QComTaskResource<T[], TElementDeleter> final : public QComTaskResourceBase<T>
+{
+ using Base = QComTaskResourceBase<T>;
+
+public:
+ QComTaskResource() = default;
+ explicit QComTaskResource(T *const resource, const std::size_t size)
+ : Base(resource), m_size(size)
+ {
+ }
+
+ ~QComTaskResource() { reset(); }
+
+ T &operator[](const std::size_t index) const
+ {
+ Q_ASSERT(index < m_size);
+ return m_resource[index];
+ }
+
+ T *release()
+ {
+ m_size = 0;
+
+ return Base::release();
+ }
+
+ void reset() { reset(nullptr, 0); }
+
+ void reset(T *const resource, const std::size_t size)
{
if (m_resource != resource) {
- if (m_resource)
- CoTaskMemFree(m_resource);
- m_resource = resource;
+ resetElements();
+
+ Base::reset(resource);
+
+ m_size = size;
}
}
private:
- T *m_resource = nullptr;
+ void resetElements()
+ {
+ if constexpr (!std::is_same_v<TElementDeleter, QEmptyDeleter>) {
+ std::for_each(m_resource, m_resource + m_size, TElementDeleter());
+ }
+ }
+
+ std::size_t m_size = 0;
+
+ using Base::m_resource;
};
#endif
diff --git a/src/multimedia/windows/qwindowsaudiosink.cpp b/src/multimedia/windows/qwindowsaudiosink.cpp
index f585b83e2..1957d1cb6 100644
--- a/src/multimedia/windows/qwindowsaudiosink.cpp
+++ b/src/multimedia/windows/qwindowsaudiosink.cpp
@@ -15,6 +15,7 @@
#include "qwindowsaudiosink_p.h"
#include "qwindowsaudioutils_p.h"
#include "qwindowsmultimediautils_p.h"
+#include "qcomtaskresource_p.h"
#include <QtCore/QDataStream>
#include <QtCore/qtimer.h>
@@ -215,8 +216,8 @@ bool QWindowsAudioSink::open()
auto resetClient = qScopeGuard([this](){ m_audioClient.reset(); });
- WAVEFORMATEX *pwfx = nullptr;
- hr = m_audioClient->GetMixFormat(&pwfx);
+ QComTaskResource<WAVEFORMATEX> pwfx;
+ hr = m_audioClient->GetMixFormat(pwfx.address());
if (FAILED(hr)) {
qCWarning(qLcAudioOutput) << "Format unsupported" << errorString(hr);
return false;
@@ -224,7 +225,6 @@ bool QWindowsAudioSink::open()
if (!m_resampler.setup(m_format, QWindowsAudioUtils::waveFormatExToFormat(*pwfx))) {
qCWarning(qLcAudioOutput) << "Failed to set up resampler";
- CoTaskMemFree(pwfx);
return false;
}
@@ -233,15 +233,8 @@ bool QWindowsAudioSink::open()
REFERENCE_TIME requestedDuration = m_format.durationForBytes(m_bufferSize) * 10;
- hr = m_audioClient->Initialize(
- AUDCLNT_SHAREMODE_SHARED,
- 0,
- requestedDuration,
- 0,
- pwfx,
- nullptr);
-
- CoTaskMemFree(pwfx);
+ hr = m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, requestedDuration, 0, pwfx.get(),
+ nullptr);
if (FAILED(hr)) {
qCWarning(qLcAudioOutput) << "Failed to initialize audio client" << errorString(hr);
diff --git a/src/multimedia/windows/qwindowsaudiosource.cpp b/src/multimedia/windows/qwindowsaudiosource.cpp
index fa7a48705..01ac587fd 100644
--- a/src/multimedia/windows/qwindowsaudiosource.cpp
+++ b/src/multimedia/windows/qwindowsaudiosource.cpp
@@ -15,6 +15,7 @@
#include "qwindowsaudiosource_p.h"
#include "qwindowsmultimediautils_p.h"
+#include "qcomtaskresource_p.h"
#include <QtCore/QDataStream>
#include <QtCore/qtimer.h>
@@ -256,8 +257,8 @@ bool QWindowsAudioSource::open()
return false;
}
- WAVEFORMATEX *pwfx = nullptr;
- hr = m_audioClient->GetMixFormat(&pwfx);
+ QComTaskResource<WAVEFORMATEX> pwfx;
+ hr = m_audioClient->GetMixFormat(pwfx.address());
if (FAILED(hr)) {
qCWarning(qLcAudioSource) << "Format unsupported" << errorString(hr);
return false;
@@ -265,7 +266,6 @@ bool QWindowsAudioSource::open()
if (!m_resampler.setup(QWindowsAudioUtils::waveFormatExToFormat(*pwfx), m_format)) {
qCWarning(qLcAudioSource) << "Failed to set up resampler";
- CoTaskMemFree(pwfx);
return false;
}
@@ -274,9 +274,8 @@ bool QWindowsAudioSource::open()
REFERENCE_TIME requestedDuration = m_format.durationForBytes(m_bufferSize);
- hr = m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, requestedDuration, 0, pwfx,
+ hr = m_audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, requestedDuration, 0, pwfx.get(),
nullptr);
- CoTaskMemFree(pwfx);
if (FAILED(hr)) {
qCWarning(qLcAudioSource) << "Failed to initialize audio client" << errorString(hr);
diff --git a/src/multimedia/windows/qwindowsmediadevices.cpp b/src/multimedia/windows/qwindowsmediadevices.cpp
index c6c2b68df..bdb18b160 100644
--- a/src/multimedia/windows/qwindowsmediadevices.cpp
+++ b/src/multimedia/windows/qwindowsmediadevices.cpp
@@ -166,14 +166,12 @@ QWindowsMediaDevices::QWindowsMediaDevices()
for (UINT i = 0; i < count; i++) {
QComPtr<IMMDevice> device;
DWORD state = 0;
- LPWSTR id = nullptr;
+ QComTaskResource<WCHAR> id;
if (SUCCEEDED(devColl->Item(i, device.address()))
&& SUCCEEDED(device->GetState(&state))
- && SUCCEEDED(device->GetId(&id)))
- {
- devState.insert(QString::fromWCharArray(id), state);
- CoTaskMemFree(id);
+ && SUCCEEDED(device->GetId(id.address()))) {
+ devState.insert(QString::fromWCharArray(id.get()), state);
}
}
}
@@ -213,13 +211,12 @@ QList<QAudioDevice> QWindowsMediaDevices::availableDevices(QAudioDevice::Mode mo
const auto defaultAudioDeviceID = [this, audioOut]{
const auto dataFlow = audioOut ? EDataFlow::eRender : EDataFlow::eCapture;
QComPtr<IMMDevice> dev;
- LPWSTR id = nullptr;
+ QComTaskResource<WCHAR> id;
QString sid;
if (SUCCEEDED(m_deviceEnumerator->GetDefaultAudioEndpoint(dataFlow, ERole::eMultimedia, dev.address()))) {
- if (dev && SUCCEEDED(dev->GetId(&id))) {
- sid = QString::fromWCharArray(id);
- CoTaskMemFree(id);
+ if (dev && SUCCEEDED(dev->GetId(id.address()))) {
+ sid = QString::fromWCharArray(id.get());
}
}
return sid.toUtf8();
diff --git a/src/plugins/multimedia/windows/qwindowsformatinfo.cpp b/src/plugins/multimedia/windows/qwindowsformatinfo.cpp
index 28f89c97b..86c57632d 100644
--- a/src/plugins/multimedia/windows/qwindowsformatinfo.cpp
+++ b/src/plugins/multimedia/windows/qwindowsformatinfo.cpp
@@ -7,6 +7,7 @@
#include <mftransform.h>
#include <private/qcomptr_p.h>
#include <private/qwindowsmultimediautils_p.h>
+#include <private/qcomtaskresource_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qset.h>
@@ -33,12 +34,14 @@ template<typename T>
static QSet<T> getCodecSet(GUID category)
{
QSet<T> codecSet;
- IMFActivate **activateArray = nullptr;
+ IMFActivate **activateArrayRaw = nullptr;
UINT32 num = 0;
- HRESULT hr = MFTEnumEx(category, MFT_ENUM_FLAG_ALL, nullptr, nullptr, &activateArray, &num);
+ HRESULT hr = MFTEnumEx(category, MFT_ENUM_FLAG_ALL, nullptr, nullptr, &activateArrayRaw, &num);
if (SUCCEEDED(hr)) {
+ QComTaskResource<IMFActivate *[], QComDeleter> activateArray(activateArrayRaw, num);
+
for (UINT32 i = 0; i < num; ++i) {
QComPtr<IMFTransform> transform;
UINT32 typeIndex = 0;
@@ -61,11 +64,6 @@ static QSet<T> getCodecSet(GUID category)
}
}
}
-
- for (UINT32 i = 0; i < num; ++i)
- activateArray[i]->Release();
-
- CoTaskMemFree(activateArray);
}
return codecSet;
diff --git a/src/plugins/multimedia/windows/qwindowsvideodevices.cpp b/src/plugins/multimedia/windows/qwindowsvideodevices.cpp
index 72a0312bc..5ce94fb8a 100644
--- a/src/plugins/multimedia/windows/qwindowsvideodevices.cpp
+++ b/src/plugins/multimedia/windows/qwindowsvideodevices.cpp
@@ -7,6 +7,7 @@
#include <private/qwindowsmfdefs_p.h>
#include <private/qwindowsmultimediautils_p.h>
#include <private/qcomptr_p.h>
+#include <private/qcomtaskresource_p.h>
#include <dbt.h>
@@ -132,13 +133,11 @@ static std::optional<QCameraFormat> createCameraFormat(IMFMediaType *mediaFormat
static QString getString(IMFActivate *device, const IID &id)
{
- WCHAR *str = NULL;
+ QComTaskResource<WCHAR> str;
UINT32 length = 0;
- HRESULT hr = device->GetAllocatedString(id, &str, &length);
+ HRESULT hr = device->GetAllocatedString(id, str.address(), &length);
if (SUCCEEDED(hr)) {
- auto qstr = QString::fromWCharArray(str);
- CoTaskMemFree(str);
- return qstr;
+ return QString::fromWCharArray(str.get());
} else {
return {};
}
@@ -186,20 +185,19 @@ static QList<QCameraDevice> readCameraDevices(IMFAttributes *attr)
{
QList<QCameraDevice> cameras;
UINT32 count = 0;
- IMFActivate **devices = NULL;
- HRESULT hr = MFEnumDeviceSources(attr, &devices, &count);
+ IMFActivate **devicesRaw = nullptr;
+ HRESULT hr = MFEnumDeviceSources(attr, &devicesRaw, &count);
if (SUCCEEDED(hr)) {
+ QComTaskResource<IMFActivate *[], QComDeleter> devices(devicesRaw, count);
+
for (UINT32 i = 0; i < count; i++) {
IMFActivate *device = devices[i];
if (device) {
auto maybeCamera = createCameraDevice(device);
if (maybeCamera)
cameras << *maybeCamera;
-
- device->Release();
}
}
- CoTaskMemFree(devices);
}
return cameras;
}