| 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 | |
| 11 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 12 #include "base/logging.h" | 10 #include "base/logging.h" |
| 13 #include "base/macros.h" | 11 #include "base/macros.h" |
| 14 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 17 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 18 #include "base/win/scoped_propvariant.h" | 16 #include "base/win/scoped_propvariant.h" |
| 19 #include "media/audio/audio_device_description.h" | 17 #include "media/audio/audio_device_description.h" |
| 20 #include "media/audio/win/audio_manager_win.h" | 18 #include "media/audio/win/audio_manager_win.h" |
| 21 #include "media/audio/win/avrt_wrapper_win.h" | 19 #include "media/audio/win/avrt_wrapper_win.h" |
| 22 #include "media/audio/win/core_audio_util_win.h" | 20 #include "media/audio/win/core_audio_util_win.h" |
| 23 #include "media/base/audio_sample_types.h" | |
| 24 #include "media/base/limits.h" | 21 #include "media/base/limits.h" |
| 25 #include "media/base/media_switches.h" | 22 #include "media/base/media_switches.h" |
| 26 | 23 |
| 27 using base::win::ScopedComPtr; | 24 using base::win::ScopedComPtr; |
| 28 using base::win::ScopedCOMInitializer; | 25 using base::win::ScopedCOMInitializer; |
| 29 using base::win::ScopedCoMem; | 26 using base::win::ScopedCoMem; |
| 30 | 27 |
| 31 namespace media { | 28 namespace media { |
| 32 | 29 |
| 33 // The number of bits in a float sample. | |
| 34 static const int kBitsPerFloatSample = sizeof(float) * CHAR_BIT; | |
| 35 | |
| 36 // static | 30 // static |
| 37 AUDCLNT_SHAREMODE WASAPIAudioOutputStream::GetShareMode() { | 31 AUDCLNT_SHAREMODE WASAPIAudioOutputStream::GetShareMode() { |
| 38 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 32 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 39 if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) | 33 if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) |
| 40 return AUDCLNT_SHAREMODE_EXCLUSIVE; | 34 return AUDCLNT_SHAREMODE_EXCLUSIVE; |
| 41 return AUDCLNT_SHAREMODE_SHARED; | 35 return AUDCLNT_SHAREMODE_SHARED; |
| 42 } | 36 } |
| 43 | 37 |
| 44 // static | 38 // static |
| 45 int WASAPIAudioOutputStream::HardwareSampleRate(const std::string& device_id) { | 39 int WASAPIAudioOutputStream::HardwareSampleRate(const std::string& device_id) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 71 opened_(false), | 65 opened_(false), |
| 72 volume_(1.0), | 66 volume_(1.0), |
| 73 packet_size_frames_(0), | 67 packet_size_frames_(0), |
| 74 packet_size_bytes_(0), | 68 packet_size_bytes_(0), |
| 75 endpoint_buffer_size_frames_(0), | 69 endpoint_buffer_size_frames_(0), |
| 76 device_id_(device_id), | 70 device_id_(device_id), |
| 77 device_role_(device_role), | 71 device_role_(device_role), |
| 78 share_mode_(GetShareMode()), | 72 share_mode_(GetShareMode()), |
| 79 num_written_frames_(0), | 73 num_written_frames_(0), |
| 80 source_(NULL), | 74 source_(NULL), |
| 81 audio_bus_(AudioBus::Create(AudioParameters( | 75 audio_bus_(AudioBus::Create(params)) { |
| 82 params.format(), | |
| 83 params.channel_layout(), | |
| 84 params.sample_rate(), | |
| 85 // Ignore the given bits per sample because we're outputting | |
| 86 // floats. | |
| 87 kBitsPerFloatSample, | |
| 88 params.frames_per_buffer()))) { | |
| 89 DCHECK(manager_); | 76 DCHECK(manager_); |
| 90 | 77 |
| 91 // The empty string is used to indicate a default device and the | 78 // The empty string is used to indicate a default device and the |
| 92 // |device_role_| member controls whether that's the default or default | 79 // |device_role_| member controls whether that's the default or default |
| 93 // communications device. | 80 // communications device. |
| 94 DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); | 81 DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); |
| 95 DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); | 82 DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); |
| 96 | 83 |
| 97 DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; | 84 DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; |
| 98 DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) | 85 DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) |
| 99 << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; | 86 << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; |
| 100 | 87 |
| 101 // Load the Avrt DLL if not already loaded. Required to support MMCSS. | 88 // Load the Avrt DLL if not already loaded. Required to support MMCSS. |
| 102 bool avrt_init = avrt::Initialize(); | 89 bool avrt_init = avrt::Initialize(); |
| 103 DCHECK(avrt_init) << "Failed to load the avrt.dll"; | 90 DCHECK(avrt_init) << "Failed to load the avrt.dll"; |
| 104 | 91 |
| 105 // Set up the desired render format specified by the client. We use the | 92 // Set up the desired render format specified by the client. We use the |
| 106 // WAVE_FORMAT_EXTENSIBLE structure to ensure that multiple channel ordering | 93 // WAVE_FORMAT_EXTENSIBLE structure to ensure that multiple channel ordering |
| 107 // and high precision data can be supported. | 94 // and high precision data can be supported. |
| 108 | 95 |
| 109 // Begin with the WAVEFORMATEX structure that specifies the basic format. | 96 // Begin with the WAVEFORMATEX structure that specifies the basic format. |
| 110 WAVEFORMATEX* format = &format_.Format; | 97 WAVEFORMATEX* format = &format_.Format; |
| 111 format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; | 98 format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; |
| 112 format->nChannels = params.channels(); | 99 format->nChannels = params.channels(); |
| 113 format->nSamplesPerSec = params.sample_rate(); | 100 format->nSamplesPerSec = params.sample_rate(); |
| 114 format->wBitsPerSample = kBitsPerFloatSample; | 101 format->wBitsPerSample = params.bits_per_sample(); |
| 115 format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels; | 102 format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels; |
| 116 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign; | 103 format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign; |
| 117 format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); | 104 format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); |
| 118 | 105 |
| 119 // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. | 106 // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE. |
| 120 format_.Samples.wValidBitsPerSample = kBitsPerFloatSample; | 107 format_.Samples.wValidBitsPerSample = params.bits_per_sample(); |
| 121 format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); | 108 format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); |
| 122 format_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; | 109 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; |
| 123 | 110 |
| 124 // Store size (in different units) of audio packets which we expect to | 111 // Store size (in different units) of audio packets which we expect to |
| 125 // get from the audio endpoint device in each render event. | 112 // get from the audio endpoint device in each render event. |
| 126 packet_size_frames_ = params.frames_per_buffer(); | 113 packet_size_frames_ = params.frames_per_buffer(); |
| 127 packet_size_bytes_ = params.GetBytesPerBuffer(); | 114 packet_size_bytes_ = params.GetBytesPerBuffer(); |
| 128 DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; | 115 DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; |
| 129 DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; | 116 DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; |
| 130 DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; | 117 DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; |
| 131 DVLOG(1) << "Number of milliseconds per packet: " | 118 DVLOG(1) << "Number of milliseconds per packet: " |
| 132 << params.GetBufferDuration().InMillisecondsF(); | 119 << params.GetBufferDuration().InMillisecondsF(); |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 } | 537 } |
| 551 | 538 |
| 552 // Read a data packet from the registered client source and | 539 // Read a data packet from the registered client source and |
| 553 // deliver a delay estimate in the same callback to the client. | 540 // deliver a delay estimate in the same callback to the client. |
| 554 | 541 |
| 555 int frames_filled = | 542 int frames_filled = |
| 556 source_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); | 543 source_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); |
| 557 uint32_t num_filled_bytes = frames_filled * format_.Format.nBlockAlign; | 544 uint32_t num_filled_bytes = frames_filled * format_.Format.nBlockAlign; |
| 558 DCHECK_LE(num_filled_bytes, packet_size_bytes_); | 545 DCHECK_LE(num_filled_bytes, packet_size_bytes_); |
| 559 | 546 |
| 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; |
| 560 audio_bus_->Scale(volume_); | 551 audio_bus_->Scale(volume_); |
| 561 audio_bus_->ToInterleaved<Float32SampleTypeTraits>( | 552 audio_bus_->ToInterleaved( |
| 562 frames_filled, reinterpret_cast<float*>(audio_data)); | 553 frames_filled, bytes_per_sample, audio_data); |
| 563 | 554 |
| 564 // Release the buffer space acquired in the GetBuffer() call. | 555 // Release the buffer space acquired in the GetBuffer() call. |
| 565 // Render silence if we were not able to fill up the buffer totally. | 556 // Render silence if we were not able to fill up the buffer totally. |
| 566 DWORD flags = (num_filled_bytes < packet_size_bytes_) ? | 557 DWORD flags = (num_filled_bytes < packet_size_bytes_) ? |
| 567 AUDCLNT_BUFFERFLAGS_SILENT : 0; | 558 AUDCLNT_BUFFERFLAGS_SILENT : 0; |
| 568 audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); | 559 audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); |
| 569 | 560 |
| 570 num_written_frames_ += packet_size_frames_; | 561 num_written_frames_ += packet_size_frames_; |
| 571 } | 562 } |
| 572 | 563 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 | 657 |
| 667 // Ensure that we don't quit the main thread loop immediately next | 658 // Ensure that we don't quit the main thread loop immediately next |
| 668 // time Start() is called. | 659 // time Start() is called. |
| 669 ResetEvent(stop_render_event_.Get()); | 660 ResetEvent(stop_render_event_.Get()); |
| 670 } | 661 } |
| 671 | 662 |
| 672 source_ = NULL; | 663 source_ = NULL; |
| 673 } | 664 } |
| 674 | 665 |
| 675 } // namespace media | 666 } // namespace media |
| OLD | NEW |