| Index: media/audio/win/core_audio_util_win.cc
|
| diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc
|
| index 2c262b4e72d37026199881a3fdaae3ef37601964..efa796ae0c602a851a5660c2bdb77f12d63a1c4f 100644
|
| --- a/media/audio/win/core_audio_util_win.cc
|
| +++ b/media/audio/win/core_audio_util_win.cc
|
| @@ -138,7 +138,7 @@ AUDCLNT_SHAREMODE CoreAudioUtil::GetShareMode() {
|
| }
|
|
|
| int CoreAudioUtil::NumberOfActiveDevices(EDataFlow data_flow) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| // Create the IMMDeviceEnumerator interface.
|
| ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
|
| CreateDeviceEnumerator();
|
| @@ -166,7 +166,7 @@ int CoreAudioUtil::NumberOfActiveDevices(EDataFlow data_flow) {
|
| }
|
|
|
| ScopedComPtr<IMMDeviceEnumerator> CoreAudioUtil::CreateDeviceEnumerator() {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMDeviceEnumerator> device_enumerator;
|
| HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
|
| NULL,
|
| @@ -181,7 +181,7 @@ ScopedComPtr<IMMDeviceEnumerator> CoreAudioUtil::CreateDeviceEnumerator() {
|
|
|
| ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDefaultDevice(EDataFlow data_flow,
|
| ERole role) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMDevice> endpoint_device;
|
|
|
| // Create the IMMDeviceEnumerator interface.
|
| @@ -216,7 +216,7 @@ ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDefaultDevice(EDataFlow data_flow,
|
|
|
| ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDevice(
|
| const std::string& device_id) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMDevice> endpoint_device;
|
|
|
| // Create the IMMDeviceEnumerator interface.
|
| @@ -235,7 +235,7 @@ ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDevice(
|
| }
|
|
|
| HRESULT CoreAudioUtil::GetDeviceName(IMMDevice* device, AudioDeviceName* name) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
|
|
| // Retrieve unique name of endpoint device.
|
| // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}".
|
| @@ -270,7 +270,7 @@ HRESULT CoreAudioUtil::GetDeviceName(IMMDevice* device, AudioDeviceName* name) {
|
| }
|
|
|
| std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMDevice> audio_device = CreateDevice(device_id);
|
| if (!audio_device)
|
| return std::string();
|
| @@ -286,7 +286,7 @@ std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) {
|
| bool CoreAudioUtil::DeviceIsDefault(EDataFlow flow,
|
| ERole role,
|
| std::string device_id) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role);
|
| if (!device)
|
| return false;
|
| @@ -304,7 +304,7 @@ bool CoreAudioUtil::DeviceIsDefault(EDataFlow flow,
|
| }
|
|
|
| EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMEndpoint> endpoint;
|
| HRESULT hr = device->QueryInterface(endpoint.Receive());
|
| if (FAILED(hr)) {
|
| @@ -323,7 +323,7 @@ EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) {
|
|
|
| ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient(
|
| IMMDevice* audio_device) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
|
|
| // Creates and activates an IAudioClient COM object given the selected
|
| // endpoint device.
|
| @@ -338,7 +338,7 @@ ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient(
|
|
|
| ScopedComPtr<IAudioClient> CoreAudioUtil::CreateDefaultClient(
|
| EDataFlow data_flow, ERole role) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedComPtr<IMMDevice> default_device(CreateDefaultDevice(data_flow, role));
|
| return (default_device ? CreateClient(default_device) :
|
| ScopedComPtr<IAudioClient>());
|
| @@ -346,7 +346,7 @@ ScopedComPtr<IAudioClient> CoreAudioUtil::CreateDefaultClient(
|
|
|
| HRESULT CoreAudioUtil::GetSharedModeMixFormat(
|
| IAudioClient* client, WAVEFORMATPCMEX* format) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedCoMem<WAVEFORMATPCMEX> format_pcmex;
|
| HRESULT hr = client->GetMixFormat(
|
| reinterpret_cast<WAVEFORMATEX**>(&format_pcmex));
|
| @@ -371,10 +371,22 @@ HRESULT CoreAudioUtil::GetSharedModeMixFormat(
|
| return hr;
|
| }
|
|
|
| +HRESULT CoreAudioUtil::GetDefaultSharedModeMixFormat(
|
| + EDataFlow data_flow, ERole role, WAVEFORMATPCMEX* format) {
|
| + DCHECK(IsSupported());
|
| + ScopedComPtr<IAudioClient> client(CreateDefaultClient(data_flow, role));
|
| + if (!client) {
|
| + // Map NULL-pointer to new error code which can be different from the
|
| + // actual error code. The exact value is not important here.
|
| + return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
|
| + }
|
| + return CoreAudioUtil::GetSharedModeMixFormat(client, format);
|
| +}
|
| +
|
| bool CoreAudioUtil::IsFormatSupported(IAudioClient* client,
|
| AUDCLNT_SHAREMODE share_mode,
|
| const WAVEFORMATPCMEX* format) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| ScopedCoMem<WAVEFORMATEXTENSIBLE> closest_match;
|
| HRESULT hr = client->IsFormatSupported(
|
| share_mode, reinterpret_cast<const WAVEFORMATEX*>(format),
|
| @@ -398,7 +410,7 @@ bool CoreAudioUtil::IsFormatSupported(IAudioClient* client,
|
| HRESULT CoreAudioUtil::GetDevicePeriod(IAudioClient* client,
|
| AUDCLNT_SHAREMODE share_mode,
|
| REFERENCE_TIME* device_period) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
|
|
| // Get the period of the engine thread.
|
| REFERENCE_TIME default_period = 0;
|
| @@ -417,7 +429,7 @@ HRESULT CoreAudioUtil::GetDevicePeriod(IAudioClient* client,
|
|
|
| HRESULT CoreAudioUtil::GetPreferredAudioParameters(
|
| IAudioClient* client, AudioParameters* params) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
| WAVEFORMATPCMEX format;
|
| HRESULT hr = GetSharedModeMixFormat(client, &format);
|
| if (FAILED(hr))
|
| @@ -468,9 +480,8 @@ HRESULT CoreAudioUtil::GetPreferredAudioParameters(
|
|
|
| HRESULT CoreAudioUtil::GetPreferredAudioParameters(
|
| EDataFlow data_flow, ERole role, AudioParameters* params) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| -
|
| - ScopedComPtr<IAudioClient> client = CreateDefaultClient(data_flow, role);
|
| + DCHECK(IsSupported());
|
| + ScopedComPtr<IAudioClient> client(CreateDefaultClient(data_flow, role));
|
| if (!client) {
|
| // Map NULL-pointer to new error code which can be different from the
|
| // actual error code. The exact value is not important here.
|
| @@ -483,8 +494,7 @@ HRESULT CoreAudioUtil::SharedModeInitialize(IAudioClient* client,
|
| const WAVEFORMATPCMEX* format,
|
| HANDLE event_handle,
|
| size_t* endpoint_buffer_size) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| -
|
| + DCHECK(IsSupported());
|
| DWORD stream_flags = AUDCLNT_STREAMFLAGS_NOPERSIST;
|
|
|
| // Enable event-driven streaming if a valid event handle is provided.
|
| @@ -538,7 +548,7 @@ HRESULT CoreAudioUtil::SharedModeInitialize(IAudioClient* client,
|
|
|
| ScopedComPtr<IAudioRenderClient> CoreAudioUtil::CreateRenderClient(
|
| IAudioClient* client) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
|
|
| // Get access to the IAudioRenderClient interface. This interface
|
| // enables us to write output data to a rendering endpoint buffer.
|
| @@ -549,40 +559,12 @@ ScopedComPtr<IAudioRenderClient> CoreAudioUtil::CreateRenderClient(
|
| DVLOG(1) << "IAudioClient::GetService: " << std::hex << hr;
|
| return ScopedComPtr<IAudioRenderClient>();
|
| }
|
| -
|
| - // TODO(henrika): verify that this scheme is the same for shared mode and
|
| - // exclusive mode streams.
|
| -
|
| - // Avoid start-up glitches by filling up the endpoint buffer with "silence"
|
| - // before starting the stream.
|
| - UINT32 endpoint_buffer_size = 0;
|
| - hr = client->GetBufferSize(&endpoint_buffer_size);
|
| - DVLOG_IF(1, FAILED(hr)) << "IAudioClient::GetBufferSize: " << std::hex << hr;
|
| -
|
| - BYTE* data = NULL;
|
| - hr = audio_render_client->GetBuffer(endpoint_buffer_size, &data);
|
| - DVLOG_IF(1, FAILED(hr)) << "IAudioRenderClient::GetBuffer: "
|
| - << std::hex << hr;
|
| - if (SUCCEEDED(hr)) {
|
| - // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to
|
| - // explicitly write silence data to the rendering buffer.
|
| - hr = audio_render_client->ReleaseBuffer(endpoint_buffer_size,
|
| - AUDCLNT_BUFFERFLAGS_SILENT);
|
| - DVLOG_IF(1, FAILED(hr)) << "IAudioRenderClient::ReleaseBuffer: "
|
| - << std::hex << hr;
|
| - }
|
| -
|
| - // Sanity check: verify that the endpoint buffer is filled with silence.
|
| - UINT32 num_queued_frames = 0;
|
| - client->GetCurrentPadding(&num_queued_frames);
|
| - DCHECK(num_queued_frames == endpoint_buffer_size);
|
| -
|
| return audio_render_client;
|
| }
|
|
|
| ScopedComPtr<IAudioCaptureClient> CoreAudioUtil::CreateCaptureClient(
|
| IAudioClient* client) {
|
| - DCHECK(CoreAudioUtil::IsSupported());
|
| + DCHECK(IsSupported());
|
|
|
| // Get access to the IAudioCaptureClient interface. This interface
|
| // enables us to read input data from a capturing endpoint buffer.
|
| @@ -596,4 +578,28 @@ ScopedComPtr<IAudioCaptureClient> CoreAudioUtil::CreateCaptureClient(
|
| return audio_capture_client;
|
| }
|
|
|
| +bool CoreAudioUtil::FillRenderEndpointBufferWithSilence(
|
| + IAudioClient* client, IAudioRenderClient* render_client) {
|
| + DCHECK(IsSupported());
|
| +
|
| + UINT32 endpoint_buffer_size = 0;
|
| + if (FAILED(client->GetBufferSize(&endpoint_buffer_size)))
|
| + return false;
|
| +
|
| + UINT32 num_queued_frames = 0;
|
| + if (FAILED(client->GetCurrentPadding(&num_queued_frames)))
|
| + return false;
|
| +
|
| + BYTE* data = NULL;
|
| + int num_frames_to_fill = endpoint_buffer_size - num_queued_frames;
|
| + if (FAILED(render_client->GetBuffer(num_frames_to_fill, &data)))
|
| + return false;
|
| +
|
| + // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to
|
| + // explicitly write silence data to the rendering buffer.
|
| + DVLOG(2) << "filling up " << num_frames_to_fill << " frames with silence";
|
| + return SUCCEEDED(render_client->ReleaseBuffer(num_frames_to_fill,
|
| + AUDCLNT_BUFFERFLAGS_SILENT));
|
| +}
|
| +
|
| } // namespace media
|
|
|