Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/audio/win/audio_low_latency_output_win.h" | 5 #include "media/audio/win/audio_low_latency_output_win.h" |
| 6 | 6 |
| 7 #include <Functiondiscoverykeys_devpkey.h> | 7 #include <Functiondiscoverykeys_devpkey.h> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "base/win/scoped_propvariant.h" | 16 #include "base/win/scoped_propvariant.h" |
| 17 #include "media/audio/audio_device_description.h" | 17 #include "media/audio/audio_device_description.h" |
| 18 #include "media/audio/win/audio_manager_win.h" | 18 #include "media/audio/win/audio_manager_win.h" |
| 19 #include "media/audio/win/avrt_wrapper_win.h" | 19 #include "media/audio/win/avrt_wrapper_win.h" |
| 20 #include "media/audio/win/core_audio_util_win.h" | 20 #include "media/audio/win/core_audio_util_win.h" |
| 21 #include "media/base/audio_sample_types.h" | |
| 21 #include "media/base/limits.h" | 22 #include "media/base/limits.h" |
| 22 #include "media/base/media_switches.h" | 23 #include "media/base/media_switches.h" |
| 23 | 24 |
| 24 using base::win::ScopedComPtr; | 25 using base::win::ScopedComPtr; |
| 25 using base::win::ScopedCOMInitializer; | 26 using base::win::ScopedCOMInitializer; |
| 26 using base::win::ScopedCoMem; | 27 using base::win::ScopedCoMem; |
| 27 | 28 |
| 28 namespace media { | 29 namespace media { |
| 29 | 30 |
| 30 // static | 31 // static |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 opened_(false), | 66 opened_(false), |
| 66 volume_(1.0), | 67 volume_(1.0), |
| 67 packet_size_frames_(0), | 68 packet_size_frames_(0), |
| 68 packet_size_bytes_(0), | 69 packet_size_bytes_(0), |
| 69 endpoint_buffer_size_frames_(0), | 70 endpoint_buffer_size_frames_(0), |
| 70 device_id_(device_id), | 71 device_id_(device_id), |
| 71 device_role_(device_role), | 72 device_role_(device_role), |
| 72 share_mode_(GetShareMode()), | 73 share_mode_(GetShareMode()), |
| 73 num_written_frames_(0), | 74 num_written_frames_(0), |
| 74 source_(NULL), | 75 source_(NULL), |
| 75 audio_bus_(AudioBus::Create(params)) { | 76 audio_bus_(AudioBus::Create(AudioParameters( |
| 77 params.format(), | |
| 78 params.channel_layout(), | |
| 79 params.sample_rate(), | |
| 80 // Ignore the given bits per sample; we want 32 because | |
| 81 // we're outputting floats. | |
| 82 32, | |
| 83 params.frames_per_buffer()))) { | |
| 76 DCHECK(manager_); | 84 DCHECK(manager_); |
| 77 | 85 |
| 78 // The empty string is used to indicate a default device and the | 86 // The empty string is used to indicate a default device and the |
| 79 // |device_role_| member controls whether that's the default or default | 87 // |device_role_| member controls whether that's the default or default |
| 80 // communications device. | 88 // communications device. |
| 81 DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); | 89 DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); |
| 82 DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); | 90 DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); |
| 83 | 91 |
| 84 DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; | 92 DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; |
| 85 DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) | 93 DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) |
| 86 << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; | 94 << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; |
| 87 | 95 |
| 88 // Load the Avrt DLL if not already loaded. Required to support MMCSS. | 96 // Load the Avrt DLL if not already loaded. Required to support MMCSS. |
| 89 bool avrt_init = avrt::Initialize(); | 97 bool avrt_init = avrt::Initialize(); |
| 90 DCHECK(avrt_init) << "Failed to load the avrt.dll"; | 98 DCHECK(avrt_init) << "Failed to load the avrt.dll"; |
| 91 | 99 |
| 92 // Set up the desired render format specified by the client. We use the | 100 // Set up the desired render format specified by the client. We use the |
| 93 // WAVE_FORMAT_EXTENSIBLE structure to ensure that multiple channel ordering | 101 // WAVE_FORMAT_EXTENSIBLE structure to ensure that multiple channel ordering |
| 94 // and high precision data can be supported. | 102 // and high precision data can be supported. |
| 95 | 103 |
| 96 // Begin with the WAVEFORMATEX structure that specifies the basic format. | 104 // Begin with the WAVEFORMATEX structure that specifies the basic format. |
| 97 WAVEFORMATEX* format = &format_.Format; | 105 WAVEFORMATEX* format = &format_.Format; |
| 98 format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; | 106 format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; |
| 99 format->nChannels = params.channels(); | 107 format->nChannels = params.channels(); |
| 100 format->nSamplesPerSec = params.sample_rate(); | 108 format->nSamplesPerSec = params.sample_rate(); |
| 101 format->wBitsPerSample = params.bits_per_sample(); | 109 // Always want 32 bits because we're using floats. |
| 110 format->wBitsPerSample = 32; | |
|
tommi (sloooow) - chröme
2016/11/02 20:23:04
nit: Add a constant at the top of the file for thi
Raymond Toy
2016/11/02 21:26:14
Done. Please up choose a good name if you don't li
| |
| 102 format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels; | 111 format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels; |
| 103 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign; | 112 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign; |
| 104 format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); | 113 format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); |
| 105 | 114 |
| 106 // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. | 115 // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. |
| 107 format_.Samples.wValidBitsPerSample = params.bits_per_sample(); | 116 format_.Samples.wValidBitsPerSample = 32; |
| 108 format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); | 117 format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); |
| 109 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; | 118 format_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; |
|
tommi (sloooow) - chröme
2016/11/02 20:23:04
that's it? :-|
Raymond Toy
2016/11/02 21:26:14
I think so. :-) I can hear output now that wasn't
| |
| 110 | 119 |
| 111 // Store size (in different units) of audio packets which we expect to | 120 // Store size (in different units) of audio packets which we expect to |
| 112 // get from the audio endpoint device in each render event. | 121 // get from the audio endpoint device in each render event. |
| 113 packet_size_frames_ = params.frames_per_buffer(); | 122 packet_size_frames_ = params.frames_per_buffer(); |
| 114 packet_size_bytes_ = params.GetBytesPerBuffer(); | 123 packet_size_bytes_ = params.GetBytesPerBuffer(); |
| 115 DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; | 124 DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; |
| 116 DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; | 125 DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; |
| 117 DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; | 126 DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; |
| 118 DVLOG(1) << "Number of milliseconds per packet: " | 127 DVLOG(1) << "Number of milliseconds per packet: " |
| 119 << params.GetBufferDuration().InMillisecondsF(); | 128 << params.GetBufferDuration().InMillisecondsF(); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 542 int frames_filled = | 551 int frames_filled = |
| 543 source_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); | 552 source_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); |
| 544 uint32_t num_filled_bytes = frames_filled * format_.Format.nBlockAlign; | 553 uint32_t num_filled_bytes = frames_filled * format_.Format.nBlockAlign; |
| 545 DCHECK_LE(num_filled_bytes, packet_size_bytes_); | 554 DCHECK_LE(num_filled_bytes, packet_size_bytes_); |
| 546 | 555 |
| 547 // Note: If this ever changes to output raw float the data must be | 556 // Note: If this ever changes to output raw float the data must be |
| 548 // clipped and sanitized since it may come from an untrusted | 557 // clipped and sanitized since it may come from an untrusted |
| 549 // source such as NaCl. | 558 // source such as NaCl. |
| 550 const int bytes_per_sample = format_.Format.wBitsPerSample >> 3; | 559 const int bytes_per_sample = format_.Format.wBitsPerSample >> 3; |
| 551 audio_bus_->Scale(volume_); | 560 audio_bus_->Scale(volume_); |
| 552 audio_bus_->ToInterleaved( | 561 audio_bus_->ToInterleaved<Float32SampleTypeTraits>( |
| 553 frames_filled, bytes_per_sample, audio_data); | 562 frames_filled, reinterpret_cast<float*>(audio_data)); |
| 554 | 563 |
| 555 // Release the buffer space acquired in the GetBuffer() call. | 564 // Release the buffer space acquired in the GetBuffer() call. |
| 556 // Render silence if we were not able to fill up the buffer totally. | 565 // Render silence if we were not able to fill up the buffer totally. |
| 557 DWORD flags = (num_filled_bytes < packet_size_bytes_) ? | 566 DWORD flags = (num_filled_bytes < packet_size_bytes_) ? |
| 558 AUDCLNT_BUFFERFLAGS_SILENT : 0; | 567 AUDCLNT_BUFFERFLAGS_SILENT : 0; |
| 559 audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); | 568 audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); |
| 560 | 569 |
| 561 num_written_frames_ += packet_size_frames_; | 570 num_written_frames_ += packet_size_frames_; |
| 562 } | 571 } |
| 563 | 572 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 | 666 |
| 658 // Ensure that we don't quit the main thread loop immediately next | 667 // Ensure that we don't quit the main thread loop immediately next |
| 659 // time Start() is called. | 668 // time Start() is called. |
| 660 ResetEvent(stop_render_event_.Get()); | 669 ResetEvent(stop_render_event_.Get()); |
| 661 } | 670 } |
| 662 | 671 |
| 663 source_ = NULL; | 672 source_ = NULL; |
| 664 } | 673 } |
| 665 | 674 |
| 666 } // namespace media | 675 } // namespace media |
| OLD | NEW |