Add and refactor functionality into rtc_base/win

This change moves ScopedComInitializer out of core_audio_utility and
into rtc_base/win so it can be reused elsewhere more easily.

It also adds HSTRING and GetActivationFactory functionality to
rtc_base/win. These two were heavily based on what is already present
base/win.

All of these are necessary for the new window capturer based on the
Windows.Graphics.Capture API. You can see how these APIs will be
used in this CL: 186603: Implement WgcCaptureSession |
https://webrtc-review.googlesource.com/c/src/+/186603

Bug: webrtc:9273
Change-Id: I0a36373aac98be779ccbabe1053bb8d6e234f6a3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188523
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32522}
This commit is contained in:
Austin Orion 2020-10-29 11:30:10 -07:00 committed by Commit Bot
parent 842b675304
commit 0bb354c540
17 changed files with 340 additions and 124 deletions

View File

@ -38,8 +38,8 @@
#ifdef WEBRTC_WIN
#include "modules/audio_device/include/audio_device_factory.h"
#include "modules/audio_device/win/core_audio_utility_win.h"
#endif
#include "rtc_base/win/scoped_com_initializer.h"
#endif // WEBRTC_WIN
using ::testing::_;
using ::testing::AtLeast;
@ -596,8 +596,8 @@ class MAYBE_AudioDeviceTest
// We must initialize the COM library on a thread before we calling any of
// the library functions. All COM functions in the ADM will return
// CO_E_NOTINITIALIZED otherwise.
com_initializer_ = std::make_unique<webrtc_win::ScopedCOMInitializer>(
webrtc_win::ScopedCOMInitializer::kMTA);
com_initializer_ =
std::make_unique<ScopedCOMInitializer>(ScopedCOMInitializer::kMTA);
EXPECT_TRUE(com_initializer_->Succeeded());
EXPECT_TRUE(webrtc_win::core_audio_utility::IsSupported());
EXPECT_TRUE(webrtc_win::core_audio_utility::IsMMCSSSupported());
@ -656,7 +656,7 @@ class MAYBE_AudioDeviceTest
private:
#ifdef WEBRTC_WIN
// Windows Core Audio based ADM needs to run on a COM initialized thread.
std::unique_ptr<webrtc_win::ScopedCOMInitializer> com_initializer_;
std::unique_ptr<ScopedCOMInitializer> com_initializer_;
#endif
AudioDeviceModule::AudioLayer audio_layer_;
std::unique_ptr<TaskQueueFactory> task_queue_factory_;
@ -691,8 +691,7 @@ TEST(MAYBE_AudioDeviceTestWin, ConstructDestructWithFactory) {
// CreateWindowsCoreAudioAudioDeviceModule() can be used on Windows and that
// it sets the audio layer to kWindowsCoreAudio2 implicitly. Note that, the
// new ADM for Windows must be created on a COM thread.
webrtc_win::ScopedCOMInitializer com_initializer(
webrtc_win::ScopedCOMInitializer::kMTA);
ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
EXPECT_TRUE(com_initializer.Succeeded());
audio_device =
CreateWindowsCoreAudioAudioDeviceModule(task_queue_factory.get());

View File

@ -38,7 +38,7 @@ CreateWindowsCoreAudioAudioDeviceModuleForTest(
bool automatic_restart) {
RTC_DLOG(INFO) << __FUNCTION__;
// Returns NULL if Core Audio is not supported or if COM has not been
// initialized correctly using webrtc_win::ScopedCOMInitializer.
// initialized correctly using ScopedCOMInitializer.
if (!webrtc_win::core_audio_utility::IsSupported()) {
RTC_LOG(LS_ERROR)
<< "Unable to create ADM since Core Audio is not supported";

View File

@ -30,8 +30,8 @@ namespace webrtc {
// rtc::scoped_refptr<AudioDeviceModule> CreateAudioDevice() {
// task_queue_factory_ = CreateDefaultTaskQueueFactory();
// // Tell COM that this thread shall live in the MTA.
// com_initializer_ = std::make_unique<webrtc_win::ScopedCOMInitializer>(
// webrtc_win::ScopedCOMInitializer::kMTA);
// com_initializer_ = std::make_unique<ScopedCOMInitializer>(
// ScopedCOMInitializer::kMTA);
// if (!com_initializer_->Succeeded()) {
// return nullptr;
// }
@ -42,7 +42,7 @@ namespace webrtc {
// }
//
// private:
// std::unique_ptr<webrtc_win::ScopedCOMInitializer> com_initializer_;
// std::unique_ptr<ScopedCOMInitializer> com_initializer_;
// std::unique_ptr<TaskQueueFactory> task_queue_factory_;
//
rtc::scoped_refptr<AudioDeviceModule> CreateWindowsCoreAudioAudioDeviceModule(

View File

@ -38,6 +38,7 @@
#include <iomanip>
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/platform_thread.h"
#include "rtc_base/string_utils.h"
@ -226,7 +227,7 @@ bool AudioDeviceWindowsCore::CoreAudioIsSupported() {
// by a corresponding call to CoUninitialize.
//
ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA);
if (!comInit.succeeded()) {
if (!comInit.Succeeded()) {
// Things will work even if an STA thread is calling this method but we
// want to ensure that MTA is used and therefore return false here.
return false;
@ -395,7 +396,7 @@ AudioDeviceWindowsCore::AudioDeviceWindowsCore()
_inputDeviceIndex(0),
_outputDeviceIndex(0) {
RTC_LOG(LS_INFO) << __FUNCTION__ << " created";
assert(_comInit.succeeded());
RTC_DCHECK(_comInit.Succeeded());
// Try to load the Avrt DLL
if (!_avrtLibrary) {
@ -2364,7 +2365,6 @@ int32_t AudioDeviceWindowsCore::StartRecording() {
// Set thread priority to highest possible
SetThreadPriority(_hRecThread, THREAD_PRIORITY_TIME_CRITICAL);
} // critScoped
DWORD ret = WaitForSingleObject(_hCaptureStartedEvent, 1000);
@ -2652,7 +2652,7 @@ DWORD AudioDeviceWindowsCore::DoRenderThread() {
// Initialize COM as MTA in this thread.
ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA);
if (!comInit.succeeded()) {
if (!comInit.Succeeded()) {
RTC_LOG(LS_ERROR) << "failed to initialize COM in render thread";
return 1;
}
@ -2959,7 +2959,7 @@ DWORD AudioDeviceWindowsCore::DoCaptureThreadPollDMO() {
// Initialize COM as MTA in this thread.
ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA);
if (!comInit.succeeded()) {
if (!comInit.Succeeded()) {
RTC_LOG(LS_ERROR) << "failed to initialize COM in polling DMO thread";
return 1;
}
@ -3091,7 +3091,7 @@ DWORD AudioDeviceWindowsCore::DoCaptureThread() {
// Initialize COM as MTA in this thread.
ScopedCOMInitializer comInit(ScopedCOMInitializer::kMTA);
if (!comInit.succeeded()) {
if (!comInit.Succeeded()) {
RTC_LOG(LS_ERROR) << "failed to initialize COM in capture thread";
return 1;
}
@ -3427,7 +3427,7 @@ int AudioDeviceWindowsCore::SetDMOProperties() {
// MFPKEY_WMAAECMA_FEATR_AGC - Digital AGC (disabled).
// MFPKEY_WMAAECMA_FEATR_CENTER_CLIP - AEC center clipping (enabled).
// MFPKEY_WMAAECMA_FEATR_ECHO_LENGTH - Filter length (256 ms).
// TODO(andrew): investigate decresing the length to 128 ms.
// TODO(andrew): investigate decresing the length to 128 ms.
// MFPKEY_WMAAECMA_FEATR_FRAME_SIZE - Frame size (0).
// 0 is automatic; defaults to 160 samples (or 10 ms frames at the
// selected 16 kHz) as long as mic array processing is disabled.

View File

@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_
#define AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_
#ifndef MODULES_AUDIO_DEVICE_WIN_AUDIO_DEVICE_CORE_WIN_H_
#define MODULES_AUDIO_DEVICE_WIN_AUDIO_DEVICE_CORE_WIN_H_
#if (_MSC_VER >= 1400) // only include for VS 2005 and higher
@ -28,6 +28,7 @@
#include "api/scoped_refptr.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/win/scoped_com_initializer.h"
// Use Multimedia Class Scheduler Service (MMCSS) to boost the thread priority
#pragma comment(lib, "avrt.lib")
@ -45,37 +46,6 @@ const float MIN_CORE_MICROPHONE_VOLUME = 0.0f;
const uint16_t CORE_SPEAKER_VOLUME_STEP_SIZE = 1;
const uint16_t CORE_MICROPHONE_VOLUME_STEP_SIZE = 1;
// Utility class which initializes COM in the constructor (STA or MTA),
// and uninitializes COM in the destructor.
class ScopedCOMInitializer {
public:
// Enum value provided to initialize the thread as an MTA instead of STA.
enum SelectMTA { kMTA };
// Constructor for STA initialization.
ScopedCOMInitializer() { Initialize(COINIT_APARTMENTTHREADED); }
// Constructor for MTA initialization.
explicit ScopedCOMInitializer(SelectMTA mta) {
Initialize(COINIT_MULTITHREADED);
}
~ScopedCOMInitializer() {
if (SUCCEEDED(hr_))
CoUninitialize();
}
bool succeeded() const { return SUCCEEDED(hr_); }
private:
void Initialize(COINIT init) { hr_ = CoInitializeEx(NULL, init); }
HRESULT hr_;
ScopedCOMInitializer(const ScopedCOMInitializer&);
void operator=(const ScopedCOMInitializer&);
};
class AudioDeviceWindowsCore : public AudioDeviceGeneric {
public:
AudioDeviceWindowsCore();
@ -327,4 +297,4 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric {
} // namespace webrtc
#endif // AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_
#endif // MODULES_AUDIO_DEVICE_WIN_AUDIO_DEVICE_CORE_WIN_H_

View File

@ -19,6 +19,7 @@
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/time_utils.h"
#include "rtc_base/win/scoped_com_initializer.h"
#include "rtc_base/win/windows_version.h"
using Microsoft::WRL::ComPtr;
@ -796,7 +797,7 @@ HRESULT CoreAudioBase::QueryInterface(REFIID iid, void** object) {
if (iid == IID_IUnknown || iid == __uuidof(IAudioSessionEvents)) {
*object = static_cast<IAudioSessionEvents*>(this);
return S_OK;
};
}
*object = nullptr;
return E_NOINTERFACE;
}

View File

@ -118,71 +118,6 @@ class ScopedMMCSSRegistration {
HANDLE mmcss_handle_ = nullptr;
};
// Initializes COM in the constructor (STA or MTA), and uninitializes COM in the
// destructor. Taken from base::win::ScopedCOMInitializer.
//
// WARNING: This should only be used once per thread, ideally scoped to a
// similar lifetime as the thread itself. You should not be using this in
// random utility functions that make COM calls; instead ensure that these
// functions are running on a COM-supporting thread!
// See https://msdn.microsoft.com/en-us/library/ms809971.aspx for details.
class ScopedCOMInitializer {
public:
// Enum value provided to initialize the thread as an MTA instead of STA.
// There are two types of apartments, Single Threaded Apartments (STAs)
// and Multi Threaded Apartments (MTAs). Within a given process there can
// be multiple STAs but there is only one MTA. STA is typically used by
// "GUI applications" and MTA by "worker threads" with no UI message loop.
enum SelectMTA { kMTA };
// Constructor for STA initialization.
ScopedCOMInitializer() {
RTC_DLOG(INFO) << "Single-Threaded Apartment (STA) COM thread";
Initialize(COINIT_APARTMENTTHREADED);
}
// Constructor for MTA initialization.
explicit ScopedCOMInitializer(SelectMTA mta) {
RTC_DLOG(INFO) << "Multi-Threaded Apartment (MTA) COM thread";
Initialize(COINIT_MULTITHREADED);
}
~ScopedCOMInitializer() {
if (Succeeded()) {
CoUninitialize();
}
}
ScopedCOMInitializer(const ScopedCOMInitializer&) = delete;
ScopedCOMInitializer& operator=(const ScopedCOMInitializer&) = delete;
bool Succeeded() { return SUCCEEDED(hr_); }
private:
void Initialize(COINIT init) {
// Initializes the COM library for use by the calling thread, sets the
// thread's concurrency model, and creates a new apartment for the thread
// if one is required. CoInitializeEx must be called at least once, and is
// usually called only once, for each thread that uses the COM library.
hr_ = CoInitializeEx(NULL, init);
RTC_CHECK_NE(RPC_E_CHANGED_MODE, hr_)
<< "Invalid COM thread model change (MTA->STA)";
// Multiple calls to CoInitializeEx by the same thread are allowed as long
// as they pass the same concurrency flag, but subsequent valid calls
// return S_FALSE. To close the COM library gracefully on a thread, each
// successful call to CoInitializeEx, including any call that returns
// S_FALSE, must be balanced by a corresponding call to CoUninitialize.
if (hr_ == S_OK) {
RTC_DLOG(INFO)
<< "The COM library was initialized successfully on this thread";
} else if (hr_ == S_FALSE) {
RTC_DLOG(WARNING)
<< "The COM library is already initialized on this thread";
}
}
HRESULT hr_;
};
// A PROPVARIANT that is automatically initialized and cleared upon respective
// construction and destruction of this class.
class ScopedPropVariant {
@ -323,7 +258,7 @@ class ScopedHandle {
// Always ensure that Core Audio is supported before using these methods.
// Use webrtc_win::core_audio_utility::IsSupported() for this purpose.
// Also, all methods must be called on a valid COM thread. This can be done
// by using the webrtc_win::ScopedCOMInitializer helper class.
// by using the ScopedCOMInitializer helper class.
// These methods are based on media::CoreAudioUtil in Chrome.
namespace core_audio_utility {

View File

@ -11,6 +11,7 @@
#include "modules/audio_device/win/core_audio_utility_win.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/logging.h"
#include "rtc_base/win/scoped_com_initializer.h"
#include "rtc_base/win/windows_version.h"
#include "test/gtest.h"
@ -54,8 +55,7 @@ bool ShouldAbortTest(bool requirements_satisfied,
// CoreAudioUtilityWinTest test fixture.
class CoreAudioUtilityWinTest : public ::testing::Test {
protected:
CoreAudioUtilityWinTest()
: com_init_(webrtc_win::ScopedCOMInitializer::kMTA) {
CoreAudioUtilityWinTest() : com_init_(ScopedCOMInitializer::kMTA) {
// We must initialize the COM library on a thread before we calling any of
// the library functions. All COM functions will return CO_E_NOTINITIALIZED
// otherwise.

View File

@ -124,6 +124,12 @@ rtc_library("rtc_base_approved") {
if (is_win) {
sources += [
"win/get_activation_factory.cc",
"win/get_activation_factory.h",
"win/hstring.cc",
"win/hstring.h",
"win/scoped_com_initializer.cc",
"win/scoped_com_initializer.h",
"win/windows_version.cc",
"win/windows_version.h",
]

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/win/get_activation_factory.h"
#include <libloaderapi.h>
#include <roapi.h>
namespace {
FARPROC LoadComBaseFunction(const char* function_name) {
static HMODULE const handle =
::LoadLibraryExW(L"combase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
return handle ? ::GetProcAddress(handle, function_name) : nullptr;
}
decltype(&::RoGetActivationFactory) GetRoGetActivationFactoryFunction() {
static decltype(&::RoGetActivationFactory) const function =
reinterpret_cast<decltype(&::RoGetActivationFactory)>(
LoadComBaseFunction("RoGetActivationFactory"));
return function;
}
} // namespace
namespace webrtc {
bool ResolveCoreWinRTDelayload() {
return GetRoGetActivationFactoryFunction() &&
ResolveCoreWinRTStringDelayload();
}
HRESULT RoGetActivationFactoryProxy(HSTRING class_id,
const IID& iid,
void** out_factory) {
auto get_factory_func = GetRoGetActivationFactoryFunction();
if (!get_factory_func)
return E_FAIL;
return get_factory_func(class_id, iid, out_factory);
}
} // namespace webrtc

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_WIN_GET_ACTIVATION_FACTORY_H_
#define RTC_BASE_WIN_GET_ACTIVATION_FACTORY_H_
#include <winerror.h>
#include "rtc_base/win/hstring.h"
namespace webrtc {
// Provides access to Core WinRT functions which may not be available on
// Windows 7. Loads functions dynamically at runtime to prevent library
// dependencies.
// Callers must check the return value of ResolveCoreWinRTDelayLoad() before
// using these functions.
bool ResolveCoreWinRTDelayload();
HRESULT RoGetActivationFactoryProxy(HSTRING class_id,
const IID& iid,
void** out_factory);
// Retrieves an activation factory for the type specified.
template <typename InterfaceType, wchar_t const* runtime_class_id>
HRESULT GetActivationFactory(InterfaceType** factory) {
HSTRING class_id_hstring;
HRESULT hr = CreateHstring(runtime_class_id, wcslen(runtime_class_id),
&class_id_hstring);
if (FAILED(hr))
return hr;
hr = RoGetActivationFactoryProxy(class_id_hstring, IID_PPV_ARGS(factory));
if (FAILED(hr))
return hr;
return DeleteHstring(class_id_hstring);
}
} // namespace webrtc
#endif // RTC_BASE_WIN_GET_ACTIVATION_FACTORY_H_

62
rtc_base/win/hstring.cc Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/win/hstring.h"
#include <libloaderapi.h>
#include <winstring.h>
namespace {
FARPROC LoadComBaseFunction(const char* function_name) {
static HMODULE const handle =
::LoadLibraryExW(L"combase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
return handle ? ::GetProcAddress(handle, function_name) : nullptr;
}
decltype(&::WindowsCreateString) GetWindowsCreateString() {
static decltype(&::WindowsCreateString) const function =
reinterpret_cast<decltype(&::WindowsCreateString)>(
LoadComBaseFunction("WindowsCreateString"));
return function;
}
decltype(&::WindowsDeleteString) GetWindowsDeleteString() {
static decltype(&::WindowsDeleteString) const function =
reinterpret_cast<decltype(&::WindowsDeleteString)>(
LoadComBaseFunction("WindowsDeleteString"));
return function;
}
} // namespace
namespace webrtc {
bool ResolveCoreWinRTStringDelayload() {
return GetWindowsDeleteString() && GetWindowsCreateString();
}
HRESULT CreateHstring(const wchar_t* src, uint32_t len, HSTRING* out_hstr) {
decltype(&::WindowsCreateString) create_string_func =
GetWindowsCreateString();
if (!create_string_func)
return E_FAIL;
return create_string_func(src, len, out_hstr);
}
HRESULT DeleteHstring(HSTRING hstr) {
decltype(&::WindowsDeleteString) delete_string_func =
GetWindowsDeleteString();
if (!delete_string_func)
return E_FAIL;
return delete_string_func(hstr);
}
} // namespace webrtc

30
rtc_base/win/hstring.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_WIN_HSTRING_H_
#define RTC_BASE_WIN_HSTRING_H_
#include <hstring.h>
#include <stdint.h>
#include <winerror.h>
namespace webrtc {
// Callers must check the return value of ResolveCoreWinRTStringDelayLoad()
// before using these functions.
bool ResolveCoreWinRTStringDelayload();
HRESULT CreateHstring(const wchar_t* src, uint32_t len, HSTRING* out_hstr);
HRESULT DeleteHstring(HSTRING hstr);
} // namespace webrtc
#endif // RTC_BASE_WIN_HSTRING_H_

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/win/scoped_com_initializer.h"
namespace webrtc {
ScopedCOMInitializer::ScopedCOMInitializer() {
RTC_DLOG(INFO) << "Single-Threaded Apartment (STA) COM thread";
Initialize(COINIT_APARTMENTTHREADED);
}
// Constructor for MTA initialization.
ScopedCOMInitializer::ScopedCOMInitializer(SelectMTA mta) {
RTC_DLOG(INFO) << "Multi-Threaded Apartment (MTA) COM thread";
Initialize(COINIT_MULTITHREADED);
}
ScopedCOMInitializer::~ScopedCOMInitializer() {
if (Succeeded()) {
CoUninitialize();
}
}
void ScopedCOMInitializer::Initialize(COINIT init) {
// Initializes the COM library for use by the calling thread, sets the
// thread's concurrency model, and creates a new apartment for the thread
// if one is required. CoInitializeEx must be called at least once, and is
// usually called only once, for each thread that uses the COM library.
hr_ = CoInitializeEx(NULL, init);
RTC_CHECK_NE(RPC_E_CHANGED_MODE, hr_)
<< "Invalid COM thread model change (MTA->STA)";
// Multiple calls to CoInitializeEx by the same thread are allowed as long
// as they pass the same concurrency flag, but subsequent valid calls
// return S_FALSE. To close the COM library gracefully on a thread, each
// successful call to CoInitializeEx, including any call that returns
// S_FALSE, must be balanced by a corresponding call to CoUninitialize.
if (hr_ == S_OK) {
RTC_DLOG(INFO)
<< "The COM library was initialized successfully on this thread";
} else if (hr_ == S_FALSE) {
RTC_DLOG(WARNING)
<< "The COM library is already initialized on this thread";
}
}
} // namespace webrtc

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_BASE_WIN_SCOPED_COM_INITIALIZER_H_
#define RTC_BASE_WIN_SCOPED_COM_INITIALIZER_H_
#include <comdef.h>
#include "rtc_base/logging.h"
namespace webrtc {
// Initializes COM in the constructor (STA or MTA), and uninitializes COM in the
// destructor. Taken from base::win::ScopedCOMInitializer.
//
// WARNING: This should only be used once per thread, ideally scoped to a
// similar lifetime as the thread itself. You should not be using this in
// random utility functions that make COM calls; instead ensure that these
// functions are running on a COM-supporting thread!
// See https://msdn.microsoft.com/en-us/library/ms809971.aspx for details.
class ScopedCOMInitializer {
public:
// Enum value provided to initialize the thread as an MTA instead of STA.
// There are two types of apartments, Single Threaded Apartments (STAs)
// and Multi Threaded Apartments (MTAs). Within a given process there can
// be multiple STAs but there is only one MTA. STA is typically used by
// "GUI applications" and MTA by "worker threads" with no UI message loop.
enum SelectMTA { kMTA };
// Constructor for STA initialization.
ScopedCOMInitializer();
// Constructor for MTA initialization.
explicit ScopedCOMInitializer(SelectMTA mta);
~ScopedCOMInitializer();
ScopedCOMInitializer(const ScopedCOMInitializer&) = delete;
ScopedCOMInitializer& operator=(const ScopedCOMInitializer&) = delete;
bool Succeeded() { return SUCCEEDED(hr_); }
private:
void Initialize(COINIT init);
HRESULT hr_;
};
} // namespace webrtc
#endif // RTC_BASE_WIN_SCOPED_COM_INITIALIZER_H_

View File

@ -1348,8 +1348,8 @@ rtc::scoped_refptr<AudioDeviceModule> VideoQualityTest::CreateAudioDevice() {
// CO_E_NOTINITIALIZED otherwise. The legacy ADM for Windows used internal
// COM initialization but the new ADM requires COM to be initialized
// externally.
com_initializer_ = std::make_unique<webrtc_win::ScopedCOMInitializer>(
webrtc_win::ScopedCOMInitializer::kMTA);
com_initializer_ =
std::make_unique<ScopedCOMInitializer>(ScopedCOMInitializer::kMTA);
RTC_CHECK(com_initializer_->Succeeded());
RTC_CHECK(webrtc_win::core_audio_utility::IsSupported());
RTC_CHECK(webrtc_win::core_audio_utility::IsMMCSSSupported());

View File

@ -30,6 +30,7 @@
#include "video/video_analyzer.h"
#ifdef WEBRTC_WIN
#include "modules/audio_device/win/core_audio_utility_win.h"
#include "rtc_base/win/scoped_com_initializer.h"
#endif
namespace webrtc {
@ -137,7 +138,7 @@ class VideoQualityTest : public test::CallTest,
#ifdef WEBRTC_WIN
// Windows Core Audio based ADM needs to run on a COM initialized thread.
// Only referenced in combination with --audio --use_real_adm flags.
std::unique_ptr<webrtc_win::ScopedCOMInitializer> com_initializer_;
std::unique_ptr<ScopedCOMInitializer> com_initializer_;
#endif
};