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/virtual_audio_input_stream.h" | 5 #include "media/audio/virtual_audio_input_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 base::MessageLoopProxy* message_loop) { | 52 base::MessageLoopProxy* message_loop) { |
53 return new VirtualAudioInputStream(manager, params, message_loop); | 53 return new VirtualAudioInputStream(manager, params, message_loop); |
54 } | 54 } |
55 | 55 |
56 VirtualAudioInputStream::VirtualAudioInputStream( | 56 VirtualAudioInputStream::VirtualAudioInputStream( |
57 AudioManagerBase* manager, const AudioParameters& params, | 57 AudioManagerBase* manager, const AudioParameters& params, |
58 base::MessageLoopProxy* message_loop) | 58 base::MessageLoopProxy* message_loop) |
59 : audio_manager_(manager), | 59 : audio_manager_(manager), |
60 message_loop_(message_loop), | 60 message_loop_(message_loop), |
61 callback_(NULL), | 61 callback_(NULL), |
62 buffer_duration_ms_(base::TimeDelta::FromMilliseconds( | 62 buffer_duration_(base::TimeDelta::FromMicroseconds( |
63 params.frames_per_buffer() * base::Time::kMillisecondsPerSecond / | 63 params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond / |
64 static_cast<float>(params.sample_rate()))), | 64 static_cast<float>(params.sample_rate()))), |
65 buffer_(new uint8[params.GetBytesPerBuffer()]), | 65 buffer_(new uint8[params.GetBytesPerBuffer()]), |
66 params_(params), | 66 params_(params), |
67 audio_bus_(AudioBus::Create(params_)), | 67 audio_bus_(AudioBus::Create(params_)), |
68 mixer_(params_, params_, false), | 68 mixer_(params_, params_, false), |
69 num_attached_outputs_streams_(0) { | 69 num_attached_outputs_streams_(0) { |
70 } | 70 } |
71 | 71 |
72 VirtualAudioInputStream::~VirtualAudioInputStream() { | 72 VirtualAudioInputStream::~VirtualAudioInputStream() { |
73 for (AudioConvertersMap::iterator it = converters_.begin(); | 73 for (AudioConvertersMap::iterator it = converters_.begin(); |
74 it != converters_.end(); ++it) | 74 it != converters_.end(); ++it) |
75 delete it->second; | 75 delete it->second; |
76 | 76 |
77 DCHECK_EQ(0, num_attached_outputs_streams_); | 77 DCHECK_EQ(0, num_attached_outputs_streams_); |
78 } | 78 } |
79 | 79 |
80 bool VirtualAudioInputStream::Open() { | 80 bool VirtualAudioInputStream::Open() { |
81 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); | 81 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); |
82 return true; | 82 return true; |
83 } | 83 } |
84 | 84 |
85 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { | 85 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { |
86 DCHECK(message_loop_->BelongsToCurrentThread()); | 86 DCHECK(message_loop_->BelongsToCurrentThread()); |
87 callback_ = callback; | 87 callback_ = callback; |
| 88 next_read_time_ = base::Time::Now(); |
88 on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio, | 89 on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio, |
89 base::Unretained(this))); | 90 base::Unretained(this))); |
90 audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, | 91 audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, |
91 on_more_data_cb_.callback()); | 92 on_more_data_cb_.callback()); |
92 } | 93 } |
93 | 94 |
94 void VirtualAudioInputStream::Stop() { | 95 void VirtualAudioInputStream::Stop() { |
95 DCHECK(message_loop_->BelongsToCurrentThread()); | 96 DCHECK(message_loop_->BelongsToCurrentThread()); |
96 on_more_data_cb_.Cancel(); | 97 on_more_data_cb_.Cancel(); |
97 } | 98 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 audio_bus_->ToInterleaved(params_.frames_per_buffer(), | 133 audio_bus_->ToInterleaved(params_.frames_per_buffer(), |
133 params_.bits_per_sample() / 8, | 134 params_.bits_per_sample() / 8, |
134 buffer_.get()); | 135 buffer_.get()); |
135 | 136 |
136 callback_->OnData(this, | 137 callback_->OnData(this, |
137 buffer_.get(), | 138 buffer_.get(), |
138 params_.GetBytesPerBuffer(), | 139 params_.GetBytesPerBuffer(), |
139 params_.GetBytesPerBuffer(), | 140 params_.GetBytesPerBuffer(), |
140 1.0); | 141 1.0); |
141 | 142 |
| 143 // Need to account for time spent here due to renderer side mixing as well as |
| 144 // the imprecision of PostDelayedTask. |
| 145 next_read_time_ += buffer_duration_; |
| 146 base::Time now = base::Time::Now(); |
| 147 base::TimeDelta delay = next_read_time_ - now; |
| 148 if (delay < base::TimeDelta()) { |
| 149 // Reset the next read time if we end up getting too far behind. We'll just |
| 150 // slow down playback to avoid using up all the CPU. |
| 151 delay = buffer_duration_; |
| 152 next_read_time_ = now; |
| 153 } |
| 154 |
142 message_loop_->PostDelayedTask(FROM_HERE, | 155 message_loop_->PostDelayedTask(FROM_HERE, |
143 on_more_data_cb_.callback(), | 156 on_more_data_cb_.callback(), |
144 buffer_duration_ms_); | 157 delay); |
145 } | 158 } |
146 | 159 |
147 void VirtualAudioInputStream::Close() { | 160 void VirtualAudioInputStream::Close() { |
148 DCHECK(message_loop_->BelongsToCurrentThread()); | 161 DCHECK(message_loop_->BelongsToCurrentThread()); |
149 if (callback_) { | 162 if (callback_) { |
150 DCHECK(on_more_data_cb_.IsCancelled()); | 163 DCHECK(on_more_data_cb_.IsCancelled()); |
151 callback_->OnClose(this); | 164 callback_->OnClose(this); |
152 callback_ = NULL; | 165 callback_ = NULL; |
153 } | 166 } |
154 audio_manager_->ReleaseInputStream(this); | 167 audio_manager_->ReleaseInputStream(this); |
155 } | 168 } |
156 | 169 |
157 double VirtualAudioInputStream::GetMaxVolume() { | 170 double VirtualAudioInputStream::GetMaxVolume() { |
158 return 1.0; | 171 return 1.0; |
159 } | 172 } |
160 | 173 |
161 void VirtualAudioInputStream::SetVolume(double volume) {} | 174 void VirtualAudioInputStream::SetVolume(double volume) {} |
162 | 175 |
163 double VirtualAudioInputStream::GetVolume() { | 176 double VirtualAudioInputStream::GetVolume() { |
164 return 1.0; | 177 return 1.0; |
165 } | 178 } |
166 | 179 |
167 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} | 180 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} |
168 | 181 |
169 bool VirtualAudioInputStream::GetAutomaticGainControl() { | 182 bool VirtualAudioInputStream::GetAutomaticGainControl() { |
170 return false; | 183 return false; |
171 } | 184 } |
172 | 185 |
173 } // namespace media | 186 } // namespace media |
OLD | NEW |