OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "media/audio/audio_input_proxy.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/time/time.h" |
| 9 #include "media/audio/audio_manager_base.h" |
| 10 #include "media/base/audio_fifo.h" |
| 11 |
| 12 namespace media { |
| 13 |
| 14 AudioInputProxy::AudioInputProxy(AudioManagerBase* manager, |
| 15 const AudioParameters& input_params, |
| 16 const AudioParameters& output_params, |
| 17 const std::string& device_id) |
| 18 : audio_manager_(manager), |
| 19 stream_(NULL), |
| 20 input_params_(input_params), |
| 21 output_params_(output_params), |
| 22 device_id_(device_id), |
| 23 callback_(NULL), |
| 24 opened_(false), |
| 25 agc_enabled_(false) { |
| 26 DCHECK(input_params.IsValid()); |
| 27 DCHECK(output_params.IsValid()); |
| 28 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); |
| 29 |
| 30 Initialize(input_params); |
| 31 } |
| 32 |
| 33 AudioInputProxy::~AudioInputProxy() { |
| 34 DCHECK(thread_checker_.CalledOnValidThread()); |
| 35 Close(); |
| 36 } |
| 37 |
| 38 void AudioInputProxy::MaybeRestartStream(const AudioParameters& input_params) { |
| 39 DCHECK(thread_checker_.CalledOnValidThread()); |
| 40 // Do nothing if the required input formats are the same. |
| 41 if (input_params == input_params_) |
| 42 return; |
| 43 |
| 44 // Do nothing if |stream_| has already been closed, which means this proxy |
| 45 // is idle. |
| 46 if (!stream_) |
| 47 return; |
| 48 |
| 49 // Cache the |callback_| because Stop() will set it to NULL> |
| 50 AudioInputStream::AudioInputCallback* callback = callback_; |
| 51 |
| 52 // Stop and Close the old stream. |
| 53 Stop(); |
| 54 Close(); |
| 55 DCHECK(!stream_); |
| 56 |
| 57 // Initialize the new stream. |
| 58 Initialize(input_params); |
| 59 |
| 60 // Create and restore the previous state for the new stream. |
| 61 if (opened_) |
| 62 Open(); |
| 63 |
| 64 // AGC needs to be enabled before calling Start(); |
| 65 SetAutomaticGainControl(agc_enabled_); |
| 66 |
| 67 if (callback) |
| 68 Start(callback); |
| 69 DCHECK_EQ(callback, callback_); |
| 70 } |
| 71 |
| 72 void AudioInputProxy::Initialize(const AudioParameters& input_params) { |
| 73 DCHECK(thread_checker_.CalledOnValidThread()); |
| 74 // We do not support resampling and down/up-mixing yet. |
| 75 // TODO(xians): Implement a push model AudioConverter and support resampling. |
| 76 DCHECK_EQ(output_params_.sample_rate(), input_params.sample_rate()); |
| 77 DCHECK_EQ(output_params_.channels(), input_params.channels()); |
| 78 DCHECK(!stream_); |
| 79 |
| 80 input_params_ = input_params; |
| 81 |
| 82 // Create the required audio fifo and audio bus to deal with the |
| 83 // mismatching between the input and output params. |
| 84 // The size of the FIFO is input buffer size + output buffer size. |
| 85 // When the input buffer size and the output buffer size are the same, FIFO |
| 86 // is not needed. |
| 87 if (input_params_.frames_per_buffer() != output_params_.frames_per_buffer()) { |
| 88 int buffer_size = |
| 89 input_params_.frames_per_buffer() + output_params_.frames_per_buffer(); |
| 90 fifo_.reset(new media::AudioFifo(input_params_.channels(), buffer_size)); |
| 91 audio_bus_ = media::AudioBus::Create( |
| 92 output_params_.channels(), output_params_.frames_per_buffer()); |
| 93 } |
| 94 |
| 95 // Create a new audio input stream. |
| 96 stream_ = audio_manager_->MakeLowLatencyInputStream(input_params, device_id_); |
| 97 } |
| 98 |
| 99 bool AudioInputProxy::Open() { |
| 100 DCHECK(thread_checker_.CalledOnValidThread()); |
| 101 DCHECK(!stream_); |
| 102 |
| 103 opened_ = true; |
| 104 return stream_->Open(); |
| 105 } |
| 106 |
| 107 void AudioInputProxy::Start(AudioInputStream::AudioInputCallback* callback) { |
| 108 DCHECK(thread_checker_.CalledOnValidThread()); |
| 109 DCHECK(!callback_ || callback_ == callback); |
| 110 |
| 111 stream_->Start(callback); |
| 112 callback_ = callback; |
| 113 } |
| 114 |
| 115 void AudioInputProxy::Stop() { |
| 116 DCHECK(thread_checker_.CalledOnValidThread()); |
| 117 |
| 118 stream_->Stop(); |
| 119 callback_ = NULL; |
| 120 } |
| 121 |
| 122 void AudioInputProxy::Close() { |
| 123 DCHECK(thread_checker_.CalledOnValidThread()); |
| 124 if (!stream_) |
| 125 return; |
| 126 |
| 127 // AudioManager owns the |stream_|. |
| 128 stream_->Close(); |
| 129 stream_ = NULL; |
| 130 } |
| 131 |
| 132 double AudioInputProxy::GetMaxVolume() { |
| 133 DCHECK(thread_checker_.CalledOnValidThread()); |
| 134 return stream_->GetMaxVolume(); |
| 135 } |
| 136 |
| 137 void AudioInputProxy::SetVolume(double volume) { |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); |
| 139 stream_->SetVolume(volume); |
| 140 } |
| 141 |
| 142 double AudioInputProxy::GetVolume() { |
| 143 DCHECK(thread_checker_.CalledOnValidThread()); |
| 144 return stream_->GetVolume(); |
| 145 } |
| 146 |
| 147 void AudioInputProxy::SetAutomaticGainControl(bool enabled) { |
| 148 DCHECK(thread_checker_.CalledOnValidThread()); |
| 149 stream_->SetAutomaticGainControl(enabled); |
| 150 agc_enabled_ = enabled; |
| 151 } |
| 152 |
| 153 bool AudioInputProxy::GetAutomaticGainControl() { |
| 154 return stream_->GetAutomaticGainControl(); |
| 155 } |
| 156 |
| 157 void AudioInputProxy::OnData(AudioInputStream* stream, |
| 158 const media::AudioBus* src, |
| 159 uint32 hardware_delay_bytes, |
| 160 double volume) { |
| 161 // TODO(xians) We need to handle the frames changing on the fly ?? |
| 162 DCHECK_EQ(src->frames(), input_params_.frames_per_buffer()); |
| 163 if (!fifo_.get()) |
| 164 callback_->OnData(stream, src, hardware_delay_bytes, volume); |
| 165 |
| 166 DCHECK_LE(fifo_->frames() + src->frames(), fifo_->max_frames()); |
| 167 fifo_->Push(src); |
| 168 |
| 169 // Consume the data if the FIFO has enough data. |
| 170 while (fifo_->frames() >= output_params_.frames_per_buffer()) { |
| 171 fifo_->Consume(audio_bus_.get(), 0, audio_bus_->frames()); |
| 172 callback_->OnData(stream, audio_bus_.get(), hardware_delay_bytes, volume); |
| 173 } |
| 174 } |
| 175 |
| 176 void AudioInputProxy::OnError(AudioInputStream* stream) { |
| 177 callback_->OnError(stream); |
| 178 } |
| 179 |
| 180 |
| 181 |
| 182 } // namespace media |
OLD | NEW |