author | Matthew Gregan <kinetik@flim.org> |
Thu, 28 Nov 2013 14:12:45 +1300 | |
changeset 158045 | 41c241079f2515c0ac764516c38564617e02bfc3 |
parent 158044 | 6c15f3df605a3d1d9df06bc12673dec99b9c2143 |
child 158046 | c84597fb24e0c690da82e303444da6b5ae1ec6bc |
push id | 25731 |
push user | Ms2ger@gmail.com |
push date | Fri, 29 Nov 2013 08:54:33 +0000 |
treeherder | mozilla-central@648926a246c0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | padenot |
bugs | 923992 |
milestone | 28.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
media/libcubeb/README_MOZILLA | file | annotate | diff | comparison | revisions | |
media/libcubeb/src/cubeb_wasapi.cpp | file | annotate | diff | comparison | revisions |
--- a/media/libcubeb/README_MOZILLA +++ b/media/libcubeb/README_MOZILLA @@ -1,8 +1,8 @@ The source from this directory was copied from the cubeb git repository using the update.sh script. The only changes made were those applied by update.sh and the addition of Makefile.in build files for the Mozilla build system. The cubeb git repository is: git://github.com/kinetiknz/cubeb.git -The git commit ID used was e92a27c96c0efd33acf983e4c873376ff4cae3d8. +The git commit ID used was a137c78c4ba1a6b0ebde5548664bdf6390ef5437.
--- a/media/libcubeb/src/cubeb_wasapi.cpp +++ b/media/libcubeb/src/cubeb_wasapi.cpp @@ -83,17 +83,16 @@ typedef HANDLE (WINAPI *set_mm_thread_ch typedef BOOL (WINAPI *revert_mm_thread_characteristics_function)(HANDLE handle); extern cubeb_ops const wasapi_ops; } struct cubeb { cubeb_ops const * ops; - IMMDevice * device; /* Library dynamically opened to increase the render * thread priority, and the two function pointers we need. */ HMODULE mmcss_module; set_mm_thread_characteristics_function set_mm_thread_characteristics; revert_mm_thread_characteristics_function revert_mm_thread_characteristics; }; @@ -395,17 +394,17 @@ wasapi_stream_render_loop(LPVOID stream) LOG("failed to get buffer."); is_playing = false; } } break; default: LOG("case %d not handled in render loop.", waitResult); abort(); - }; + } } if (FAILED(hr)) { stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED); } stm->context->revert_mm_thread_characteristics(mmcss_handle); @@ -419,57 +418,70 @@ HANDLE WINAPI set_mm_thread_characterist { return (HANDLE)1; } BOOL WINAPI revert_mm_thread_characteristics_noop(HANDLE mmcss_handle) { return true; } + +HRESULT get_default_endpoint(IMMDevice ** device) +{ + IMMDeviceEnumerator * enumerator; + HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), + NULL, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&enumerator)); + if (FAILED(hr)) { + LOG("Could not get device enumerator."); + return hr; + } + /* eMultimedia is okay for now ("Music, movies, narration, [...]"). + * We will need to change this when we distinguish streams by use-case, other + * possible values being eConsole ("Games, system notification sounds [...]") + * and eCommunication ("Voice communication"). */ + hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, device); + if (FAILED(hr)) { + LOG("Could not get default audio endpoint."); + SafeRelease(enumerator); + return hr; + } + + SafeRelease(enumerator); + + return ERROR_SUCCESS; +} } // namespace anonymous extern "C" { int wasapi_init(cubeb ** context, char const * context_name) { HRESULT hr; - IMMDeviceEnumerator * enumerator = NULL; hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) { LOG("Could not init COM."); return CUBEB_ERROR; } + /* 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 + support WASAPI. */ + IMMDevice * device; + hr = get_default_endpoint(&device); + if (FAILED(hr)) { + LOG("Could not get device."); + return CUBEB_ERROR; + } + SafeRelease(device); + cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb)); ctx->ops = &wasapi_ops; - hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), - NULL, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&enumerator)); - if (FAILED(hr)) { - LOG("Could not get device enumerator."); - wasapi_destroy(ctx); - return CUBEB_ERROR; - } - - /* eMultimedia is okay for now ("Music, movies, narration, [...]"). - * We will need to change this when we distinguish streams by use-case, other - * possible values being eConsole ("Games, system notification sounds [...]") - * and eCommunication ("Voice communication"). */ - hr = enumerator->GetDefaultAudioEndpoint(eRender, - eMultimedia, - &ctx->device); - if (FAILED(hr)) { - LOG("Could not get default audio endpoint."); - SafeRelease(enumerator); - wasapi_destroy(ctx); - return CUBEB_ERROR; - } - ctx->mmcss_module = LoadLibraryA("Avrt.dll"); if (ctx->mmcss_module) { ctx->set_mm_thread_characteristics = (set_mm_thread_characteristics_function) GetProcAddress( ctx->mmcss_module, "AvSetMmThreadCharacteristicsA"); ctx->revert_mm_thread_characteristics = (revert_mm_thread_characteristics_function) GetProcAddress( @@ -480,59 +492,63 @@ int wasapi_init(cubeb ** context, char c } } else { // This is not a fatal error, but we might end up glitching when // the system is under high load. LOG("Could not load Avrt.dll"); ctx->set_mm_thread_characteristics = &set_mm_thread_characteristics_noop; ctx->revert_mm_thread_characteristics = &revert_mm_thread_characteristics_noop; } - - SafeRelease(enumerator); *context = ctx; return CUBEB_OK; } } namespace { void wasapi_destroy(cubeb * context) { - SafeRelease(context->device); if (context->mmcss_module) { FreeLibrary(context->mmcss_module); } free(context); } char const* wasapi_get_backend_id(cubeb * context) { return "wasapi"; } int wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) { - HRESULT hr; IAudioClient * client; WAVEFORMATEX * mix_format; assert(ctx && max_channels); - hr = ctx->device->Activate(__uuidof(IAudioClient), - CLSCTX_INPROC_SERVER, - NULL, (void **)&client); + IMMDevice * device; + HRESULT hr = get_default_endpoint(&device); + if (FAILED(hr)) { + return CUBEB_ERROR; + } + + hr = device->Activate(__uuidof(IAudioClient), + CLSCTX_INPROC_SERVER, + NULL, (void **)&client); + SafeRelease(device); if (FAILED(hr)) { return CUBEB_ERROR; } hr = client->GetMixFormat(&mix_format); if (FAILED(hr)) { + SafeRelease(client); return CUBEB_ERROR; } *max_channels = mix_format->nChannels; CoTaskMemFree(mix_format); SafeRelease(client); @@ -541,26 +557,36 @@ wasapi_get_max_channel_count(cubeb * ctx int wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_ms) { HRESULT hr; IAudioClient * client; REFERENCE_TIME default_period; - hr = ctx->device->Activate(__uuidof(IAudioClient), - CLSCTX_INPROC_SERVER, - NULL, (void **)&client); + IMMDevice * device; + hr = get_default_endpoint(&device); + if (FAILED(hr)) { + return CUBEB_ERROR; + } + hr = device->Activate(__uuidof(IAudioClient), + CLSCTX_INPROC_SERVER, + NULL, (void **)&client); + SafeRelease(device); if (FAILED(hr)) { return CUBEB_ERROR; } /* The second parameter is for exclusive mode, that we don't use. */ - hr= client->GetDevicePeriod(&default_period, NULL); + hr = client->GetDevicePeriod(&default_period, NULL); + if (FAILED(hr)) { + SafeRelease(client); + return CUBEB_ERROR; + } /* 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 */ *latency_ms = hns_to_ms(default_period); SafeRelease(client); @@ -569,26 +595,31 @@ wasapi_get_min_latency(cubeb * ctx, cube int wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) { HRESULT hr; IAudioClient * client; WAVEFORMATEX * mix_format; - hr = ctx->device->Activate(__uuidof(IAudioClient), - CLSCTX_INPROC_SERVER, - NULL, (void **)&client); + IMMDevice * device; + hr = get_default_endpoint(&device); + if (FAILED(hr)) { + return CUBEB_ERROR; + } + hr = device->Activate(__uuidof(IAudioClient), + CLSCTX_INPROC_SERVER, + NULL, (void **)&client); + SafeRelease(device); if (FAILED(hr)) { return CUBEB_ERROR; } hr = client->GetMixFormat(&mix_format); - if (FAILED(hr)) { SafeRelease(client); return CUBEB_ERROR; } *rate = mix_format->nSamplesPerSec; CoTaskMemFree(mix_format); @@ -706,30 +737,43 @@ wasapi_stream_init(cubeb * context, cube if (!stm->refill_event) { SafeRelease(stm->shutdown_event); LOG("Can't create the refill event, error: %d.", GetLastError()); wasapi_stream_destroy(stm); return CUBEB_ERROR; } + IMMDevice * device; + hr = get_default_endpoint(&device); + if (FAILED(hr)) { + wasapi_stream_destroy(stm); + return CUBEB_ERROR; + } + /* Get a client. We will get all other interfaces we need from * this pointer. */ - hr = context->device->Activate(__uuidof(IAudioClient), - CLSCTX_INPROC_SERVER, - NULL, (void **)&stm->client); + hr = device->Activate(__uuidof(IAudioClient), + CLSCTX_INPROC_SERVER, + NULL, (void **)&stm->client); + SafeRelease(device); if (FAILED(hr)) { LOG("Could not activate the device to get an audio client."); wasapi_stream_destroy(stm); return CUBEB_ERROR; } /* We have to distinguish between the format the mixer uses, * and the format the stream we want to play uses. */ - stm->client->GetMixFormat(&mix_format); + hr = stm->client->GetMixFormat(&mix_format); + if (FAILED(hr)) { + LOG("Could not fetch current mix format from the audio client."); + wasapi_stream_destroy(stm); + return CUBEB_ERROR; + } handle_channel_layout(stm, &mix_format, &stream_params); /* Shared mode WASAPI always supports float32 sample format, so this * is safe. */ stm->mix_params.format = CUBEB_SAMPLE_FLOAT32NE; stm->mix_params.rate = mix_format->nSamplesPerSec; @@ -805,25 +849,25 @@ wasapi_stream_init(cubeb * context, cube hr = stm->client->SetEventHandle(stm->refill_event); if (FAILED(hr)) { LOG("Could set the event handle for the client."); wasapi_stream_destroy(stm); return CUBEB_ERROR; } hr = stm->client->GetService(__uuidof(IAudioRenderClient), - (void **)&stm->render_client); + (void **)&stm->render_client); if (FAILED(hr)) { LOG("Could not get the render client."); wasapi_stream_destroy(stm); return CUBEB_ERROR; } hr = stm->client->GetService(__uuidof(IAudioClock), - (void **)&stm->audio_clock); + (void **)&stm->audio_clock); if (FAILED(hr)) { LOG("Could not get the IAudioClock."); wasapi_stream_destroy(stm); return CUBEB_ERROR; } hr = stm->audio_clock->GetFrequency(&stm->clock_freq); if (FAILED(hr)) {