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/filters/audio_renderer_algorithm_base.h" | 5 #include "media/filters/audio_renderer_algorithm_base.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 // Audio at these speeds would sound better under a frequency domain algorithm. | 34 // Audio at these speeds would sound better under a frequency domain algorithm. |
35 static const float kMinPlaybackRate = 0.5f; | 35 static const float kMinPlaybackRate = 0.5f; |
36 static const float kMaxPlaybackRate = 4.0f; | 36 static const float kMaxPlaybackRate = 4.0f; |
37 | 37 |
38 AudioRendererAlgorithmBase::AudioRendererAlgorithmBase() | 38 AudioRendererAlgorithmBase::AudioRendererAlgorithmBase() |
39 : channels_(0), | 39 : channels_(0), |
40 samples_per_second_(0), | 40 samples_per_second_(0), |
41 bytes_per_channel_(0), | 41 bytes_per_channel_(0), |
42 playback_rate_(0.0f), | 42 playback_rate_(0.0f), |
43 audio_buffer_(0, kStartingBufferSizeInBytes), | 43 audio_buffer_(0, kStartingBufferSizeInBytes), |
44 crossfade_size_(0), | 44 bytes_in_crossfade_(0), |
| 45 bytes_per_frame_(0), |
| 46 index_into_window_(0), |
| 47 crossfade_frame_number_(0), |
| 48 muted_(false), |
| 49 needs_more_data_(false), |
45 window_size_(0) { | 50 window_size_(0) { |
46 } | 51 } |
47 | 52 |
48 AudioRendererAlgorithmBase::~AudioRendererAlgorithmBase() {} | 53 AudioRendererAlgorithmBase::~AudioRendererAlgorithmBase() {} |
49 | 54 |
50 bool AudioRendererAlgorithmBase::ValidateConfig( | 55 bool AudioRendererAlgorithmBase::ValidateConfig( |
51 int channels, | 56 int channels, |
52 int samples_per_second, | 57 int samples_per_second, |
53 int bits_per_channel) { | 58 int bits_per_channel) { |
54 bool status = true; | 59 bool status = true; |
(...skipping 22 matching lines...) Expand all Loading... |
77 int samples_per_second, | 82 int samples_per_second, |
78 int bits_per_channel, | 83 int bits_per_channel, |
79 float initial_playback_rate, | 84 float initial_playback_rate, |
80 const base::Closure& callback) { | 85 const base::Closure& callback) { |
81 DCHECK(!callback.is_null()); | 86 DCHECK(!callback.is_null()); |
82 DCHECK(ValidateConfig(channels, samples_per_second, bits_per_channel)); | 87 DCHECK(ValidateConfig(channels, samples_per_second, bits_per_channel)); |
83 | 88 |
84 channels_ = channels; | 89 channels_ = channels; |
85 samples_per_second_ = samples_per_second; | 90 samples_per_second_ = samples_per_second; |
86 bytes_per_channel_ = bits_per_channel / 8; | 91 bytes_per_channel_ = bits_per_channel / 8; |
| 92 bytes_per_frame_ = bytes_per_channel_ * channels_; |
87 request_read_cb_ = callback; | 93 request_read_cb_ = callback; |
88 SetPlaybackRate(initial_playback_rate); | 94 SetPlaybackRate(initial_playback_rate); |
89 | 95 |
90 window_size_ = | 96 window_size_ = |
91 samples_per_second_ * bytes_per_channel_ * channels_ * kWindowDuration; | 97 samples_per_second_ * bytes_per_channel_ * channels_ * kWindowDuration; |
92 AlignToSampleBoundary(&window_size_); | 98 AlignToFrameBoundary(&window_size_); |
93 | 99 |
94 crossfade_size_ = | 100 bytes_in_crossfade_ = |
95 samples_per_second_ * bytes_per_channel_ * channels_ * kCrossfadeDuration; | 101 samples_per_second_ * bytes_per_channel_ * channels_ * kCrossfadeDuration; |
96 AlignToSampleBoundary(&crossfade_size_); | 102 AlignToFrameBoundary(&bytes_in_crossfade_); |
97 } | 103 |
98 | 104 crossfade_buffer_.reset(new uint8[bytes_in_crossfade_]); |
99 uint32 AudioRendererAlgorithmBase::FillBuffer(uint8* dest, uint32 length) { | 105 } |
100 if (IsQueueEmpty() || playback_rate_ == 0.0f) | 106 |
| 107 uint32 AudioRendererAlgorithmBase::FillBuffer( |
| 108 uint8* dest, uint32 requested_frames) { |
| 109 DCHECK_NE(bytes_per_frame_, 0u); |
| 110 |
| 111 if (playback_rate_ == 0.0f) |
101 return 0; | 112 return 0; |
102 | 113 |
103 // Handle the simple case of normal playback. | 114 uint32 total_frames_rendered = 0; |
104 if (playback_rate_ == 1.0f) { | |
105 uint32 bytes_written = | |
106 CopyFromAudioBuffer(dest, std::min(length, bytes_buffered())); | |
107 AdvanceBufferPosition(bytes_written); | |
108 return bytes_written; | |
109 } | |
110 | |
111 // Output muted data when out of acceptable quality range. | |
112 if (playback_rate_ < kMinPlaybackRate || playback_rate_ > kMaxPlaybackRate) | |
113 return MuteBuffer(dest, length); | |
114 | |
115 uint32 input_step = window_size_; | |
116 uint32 output_step = window_size_; | |
117 | |
118 if (playback_rate_ > 1.0f) { | |
119 // Playback is faster than normal; need to squish output! | |
120 output_step = ceil(window_size_ / playback_rate_); | |
121 } else { | |
122 // Playback is slower than normal; need to stretch input! | |
123 input_step = ceil(window_size_ * playback_rate_); | |
124 } | |
125 | |
126 AlignToSampleBoundary(&input_step); | |
127 AlignToSampleBoundary(&output_step); | |
128 DCHECK_LE(crossfade_size_, input_step); | |
129 DCHECK_LE(crossfade_size_, output_step); | |
130 | |
131 uint32 bytes_written = 0; | |
132 uint32 bytes_left_to_output = length; | |
133 uint8* output_ptr = dest; | 115 uint8* output_ptr = dest; |
134 | 116 while (total_frames_rendered < requested_frames) { |
135 // TODO(vrk): The while loop and if test below are lame! We are requiring the | 117 if (index_into_window_ == window_size_) |
136 // client to provide us with enough data to output only complete crossfaded | 118 ResetWindow(); |
137 // windows. Instead, we should output as much data as we can, and add state to | 119 |
138 // keep track of what point in the crossfade we are at. | 120 bool rendered_frame = true; |
139 // This is also the cause of crbug.com/108239. | 121 if (playback_rate_ > 1.0) |
140 while (bytes_left_to_output >= output_step) { | 122 rendered_frame = OutputFasterPlayback(output_ptr); |
141 // If there is not enough data buffered to complete an iteration of the | 123 else if (playback_rate_ < 1.0) |
142 // loop, mute the remaining and break. | 124 rendered_frame = OutputSlowerPlayback(output_ptr); |
143 if (bytes_buffered() < window_size_) { | 125 else |
144 bytes_written += MuteBuffer(output_ptr, bytes_left_to_output); | 126 rendered_frame = OutputNormalPlayback(output_ptr); |
| 127 |
| 128 if (!rendered_frame) { |
| 129 needs_more_data_ = true; |
145 break; | 130 break; |
146 } | 131 } |
147 | 132 |
148 // Copy |output_step| bytes into destination buffer. | 133 output_ptr += bytes_per_frame_; |
149 uint32 copied = CopyFromAudioBuffer(output_ptr, output_step); | 134 total_frames_rendered++; |
150 DCHECK_EQ(copied, output_step); | 135 } |
151 output_ptr += output_step; | 136 return total_frames_rendered; |
152 bytes_written += copied; | 137 } |
153 bytes_left_to_output -= copied; | 138 |
154 | 139 void AudioRendererAlgorithmBase::ResetWindow() { |
155 // Copy the |crossfade_size_| bytes leading up to the next window that will | 140 DCHECK_LE(index_into_window_, window_size_); |
156 // be played into an intermediate buffer. This will be used to crossfade | 141 index_into_window_ = 0; |
157 // from the current window to the next. | 142 crossfade_frame_number_ = 0; |
158 AdvanceBufferPosition(input_step - crossfade_size_); | 143 } |
159 scoped_array<uint8> next_window_intro(new uint8[crossfade_size_]); | 144 |
160 uint32 bytes_copied = | 145 bool AudioRendererAlgorithmBase::OutputFasterPlayback(uint8* dest) { |
161 CopyFromAudioBuffer(next_window_intro.get(), crossfade_size_); | 146 DCHECK_LT(index_into_window_, window_size_); |
162 DCHECK_EQ(bytes_copied, crossfade_size_); | 147 DCHECK_GT(playback_rate_, 1.0); |
163 AdvanceBufferPosition(crossfade_size_); | 148 |
164 | 149 if (audio_buffer_.forward_bytes() < bytes_per_frame_) |
165 // Prepare pointers to end of the current window and the start of the next | 150 return false; |
166 // window. | 151 |
167 uint8* start_of_outro = output_ptr - crossfade_size_; | 152 // The audio data is output in a series of windows. For sped-up playback, |
168 const uint8* start_of_intro = next_window_intro.get(); | 153 // the window is comprised of the following phases: |
169 | 154 // |
170 // Do crossfade! | 155 // a) Output raw data. |
171 Crossfade(crossfade_size_, channels_, bytes_per_channel_, | 156 // b) Save bytes for crossfade in |crossfade_buffer_|. |
172 start_of_intro, start_of_outro); | 157 // c) Drop data. |
173 } | 158 // d) Output crossfaded audio leading up to the next window. |
174 | 159 // |
175 return bytes_written; | 160 // The duration of each phase is computed below based on the |window_size_| |
176 } | 161 // and |playback_rate_|. |
177 | 162 uint32 input_step = window_size_; |
178 uint32 AudioRendererAlgorithmBase::MuteBuffer(uint8* dest, uint32 length) { | 163 uint32 output_step = ceil(window_size_ / playback_rate_); |
| 164 AlignToFrameBoundary(&output_step); |
| 165 DCHECK_GT(input_step, output_step); |
| 166 |
| 167 uint32 bytes_to_crossfade = bytes_in_crossfade_; |
| 168 if (muted_ || bytes_to_crossfade > output_step) |
| 169 bytes_to_crossfade = 0; |
| 170 |
| 171 // This is the index of the end of phase a, beginning of phase b. |
| 172 uint32 outtro_crossfade_begin = output_step - bytes_to_crossfade; |
| 173 |
| 174 // This is the index of the end of phase b, beginning of phase c. |
| 175 uint32 outtro_crossfade_end = output_step; |
| 176 |
| 177 // This is the index of the end of phase c, beginning of phase d. |
| 178 // This phase continues until |index_into_window_| reaches |window_size_|, at |
| 179 // which point the window restarts. |
| 180 uint32 intro_crossfade_begin = input_step - bytes_to_crossfade; |
| 181 |
| 182 // a) Output a raw frame if we haven't reached the crossfade section. |
| 183 if (index_into_window_ < outtro_crossfade_begin) { |
| 184 CopyWithAdvance(dest); |
| 185 index_into_window_ += bytes_per_frame_; |
| 186 return true; |
| 187 } |
| 188 |
| 189 // b) Save outtro crossfade frames into intermediate buffer, but do not output |
| 190 // anything to |dest|. |
| 191 while (index_into_window_ < outtro_crossfade_end) { |
| 192 if (audio_buffer_.forward_bytes() < bytes_per_frame_) |
| 193 return false; |
| 194 |
| 195 // This phase only applies if there are bytes to crossfade. |
| 196 DCHECK_GT(bytes_to_crossfade, 0u); |
| 197 uint8* place_to_copy = crossfade_buffer_.get() + |
| 198 (index_into_window_ - outtro_crossfade_begin); |
| 199 CopyWithAdvance(place_to_copy); |
| 200 index_into_window_ += bytes_per_frame_; |
| 201 } |
| 202 |
| 203 // c) Drop frames until we reach the intro crossfade section. |
| 204 while (index_into_window_ < intro_crossfade_begin) { |
| 205 if (audio_buffer_.forward_bytes() < bytes_per_frame_) |
| 206 return false; |
| 207 |
| 208 DropFrame(); |
| 209 index_into_window_ += bytes_per_frame_; |
| 210 } |
| 211 |
| 212 // Return if we have run out of data after Phase c). |
| 213 if (audio_buffer_.forward_bytes() < bytes_per_frame_) |
| 214 return false; |
| 215 |
| 216 // Phase d) doesn't apply if there are no bytes to crossfade. |
| 217 if (bytes_to_crossfade == 0) { |
| 218 DCHECK_EQ(index_into_window_, window_size_); |
| 219 return false; |
| 220 } |
| 221 |
| 222 // d) Crossfade and output a frame. |
| 223 DCHECK_LT(index_into_window_, window_size_); |
| 224 uint32 offset_into_buffer = index_into_window_ - intro_crossfade_begin; |
| 225 memcpy(dest, crossfade_buffer_.get() + offset_into_buffer, |
| 226 bytes_per_frame_); |
| 227 scoped_array<uint8> intro_frame_ptr(new uint8[bytes_per_frame_]); |
| 228 audio_buffer_.Read(intro_frame_ptr.get(), bytes_per_frame_); |
| 229 OutputCrossfadedFrame(dest, intro_frame_ptr.get()); |
| 230 index_into_window_ += bytes_per_frame_; |
| 231 return true; |
| 232 } |
| 233 |
| 234 bool AudioRendererAlgorithmBase::OutputSlowerPlayback(uint8* dest) { |
| 235 DCHECK_LT(index_into_window_, window_size_); |
| 236 DCHECK_LT(playback_rate_, 1.0); |
179 DCHECK_NE(playback_rate_, 0.0); | 237 DCHECK_NE(playback_rate_, 0.0); |
180 // Note: This may not play at the speed requested as we can only consume as | 238 |
181 // much data as we have, and audio timestamps drive the pipeline clock. | 239 if (audio_buffer_.forward_bytes() < bytes_per_frame_) |
182 // | 240 return false; |
183 // Furthermore, we won't end up scaling the very last bit of audio, but | 241 |
184 // we're talking about <8ms of audio data. | 242 // The audio data is output in a series of windows. For slowed down playback, |
185 | 243 // the window is comprised of the following phases: |
186 // Cap the |input_step| by the amount of bytes buffered. | 244 // |
187 uint32 input_step = | 245 // a) Output raw data. |
188 std::min(static_cast<uint32>(length * playback_rate_), bytes_buffered()); | 246 // b) Output and save bytes for crossfade in |crossfade_buffer_|. |
189 uint32 output_step = input_step / playback_rate_; | 247 // c) Output* raw data. |
190 AlignToSampleBoundary(&input_step); | 248 // d) Output* crossfaded audio leading up to the next window. |
191 AlignToSampleBoundary(&output_step); | 249 // |
192 | 250 // * Phases c) and d) do not progress |audio_buffer_|'s cursor so that the |
193 DCHECK_LE(output_step, length); | 251 // |audio_buffer_|'s cursor is in the correct place for the next window. |
194 if (output_step > length) { | 252 // |
195 LOG(ERROR) << "OLA: output_step (" << output_step << ") calculated to " | 253 // The duration of each phase is computed below based on the |window_size_| |
196 << "be larger than destination length (" << length << ")"; | 254 // and |playback_rate_|. |
197 output_step = length; | 255 uint32 input_step = ceil(window_size_ * playback_rate_); |
198 } | 256 AlignToFrameBoundary(&input_step); |
199 | 257 uint32 output_step = window_size_; |
200 memset(dest, 0, output_step); | 258 DCHECK_LT(input_step, output_step); |
201 AdvanceBufferPosition(input_step); | 259 |
202 return output_step; | 260 uint32 bytes_to_crossfade = bytes_in_crossfade_; |
| 261 if (muted_ || bytes_to_crossfade > input_step) |
| 262 bytes_to_crossfade = 0; |
| 263 |
| 264 // This is the index of the end of phase a, beginning of phase b. |
| 265 uint32 intro_crossfade_begin = input_step - bytes_to_crossfade; |
| 266 |
| 267 // This is the index of the end of phase b, beginning of phase c. |
| 268 uint32 intro_crossfade_end = input_step; |
| 269 |
| 270 // This is the index of the end of phase c, beginning of phase d. |
| 271 // This phase continues until |index_into_window_| reaches |window_size_|, at |
| 272 // which point the window restarts. |
| 273 uint32 outtro_crossfade_begin = output_step - bytes_to_crossfade; |
| 274 |
| 275 // a) Output a raw frame. |
| 276 if (index_into_window_ < intro_crossfade_begin) { |
| 277 CopyWithAdvance(dest); |
| 278 index_into_window_ += bytes_per_frame_; |
| 279 return true; |
| 280 } |
| 281 |
| 282 // b) Save the raw frame for the intro crossfade section, then output the |
| 283 // frame to |dest|. |
| 284 if (index_into_window_ < intro_crossfade_end) { |
| 285 uint32 offset = index_into_window_ - intro_crossfade_begin; |
| 286 uint8* place_to_copy = crossfade_buffer_.get() + offset; |
| 287 CopyWithoutAdvance(place_to_copy); |
| 288 CopyWithAdvance(dest); |
| 289 index_into_window_ += bytes_per_frame_; |
| 290 return true; |
| 291 } |
| 292 |
| 293 uint32 audio_buffer_offset = index_into_window_ - intro_crossfade_end; |
| 294 |
| 295 if (audio_buffer_.forward_bytes() < audio_buffer_offset + bytes_per_frame_) |
| 296 return false; |
| 297 |
| 298 // c) Output a raw frame into |dest| without advancing the |audio_buffer_| |
| 299 // cursor. See function-level comment. |
| 300 DCHECK_GE(index_into_window_, intro_crossfade_end); |
| 301 CopyWithoutAdvance(dest, audio_buffer_offset); |
| 302 |
| 303 // d) Crossfade the next frame of |crossfade_buffer_| into |dest| if we've |
| 304 // reached the outtro crossfade section of the window. |
| 305 if (index_into_window_ >= outtro_crossfade_begin) { |
| 306 uint32 offset_into_crossfade_buffer = |
| 307 index_into_window_ - outtro_crossfade_begin; |
| 308 uint8* intro_frame_ptr = |
| 309 crossfade_buffer_.get() + offset_into_crossfade_buffer; |
| 310 OutputCrossfadedFrame(dest, intro_frame_ptr); |
| 311 } |
| 312 |
| 313 index_into_window_ += bytes_per_frame_; |
| 314 return true; |
| 315 } |
| 316 |
| 317 bool AudioRendererAlgorithmBase::OutputNormalPlayback(uint8* dest) { |
| 318 if (audio_buffer_.forward_bytes() >= bytes_per_frame_) { |
| 319 CopyWithAdvance(dest); |
| 320 index_into_window_ += bytes_per_frame_; |
| 321 return true; |
| 322 } |
| 323 return false; |
| 324 } |
| 325 |
| 326 void AudioRendererAlgorithmBase::CopyWithAdvance(uint8* dest) { |
| 327 CopyWithoutAdvance(dest); |
| 328 DropFrame(); |
| 329 } |
| 330 |
| 331 void AudioRendererAlgorithmBase::CopyWithoutAdvance(uint8* dest) { |
| 332 CopyWithoutAdvance(dest, 0); |
| 333 } |
| 334 |
| 335 void AudioRendererAlgorithmBase::CopyWithoutAdvance( |
| 336 uint8* dest, uint32 offset) { |
| 337 if (muted_) { |
| 338 memset(dest, 0, bytes_per_frame_); |
| 339 return; |
| 340 } |
| 341 uint32 copied = audio_buffer_.Peek(dest, bytes_per_frame_, offset); |
| 342 DCHECK_EQ(bytes_per_frame_, copied); |
| 343 } |
| 344 |
| 345 void AudioRendererAlgorithmBase::DropFrame() { |
| 346 audio_buffer_.Seek(bytes_per_frame_); |
| 347 |
| 348 if (!IsQueueFull()) |
| 349 request_read_cb_.Run(); |
| 350 } |
| 351 |
| 352 void AudioRendererAlgorithmBase::OutputCrossfadedFrame( |
| 353 uint8* outtro, const uint8* intro) { |
| 354 DCHECK_LE(index_into_window_, window_size_); |
| 355 DCHECK(!muted_); |
| 356 |
| 357 switch (bytes_per_channel_) { |
| 358 case 4: |
| 359 CrossfadeFrame<int32>(outtro, intro); |
| 360 break; |
| 361 case 2: |
| 362 CrossfadeFrame<int16>(outtro, intro); |
| 363 break; |
| 364 case 1: |
| 365 CrossfadeFrame<uint8>(outtro, intro); |
| 366 break; |
| 367 default: |
| 368 NOTREACHED() << "Unsupported audio bit depth in crossfade."; |
| 369 } |
| 370 } |
| 371 |
| 372 template <class Type> |
| 373 void AudioRendererAlgorithmBase::CrossfadeFrame( |
| 374 uint8* outtro_bytes, const uint8* intro_bytes) { |
| 375 Type* outtro = reinterpret_cast<Type*>(outtro_bytes); |
| 376 const Type* intro = reinterpret_cast<const Type*>(intro_bytes); |
| 377 |
| 378 uint32 frames_in_crossfade = bytes_in_crossfade_ / bytes_per_frame_; |
| 379 float crossfade_ratio = |
| 380 static_cast<float>(crossfade_frame_number_) / frames_in_crossfade; |
| 381 for (int channel = 0; channel < channels_; ++channel) { |
| 382 *outtro *= 1.0 - crossfade_ratio; |
| 383 *outtro++ += (*intro++) * crossfade_ratio; |
| 384 } |
| 385 crossfade_frame_number_++; |
203 } | 386 } |
204 | 387 |
205 void AudioRendererAlgorithmBase::SetPlaybackRate(float new_rate) { | 388 void AudioRendererAlgorithmBase::SetPlaybackRate(float new_rate) { |
206 DCHECK_GE(new_rate, 0.0); | 389 DCHECK_GE(new_rate, 0.0); |
207 playback_rate_ = new_rate; | 390 playback_rate_ = new_rate; |
208 } | 391 muted_ = |
209 | 392 playback_rate_ < kMinPlaybackRate || playback_rate_ > kMaxPlaybackRate; |
210 void AudioRendererAlgorithmBase::AlignToSampleBoundary(uint32* value) { | 393 |
211 (*value) -= ((*value) % (channels_ * bytes_per_channel_)); | 394 ResetWindow(); |
| 395 } |
| 396 |
| 397 void AudioRendererAlgorithmBase::AlignToFrameBoundary(uint32* value) { |
| 398 (*value) -= ((*value) % bytes_per_frame_); |
212 } | 399 } |
213 | 400 |
214 void AudioRendererAlgorithmBase::FlushBuffers() { | 401 void AudioRendererAlgorithmBase::FlushBuffers() { |
| 402 ResetWindow(); |
| 403 |
215 // Clear the queue of decoded packets (releasing the buffers). | 404 // Clear the queue of decoded packets (releasing the buffers). |
216 audio_buffer_.Clear(); | 405 audio_buffer_.Clear(); |
217 request_read_cb_.Run(); | 406 request_read_cb_.Run(); |
218 } | 407 } |
219 | 408 |
220 base::TimeDelta AudioRendererAlgorithmBase::GetTime() { | 409 base::TimeDelta AudioRendererAlgorithmBase::GetTime() { |
221 return audio_buffer_.current_time(); | 410 return audio_buffer_.current_time(); |
222 } | 411 } |
223 | 412 |
224 void AudioRendererAlgorithmBase::EnqueueBuffer(Buffer* buffer_in) { | 413 void AudioRendererAlgorithmBase::EnqueueBuffer(Buffer* buffer_in) { |
225 // If we're at end of stream, |buffer_in| contains no data. | 414 DCHECK(!buffer_in->IsEndOfStream()); |
226 if (!buffer_in->IsEndOfStream()) | 415 audio_buffer_.Append(buffer_in); |
227 audio_buffer_.Append(buffer_in); | 416 needs_more_data_ = false; |
228 | 417 |
229 // If we still don't have enough data, request more. | 418 // If we still don't have enough data, request more. |
230 if (!IsQueueFull()) | 419 if (!IsQueueFull()) |
231 request_read_cb_.Run(); | 420 request_read_cb_.Run(); |
232 } | 421 } |
233 | 422 |
| 423 bool AudioRendererAlgorithmBase::NeedsMoreData() { |
| 424 return needs_more_data_ || IsQueueEmpty(); |
| 425 } |
| 426 |
234 bool AudioRendererAlgorithmBase::IsQueueEmpty() { | 427 bool AudioRendererAlgorithmBase::IsQueueEmpty() { |
235 return audio_buffer_.forward_bytes() == 0; | 428 return audio_buffer_.forward_bytes() == 0; |
236 } | 429 } |
237 | 430 |
238 bool AudioRendererAlgorithmBase::IsQueueFull() { | 431 bool AudioRendererAlgorithmBase::IsQueueFull() { |
239 return audio_buffer_.forward_bytes() >= audio_buffer_.forward_capacity(); | 432 return audio_buffer_.forward_bytes() >= audio_buffer_.forward_capacity(); |
240 } | 433 } |
241 | 434 |
242 uint32 AudioRendererAlgorithmBase::QueueCapacity() { | 435 uint32 AudioRendererAlgorithmBase::QueueCapacity() { |
243 return audio_buffer_.forward_capacity(); | 436 return audio_buffer_.forward_capacity(); |
244 } | 437 } |
245 | 438 |
246 void AudioRendererAlgorithmBase::IncreaseQueueCapacity() { | 439 void AudioRendererAlgorithmBase::IncreaseQueueCapacity() { |
247 audio_buffer_.set_forward_capacity( | 440 audio_buffer_.set_forward_capacity( |
248 std::min(2 * audio_buffer_.forward_capacity(), kMaxBufferSizeInBytes)); | 441 std::min(2 * audio_buffer_.forward_capacity(), kMaxBufferSizeInBytes)); |
249 } | 442 } |
250 | 443 |
251 void AudioRendererAlgorithmBase::AdvanceBufferPosition(uint32 bytes) { | |
252 audio_buffer_.Seek(bytes); | |
253 | |
254 if (!IsQueueFull()) | |
255 request_read_cb_.Run(); | |
256 } | |
257 | |
258 uint32 AudioRendererAlgorithmBase::CopyFromAudioBuffer( | |
259 uint8* dest, uint32 bytes) { | |
260 return audio_buffer_.Peek(dest, bytes); | |
261 } | |
262 | |
263 } // namespace media | 444 } // namespace media |
OLD | NEW |