diff options
author | Pavel Dubsky <pavel.dubsky@qt.io> | 2023-05-31 12:28:02 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-06-06 20:49:35 +0000 |
commit | 188d92cd2c21e6e32a6c512c447341e28037cbd2 (patch) | |
tree | 58deb68d5860000aaf8b8d3b7c4344273a9731e2 /src | |
parent | 565950c5c24e5867f49e077bd720999d6a191273 (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.h | 123 | ||||
-rw-r--r-- | src/multimedia/windows/qwindowsaudiosink.cpp | 17 | ||||
-rw-r--r-- | src/multimedia/windows/qwindowsaudiosource.cpp | 9 | ||||
-rw-r--r-- | src/multimedia/windows/qwindowsmediadevices.cpp | 15 | ||||
-rw-r--r-- | src/plugins/multimedia/windows/qwindowsformatinfo.cpp | 12 | ||||
-rw-r--r-- | src/plugins/multimedia/windows/qwindowsvideodevices.cpp | 18 |
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; } |