Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/renderer/media/audio_renderer_impl.h" | 5 #include "content/renderer/media/audio_renderer_impl.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 if (sample_rate <= 48000) | 31 if (sample_rate <= 48000) |
| 32 return kNominalBufferSize; | 32 return kNominalBufferSize; |
| 33 else if (sample_rate <= 96000) | 33 else if (sample_rate <= 96000) |
| 34 return kNominalBufferSize * 2; | 34 return kNominalBufferSize * 2; |
| 35 return kNominalBufferSize * 4; | 35 return kNominalBufferSize * 4; |
| 36 } | 36 } |
| 37 | 37 |
| 38 AudioRendererImpl::AudioRendererImpl() | 38 AudioRendererImpl::AudioRendererImpl() |
| 39 : AudioRendererBase(), | 39 : AudioRendererBase(), |
| 40 bytes_per_second_(0), | 40 bytes_per_second_(0), |
| 41 stopped_(false) { | 41 stopped_(false), |
| 42 is_initialized_(false) { | |
| 42 // We create the AudioDevice here because it must be created in the | 43 // We create the AudioDevice here because it must be created in the |
| 43 // main thread. But we don't yet know the audio format (sample-rate, etc.) | 44 // main thread. But we don't yet know the audio format (sample-rate, etc.) |
| 44 // at this point. Later, when OnInitialize() is called, we have | 45 // at this point. Later, when OnInitialize() is called, we have |
| 45 // the audio format information and call the AudioDevice::Initialize() | 46 // the audio format information and call the AudioDevice::Initialize() |
| 46 // method to fully initialize it. | 47 // method to fully initialize it. |
| 47 audio_device_ = new AudioDevice(); | 48 audio_device_ = new AudioDevice(); |
| 49 | |
| 50 // Assign the AudioDevice as the default audio sink. | |
| 51 sink_ = audio_device_.get(); | |
| 48 } | 52 } |
| 49 | 53 |
| 50 AudioRendererImpl::~AudioRendererImpl() { | 54 AudioRendererImpl::~AudioRendererImpl() { |
| 51 } | 55 } |
| 52 | 56 |
| 53 base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { | 57 base::TimeDelta AudioRendererImpl::ConvertToDuration(int bytes) { |
| 54 if (bytes_per_second_) { | 58 if (bytes_per_second_) { |
| 55 return base::TimeDelta::FromMicroseconds( | 59 return base::TimeDelta::FromMicroseconds( |
| 56 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); | 60 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); |
| 57 } | 61 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 83 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627 | 87 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627 |
| 84 // for more details. | 88 // for more details. |
| 85 audio_parameters_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, | 89 audio_parameters_ = AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, |
| 86 channel_layout, | 90 channel_layout, |
| 87 sample_rate, | 91 sample_rate, |
| 88 bits_per_channel, | 92 bits_per_channel, |
| 89 0); | 93 0); |
| 90 | 94 |
| 91 bytes_per_second_ = audio_parameters_.GetBytesPerSecond(); | 95 bytes_per_second_ = audio_parameters_.GetBytesPerSecond(); |
| 92 | 96 |
| 93 DCHECK(audio_device_.get()); | 97 base::AutoLock auto_lock(sink_lock_); |
| 94 | 98 |
| 95 if (!audio_device_->IsInitialized()) { | 99 DCHECK(sink_); |
| 96 audio_device_->Initialize( | 100 |
| 101 if (!is_initialized_) { | |
| 102 sink_->Initialize( | |
| 97 GetBufferSizeForSampleRate(sample_rate), | 103 GetBufferSizeForSampleRate(sample_rate), |
| 98 audio_parameters_.channels, | 104 audio_parameters_.channels, |
| 99 audio_parameters_.sample_rate, | 105 audio_parameters_.sample_rate, |
| 100 audio_parameters_.format, | 106 audio_parameters_.format, |
| 101 this); | 107 this); |
| 102 | 108 |
| 103 audio_device_->Start(); | 109 sink_->Start(); |
| 110 is_initialized_ = true; | |
| 104 } | 111 } |
| 105 | 112 |
| 106 return true; | 113 return true; |
| 107 } | 114 } |
| 108 | 115 |
| 109 void AudioRendererImpl::OnStop() { | 116 void AudioRendererImpl::OnStop() { |
| 110 if (stopped_) | 117 if (stopped_) |
| 111 return; | 118 return; |
| 112 | 119 |
| 113 DCHECK(audio_device_.get()); | 120 base::AutoLock auto_lock(sink_lock_); |
| 114 audio_device_->Stop(); | 121 DCHECK(sink_); |
| 122 sink_->Stop(); | |
| 115 | 123 |
| 116 stopped_ = true; | 124 stopped_ = true; |
| 117 } | 125 } |
| 118 | 126 |
| 119 void AudioRendererImpl::SetPlaybackRate(float rate) { | 127 void AudioRendererImpl::SetPlaybackRate(float rate) { |
| 120 DCHECK_LE(0.0f, rate); | 128 DCHECK_LE(0.0f, rate); |
| 121 | 129 |
| 122 // Handle the case where we stopped due to IO message loop dying. | 130 // Handle the case where we stopped due to IO message loop dying. |
| 123 if (stopped_) { | 131 if (stopped_) { |
| 124 AudioRendererBase::SetPlaybackRate(rate); | 132 AudioRendererBase::SetPlaybackRate(rate); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 if (GetPlaybackRate() != 0.0f) { | 170 if (GetPlaybackRate() != 0.0f) { |
| 163 DoPlay(); | 171 DoPlay(); |
| 164 } else { | 172 } else { |
| 165 DoPause(); | 173 DoPause(); |
| 166 } | 174 } |
| 167 } | 175 } |
| 168 | 176 |
| 169 void AudioRendererImpl::SetVolume(float volume) { | 177 void AudioRendererImpl::SetVolume(float volume) { |
| 170 if (stopped_) | 178 if (stopped_) |
| 171 return; | 179 return; |
| 172 DCHECK(audio_device_.get()); | 180 base::AutoLock auto_lock(sink_lock_); |
| 173 audio_device_->SetVolume(volume); | 181 DCHECK(sink_); |
| 182 sink_->SetVolume(volume); | |
| 174 } | 183 } |
| 175 | 184 |
| 176 void AudioRendererImpl::DoPlay() { | 185 void AudioRendererImpl::DoPlay() { |
| 177 earliest_end_time_ = base::Time::Now(); | 186 earliest_end_time_ = base::Time::Now(); |
| 178 DCHECK(audio_device_.get()); | 187 base::AutoLock auto_lock(sink_lock_); |
| 179 audio_device_->Play(); | 188 DCHECK(sink_); |
| 189 sink_->Play(); | |
| 180 } | 190 } |
| 181 | 191 |
| 182 void AudioRendererImpl::DoPause() { | 192 void AudioRendererImpl::DoPause() { |
| 183 DCHECK(audio_device_.get()); | 193 base::AutoLock auto_lock(sink_lock_); |
| 184 audio_device_->Pause(false); | 194 DCHECK(sink_); |
| 195 sink_->Pause(false); | |
| 185 } | 196 } |
| 186 | 197 |
| 187 void AudioRendererImpl::DoSeek() { | 198 void AudioRendererImpl::DoSeek() { |
| 188 earliest_end_time_ = base::Time::Now(); | 199 earliest_end_time_ = base::Time::Now(); |
| 189 | 200 |
| 190 // Pause and flush the stream when we seek to a new location. | 201 // Pause and flush the stream when we seek to a new location. |
| 191 DCHECK(audio_device_.get()); | 202 base::AutoLock auto_lock(sink_lock_); |
| 192 audio_device_->Pause(true); | 203 DCHECK(sink_); |
| 204 sink_->Pause(true); | |
| 193 } | 205 } |
| 194 | 206 |
| 195 void AudioRendererImpl::Render(const std::vector<float*>& audio_data, | 207 void AudioRendererImpl::Render(const std::vector<float*>& audio_data, |
| 196 size_t number_of_frames, | 208 size_t number_of_frames, |
| 197 size_t audio_delay_milliseconds) { | 209 size_t audio_delay_milliseconds) { |
| 198 if (stopped_ || GetPlaybackRate() == 0.0f) { | 210 if (stopped_ || GetPlaybackRate() == 0.0f) { |
| 199 // Output silence if stopped. | 211 // Output silence if stopped. |
| 200 for (size_t i = 0; i < audio_data.size(); ++i) | 212 for (size_t i = 0; i < audio_data.size(); ++i) |
| 201 memset(audio_data[i], 0, sizeof(float) * number_of_frames); | 213 memset(audio_data[i], 0, sizeof(float) * number_of_frames); |
| 202 return; | 214 return; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 bytes_per_frame / channels, | 250 bytes_per_frame / channels, |
| 239 filled_frames); | 251 filled_frames); |
| 240 | 252 |
| 241 // If FillBuffer() didn't give us enough data then zero out the remainder. | 253 // If FillBuffer() didn't give us enough data then zero out the remainder. |
| 242 if (filled_frames < number_of_frames) { | 254 if (filled_frames < number_of_frames) { |
| 243 int frames_to_zero = number_of_frames - filled_frames; | 255 int frames_to_zero = number_of_frames - filled_frames; |
| 244 memset(audio_data[channel_index], 0, sizeof(float) * frames_to_zero); | 256 memset(audio_data[channel_index], 0, sizeof(float) * frames_to_zero); |
| 245 } | 257 } |
| 246 } | 258 } |
| 247 } | 259 } |
| 260 | |
| 261 void AudioRendererImpl::SetAudioRendererSink(media::AudioRendererSink* sink) { | |
| 262 // NULL should be passed in to use the default AudioDevice sink. | |
| 263 DCHECK_NE(sink, audio_device_.get()); | |
| 264 | |
| 265 // Synchronize with other uses of sink_ since we're messing with it here. | |
| 266 base::AutoLock auto_lock(sink_lock_); | |
| 267 | |
| 268 if (sink && sink != sink_) { | |
| 269 // We're switching rendering to a different sink than the AudioDevice. | |
| 270 | |
| 271 // Since we're no longer rendering to the AudioDevice, we don't want | |
| 272 // it to make callbacks to us any more. | |
|
tommi (sloooow) - chröme
2011/12/19 15:26:24
nit: anymore
Chris Rogers
2011/12/19 21:40:35
Done.
| |
| 273 if (sink_ == audio_device_.get()) | |
| 274 audio_device_->Pause(true); | |
| 275 | |
| 276 sink_ = sink; | |
| 277 if (is_initialized_) { | |
| 278 // The sink needs to be notified of the audio format, if available. | |
| 279 // If the format is not yet available, it will later be called | |
| 280 // in OnInitialize(). | |
| 281 sink_->Initialize( | |
| 282 GetBufferSizeForSampleRate(audio_parameters_.sample_rate), | |
| 283 audio_parameters_.channels, | |
| 284 audio_parameters_.sample_rate, | |
| 285 audio_parameters_.format, | |
| 286 this); | |
| 287 } | |
| 288 } else if (!sink && sink_ != audio_device_.get()) { | |
| 289 // Use default sink. | |
| 290 sink_ = audio_device_.get(); | |
| 291 | |
| 292 // !!!!! should only call Play() if we're in the playing state. | |
|
tommi (sloooow) - chröme
2011/12/19 15:26:24
will you fix this or is it a todo?
do we need to c
Chris Rogers
2011/12/19 21:40:35
Actually, for now I think it's better to do nothin
tommi (sloooow) - chröme
2011/12/20 15:05:46
sounds good.
| |
| 293 audio_device_->Play(); | |
| 294 } | |
| 295 } | |
| OLD | NEW |