Bug 848954 - Part 12 - Make sure COM is initialized when calling into WASAPI functions. r=kinetik

This commit is contained in:
Paul Adenot 2014-08-26 17:01:35 +02:00
Родитель 94dff88eb5
Коммит b1ff1946e0
1 изменённых файлов: 42 добавлений и 20 удалений

Просмотреть файл

@ -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)