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:
parent
842b675304
commit
0bb354c540
@ -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());
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 STA’s 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 {
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
49
rtc_base/win/get_activation_factory.cc
Normal file
49
rtc_base/win/get_activation_factory.cc
Normal 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
|
||||
51
rtc_base/win/get_activation_factory.h
Normal file
51
rtc_base/win/get_activation_factory.h
Normal 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
62
rtc_base/win/hstring.cc
Normal 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
30
rtc_base/win/hstring.h
Normal 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_
|
||||
54
rtc_base/win/scoped_com_initializer.cc
Normal file
54
rtc_base/win/scoped_com_initializer.cc
Normal 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
|
||||
58
rtc_base/win/scoped_com_initializer.h
Normal file
58
rtc_base/win/scoped_com_initializer.h
Normal 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 STA’s 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_
|
||||
@ -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());
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user