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 <climits> | |
| 10 | |
| 9 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 12 #include "base/logging.h" |
| 11 #include "base/macros.h" | 13 #include "base/macros.h" |
| 12 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 15 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 16 #include "base/win/scoped_propvariant.h" | 18 #include "base/win/scoped_propvariant.h" |
| 17 #include "media/audio/audio_device_description.h" | 19 #include "media/audio/audio_device_description.h" |
| 18 #include "media/audio/win/audio_manager_win.h" | 20 #include "media/audio/win/audio_manager_win.h" |
| 19 #include "media/audio/win/avrt_wrapper_win.h" | 21 #include "media/audio/win/avrt_wrapper_win.h" |
| 20 #include "media/audio/win/core_audio_util_win.h" | 22 #include "media/audio/win/core_audio_util_win.h" |
| 23 #include "media/base/audio_sample_types.h" | |
| 21 #include "media/base/limits.h" | 24 #include "media/base/limits.h" |
| 22 #include "media/base/media_switches.h" | 25 #include "media/base/media_switches.h" |
| 23 | 26 |
| 24 using base::win::ScopedComPtr; | 27 using base::win::ScopedComPtr; |
| 25 using base::win::ScopedCOMInitializer; | 28 using base::win::ScopedCOMInitializer; |
| 26 using base::win::ScopedCoMem; | 29 using base::win::ScopedCoMem; |
| 27 | 30 |
| 28 namespace media { | 31 namespace media { |
| 29 | 32 |
| 30 // static | 33 // static |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 format_(), | 67 format_(), |
| 65 opened_(false), | 68 opened_(false), |
| 66 volume_(1.0), | 69 volume_(1.0), |
| 67 packet_size_frames_(0), | 70 packet_size_frames_(0), |
| 68 packet_size_bytes_(0), | 71 packet_size_bytes_(0), |
| 69 endpoint_buffer_size_frames_(0), | 72 endpoint_buffer_size_frames_(0), |
| 70 device_id_(device_id), | 73 device_id_(device_id), |
| 71 device_role_(device_role), | 74 device_role_(device_role), |
| 72 share_mode_(GetShareMode()), | 75 share_mode_(GetShareMode()), |
| 73 num_written_frames_(0), | 76 num_written_frames_(0), |
| 74 source_(NULL), | 77 source_(NULL) { |
| 75 audio_bus_(AudioBus::Create(params)) { | |
| 76 DCHECK(manager_); | 78 DCHECK(manager_); |
| 77 | 79 |
| 78 // The empty string is used to indicate a default device and the | 80 // The empty string is used to indicate a default device and the |
| 79 // |device_role_| member controls whether that's the default or default | 81 // |device_role_| member controls whether that's the default or default |
| 80 // communications device. | 82 // communications device. |
| 81 DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); | 83 DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); |
| 82 DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); | 84 DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); |
| 83 | 85 |
| 84 DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; | 86 DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; |
| 85 DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) | 87 DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) |
| 86 << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; | 88 << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; |
| 87 | 89 |
| 88 // Load the Avrt DLL if not already loaded. Required to support MMCSS. | 90 // Load the Avrt DLL if not already loaded. Required to support MMCSS. |
| 89 bool avrt_init = avrt::Initialize(); | 91 bool avrt_init = avrt::Initialize(); |
| 90 DCHECK(avrt_init) << "Failed to load the avrt.dll"; | 92 DCHECK(avrt_init) << "Failed to load the avrt.dll"; |
| 91 | 93 |
| 94 // New set that appropriate for float output. | |
| 95 AudioParameters floatParams = AudioParameters(AudioParameters( | |
|
DaleCurtis
2016/11/07 18:54:00
float_params also you're constructing three audio
Raymond Toy
2016/11/07 19:03:20
Whoa! Don't know how that happened!
| |
| 96 params.format(), params.channel_layout(), params.sample_rate(), | |
| 97 // Ignore the given bits per sample because we're outputting | |
| 98 // floats. | |
| 99 sizeof(float) * CHAR_BIT, params.frames_per_buffer())); | |
| 100 | |
| 101 audio_bus_ = AudioBus::Create(floatParams); | |
| 102 | |
| 92 // Set up the desired render format specified by the client. We use the | 103 // Set up the desired render format specified by the client. We use the |
| 93 // WAVE_FORMAT_EXTENSIBLE structure to ensure that multiple channel ordering | 104 // WAVE_FORMAT_EXTENSIBLE structure to ensure that multiple channel ordering |
| 94 // and high precision data can be supported. | 105 // and high precision data can be supported. |
| 95 | 106 |
| 96 // Begin with the WAVEFORMATEX structure that specifies the basic format. | 107 // Begin with the WAVEFORMATEX structure that specifies the basic format. |
| 97 WAVEFORMATEX* format = &format_.Format; | 108 WAVEFORMATEX* format = &format_.Format; |
| 98 format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; | 109 format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; |
| 99 format->nChannels = params.channels(); | 110 format->nChannels = floatParams.channels(); |
| 100 format->nSamplesPerSec = params.sample_rate(); | 111 format->nSamplesPerSec = floatParams.sample_rate(); |
| 101 format->wBitsPerSample = params.bits_per_sample(); | 112 format->wBitsPerSample = floatParams.bits_per_sample(); |
| 102 format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels; | 113 format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels; |
| 103 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign; | 114 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign; |
| 104 format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); | 115 format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); |
| 105 | 116 |
| 106 // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. | 117 // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. |
| 107 format_.Samples.wValidBitsPerSample = params.bits_per_sample(); | 118 format_.Samples.wValidBitsPerSample = floatParams.bits_per_sample(); |
| 108 format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); | 119 format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); |
| 109 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; | 120 format_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; |
| 110 | 121 |
| 111 // Store size (in different units) of audio packets which we expect to | 122 // Store size (in different units) of audio packets which we expect to |
| 112 // get from the audio endpoint device in each render event. | 123 // get from the audio endpoint device in each render event. |
| 113 packet_size_frames_ = params.frames_per_buffer(); | 124 packet_size_frames_ = floatParams.frames_per_buffer(); |
| 114 packet_size_bytes_ = params.GetBytesPerBuffer(); | 125 packet_size_bytes_ = floatParams.GetBytesPerBuffer(); |
| 115 DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; | 126 DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; |
| 116 DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; | 127 DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; |
| 117 DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; | 128 DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; |
| 118 DVLOG(1) << "Number of milliseconds per packet: " | 129 DVLOG(1) << "Number of milliseconds per packet: " |
| 119 << params.GetBufferDuration().InMillisecondsF(); | 130 << floatParams.GetBufferDuration().InMillisecondsF(); |
| 120 | 131 |
| 121 // All events are auto-reset events and non-signaled initially. | 132 // All events are auto-reset events and non-signaled initially. |
| 122 | 133 |
| 123 // Create the event which the audio engine will signal each time | 134 // Create the event which the audio engine will signal each time |
| 124 // a buffer becomes ready to be processed by the client. | 135 // a buffer becomes ready to be processed by the client. |
| 125 audio_samples_render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL)); | 136 audio_samples_render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL)); |
| 126 DCHECK(audio_samples_render_event_.IsValid()); | 137 DCHECK(audio_samples_render_event_.IsValid()); |
| 127 | 138 |
| 128 // Create the event which will be set in Stop() when capturing shall stop. | 139 // Create the event which will be set in Stop() when capturing shall stop. |
| 129 stop_render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL)); | 140 stop_render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL)); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 } | 548 } |
| 538 | 549 |
| 539 // Read a data packet from the registered client source and | 550 // Read a data packet from the registered client source and |
| 540 // deliver a delay estimate in the same callback to the client. | 551 // deliver a delay estimate in the same callback to the client. |
| 541 | 552 |
| 542 int frames_filled = | 553 int frames_filled = |
| 543 source_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); | 554 source_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); |
| 544 uint32_t num_filled_bytes = frames_filled * format_.Format.nBlockAlign; | 555 uint32_t num_filled_bytes = frames_filled * format_.Format.nBlockAlign; |
| 545 DCHECK_LE(num_filled_bytes, packet_size_bytes_); | 556 DCHECK_LE(num_filled_bytes, packet_size_bytes_); |
| 546 | 557 |
| 547 // Note: If this ever changes to output raw float the data must be | |
| 548 // clipped and sanitized since it may come from an untrusted | |
| 549 // source such as NaCl. | |
| 550 const int bytes_per_sample = format_.Format.wBitsPerSample >> 3; | |
| 551 audio_bus_->Scale(volume_); | 558 audio_bus_->Scale(volume_); |
| 552 audio_bus_->ToInterleaved( | 559 audio_bus_->ToInterleaved<Float32SampleTypeTraits>( |
| 553 frames_filled, bytes_per_sample, audio_data); | 560 frames_filled, reinterpret_cast<float*>(audio_data)); |
| 554 | 561 |
| 555 // Release the buffer space acquired in the GetBuffer() call. | 562 // Release the buffer space acquired in the GetBuffer() call. |
| 556 // Render silence if we were not able to fill up the buffer totally. | 563 // Render silence if we were not able to fill up the buffer totally. |
| 557 DWORD flags = (num_filled_bytes < packet_size_bytes_) ? | 564 DWORD flags = (num_filled_bytes < packet_size_bytes_) ? |
| 558 AUDCLNT_BUFFERFLAGS_SILENT : 0; | 565 AUDCLNT_BUFFERFLAGS_SILENT : 0; |
| 559 audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); | 566 audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); |
| 560 | 567 |
| 561 num_written_frames_ += packet_size_frames_; | 568 num_written_frames_ += packet_size_frames_; |
| 562 } | 569 } |
| 563 | 570 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 | 664 |
| 658 // Ensure that we don't quit the main thread loop immediately next | 665 // Ensure that we don't quit the main thread loop immediately next |
| 659 // time Start() is called. | 666 // time Start() is called. |
| 660 ResetEvent(stop_render_event_.Get()); | 667 ResetEvent(stop_render_event_.Get()); |
| 661 } | 668 } |
| 662 | 669 |
| 663 source_ = NULL; | 670 source_ = NULL; |
| 664 } | 671 } |
| 665 | 672 |
| 666 } // namespace media | 673 } // namespace media |
| OLD | NEW |