зеркало из https://github.com/mozilla/gecko-dev.git
Bug 848954 - Part 12 - Make sure COM is initialized when calling into WASAPI functions. r=kinetik
This commit is contained in:
Родитель
94dff88eb5
Коммит
b1ff1946e0
|
@ -68,6 +68,35 @@ void SafeRelease(T * ptr)
|
|||
}
|
||||
}
|
||||
|
||||
struct auto_com {
|
||||
auto_com()
|
||||
: need_uninit(true) {
|
||||
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
// This is for information purposes only, in anycase, COM is initialized
|
||||
// at the end of the constructor.
|
||||
if (hr == RPC_E_CHANGED_MODE) {
|
||||
// This is an error, COM was not initialized by this function, so it is
|
||||
// not necessary to uninit it.
|
||||
LOG("COM already initialized in STA.");
|
||||
need_uninit = false;
|
||||
} else if (hr == S_FALSE) {
|
||||
// This is not an error. We are allowed to call CoInitializeEx more than
|
||||
// once, as long as it is matches by an CoUninitialize call.
|
||||
// We do that in the dtor which is guaranteed to be called.
|
||||
LOG("COM already initialized in MTA");
|
||||
} else if (hr == S_OK) {
|
||||
LOG("COM initialized.");
|
||||
}
|
||||
}
|
||||
~auto_com() {
|
||||
if (need_uninit) {
|
||||
CoUninitialize();
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool need_uninit;
|
||||
};
|
||||
|
||||
typedef HANDLE (WINAPI *set_mm_thread_characteristics_function)(
|
||||
const char* TaskName, LPDWORD TaskIndex);
|
||||
typedef BOOL (WINAPI *revert_mm_thread_characteristics_function)(HANDLE handle);
|
||||
|
@ -244,6 +273,7 @@ wasapi_stream_render_loop(LPVOID stream)
|
|||
HRESULT hr;
|
||||
bool first = true;
|
||||
DWORD mmcss_task_index = 0;
|
||||
auto_com com;
|
||||
|
||||
/* We could consider using "Pro Audio" here for WebAudio and
|
||||
* maybe WebRTC. */
|
||||
|
@ -254,11 +284,6 @@ wasapi_stream_render_loop(LPVOID stream)
|
|||
LOG("Unable to use mmcss to bump the render thread priority: %x", GetLastError());
|
||||
}
|
||||
|
||||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr)) {
|
||||
LOG("could not initialize COM in render thread: %x", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
while (is_playing) {
|
||||
DWORD waitResult = WaitForMultipleObjects(ARRAY_LENGTH(wait_array),
|
||||
|
@ -329,7 +354,6 @@ wasapi_stream_render_loop(LPVOID stream)
|
|||
|
||||
stm->context->revert_mm_thread_characteristics(mmcss_handle);
|
||||
|
||||
CoUninitialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -376,12 +400,7 @@ extern "C" {
|
|||
int wasapi_init(cubeb ** context, char const * context_name)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not init COM.");
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
auto_com com;
|
||||
|
||||
/* We don't use the device yet, but need to make sure we can initialize one
|
||||
so that this backend is not incorrectly enabled on platforms that don't
|
||||
|
@ -443,13 +462,15 @@ char const* wasapi_get_backend_id(cubeb * context)
|
|||
int
|
||||
wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
|
||||
{
|
||||
HRESULT hr;
|
||||
IAudioClient * client;
|
||||
WAVEFORMATEX * mix_format;
|
||||
auto_com com;
|
||||
|
||||
assert(ctx && max_channels);
|
||||
|
||||
IMMDevice * device;
|
||||
HRESULT hr = get_default_endpoint(&device);
|
||||
hr = get_default_endpoint(&device);
|
||||
if (FAILED(hr)) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
@ -482,10 +503,12 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
|
|||
HRESULT hr;
|
||||
IAudioClient * client;
|
||||
REFERENCE_TIME default_period;
|
||||
auto_com com;
|
||||
|
||||
IMMDevice * device;
|
||||
hr = get_default_endpoint(&device);
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not get default endpoint:%x.", hr)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
|
@ -494,6 +517,7 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
|
|||
NULL, (void **)&client);
|
||||
SafeRelease(device);
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not activate device for latency: %x.", hr)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
|
@ -501,9 +525,12 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
|
|||
hr = client->GetDevicePeriod(&default_period, NULL);
|
||||
if (FAILED(hr)) {
|
||||
SafeRelease(client);
|
||||
LOG("Could not get device period: %x.", hr)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
LOG("default device period: %ld", default_period)
|
||||
|
||||
/* According to the docs, the best latency we can achieve is by synchronizing
|
||||
* the stream and the engine.
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/dd370871%28v=vs.85%29.aspx */
|
||||
|
@ -520,6 +547,7 @@ wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
|||
HRESULT hr;
|
||||
IAudioClient * client;
|
||||
WAVEFORMATEX * mix_format;
|
||||
auto_com com;
|
||||
|
||||
IMMDevice * device;
|
||||
hr = get_default_endpoint(&device);
|
||||
|
@ -627,15 +655,10 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
{
|
||||
HRESULT hr;
|
||||
WAVEFORMATEX * mix_format;
|
||||
auto_com com;
|
||||
|
||||
assert(context && stream);
|
||||
|
||||
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not initialize COM.");
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
cubeb_stream * stm = (cubeb_stream *)calloc(1, sizeof(cubeb_stream));
|
||||
|
||||
assert(stm);
|
||||
|
@ -808,7 +831,6 @@ void wasapi_stream_destroy(cubeb_stream * stm)
|
|||
|
||||
free(stm->mix_buffer);
|
||||
free(stm);
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
int wasapi_stream_start(cubeb_stream * stm)
|
||||
|
|
Загрузка…
Ссылка в новой задаче