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_base.h" | 5 #include "media/filters/audio_renderer_base.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <math.h> |
8 #include <string> | |
9 | 8 |
10 #include "base/bind.h" | 9 #include "base/bind.h" |
11 #include "base/callback.h" | 10 #include "base/callback.h" |
12 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "media/base/filter_host.h" | 13 #include "media/base/filter_host.h" |
| 14 #include "media/audio/audio_util.h" |
15 | 15 |
16 namespace media { | 16 namespace media { |
17 | 17 |
18 AudioRendererBase::AudioRendererBase() | 18 AudioRendererBase::AudioRendererBase(media::AudioRendererSink* sink) |
19 : state_(kUninitialized), | 19 : state_(kUninitialized), |
20 pending_read_(false), | 20 pending_read_(false), |
21 received_end_of_stream_(false), | 21 received_end_of_stream_(false), |
22 rendered_end_of_stream_(false), | 22 rendered_end_of_stream_(false), |
23 bytes_per_frame_(0), | 23 bytes_per_frame_(0), |
| 24 bytes_per_second_(0), |
| 25 stopped_(false), |
| 26 sink_(sink), |
| 27 is_initialized_(false), |
24 read_cb_(base::Bind(&AudioRendererBase::DecodedAudioReady, | 28 read_cb_(base::Bind(&AudioRendererBase::DecodedAudioReady, |
25 base::Unretained(this))) { | 29 base::Unretained(this))) { |
26 } | 30 } |
27 | 31 |
28 AudioRendererBase::~AudioRendererBase() { | 32 AudioRendererBase::~AudioRendererBase() { |
29 // Stop() should have been called and |algorithm_| should have been destroyed. | 33 // Stop() should have been called and |algorithm_| should have been destroyed. |
30 DCHECK(state_ == kUninitialized || state_ == kStopped); | 34 DCHECK(state_ == kUninitialized || state_ == kStopped); |
31 DCHECK(!algorithm_.get()); | 35 DCHECK(!algorithm_.get()); |
32 } | 36 } |
33 | 37 |
34 void AudioRendererBase::Play(const base::Closure& callback) { | 38 void AudioRendererBase::Play(const base::Closure& callback) { |
35 base::AutoLock auto_lock(lock_); | 39 { |
36 DCHECK_EQ(kPaused, state_); | 40 base::AutoLock auto_lock(lock_); |
37 state_ = kPlaying; | 41 DCHECK_EQ(kPaused, state_); |
38 callback.Run(); | 42 state_ = kPlaying; |
| 43 callback.Run(); |
| 44 } |
| 45 |
| 46 if (stopped_) |
| 47 return; |
| 48 |
| 49 if (GetPlaybackRate() != 0.0f) { |
| 50 DoPlay(); |
| 51 } else { |
| 52 DoPause(); |
| 53 } |
| 54 } |
| 55 |
| 56 void AudioRendererBase::DoPlay() { |
| 57 earliest_end_time_ = base::Time::Now(); |
| 58 DCHECK(sink_.get()); |
| 59 sink_->Play(); |
39 } | 60 } |
40 | 61 |
41 void AudioRendererBase::Pause(const base::Closure& callback) { | 62 void AudioRendererBase::Pause(const base::Closure& callback) { |
42 base::AutoLock auto_lock(lock_); | 63 { |
43 DCHECK(state_ == kPlaying || state_ == kUnderflow || state_ == kRebuffering); | 64 base::AutoLock auto_lock(lock_); |
44 pause_cb_ = callback; | 65 DCHECK(state_ == kPlaying || state_ == kUnderflow || |
45 state_ = kPaused; | 66 state_ == kRebuffering); |
| 67 pause_cb_ = callback; |
| 68 state_ = kPaused; |
46 | 69 |
47 // Pause only when we've completed our pending read. | 70 // Pause only when we've completed our pending read. |
48 if (!pending_read_) { | 71 if (!pending_read_) { |
49 pause_cb_.Run(); | 72 pause_cb_.Run(); |
50 pause_cb_.Reset(); | 73 pause_cb_.Reset(); |
51 } else { | 74 } |
52 state_ = kPaused; | |
53 } | 75 } |
| 76 |
| 77 if (stopped_) |
| 78 return; |
| 79 |
| 80 DoPause(); |
| 81 } |
| 82 |
| 83 void AudioRendererBase::DoPause() { |
| 84 DCHECK(sink_.get()); |
| 85 sink_->Pause(false); |
54 } | 86 } |
55 | 87 |
56 void AudioRendererBase::Flush(const base::Closure& callback) { | 88 void AudioRendererBase::Flush(const base::Closure& callback) { |
57 decoder_->Reset(callback); | 89 decoder_->Reset(callback); |
58 } | 90 } |
59 | 91 |
60 void AudioRendererBase::Stop(const base::Closure& callback) { | 92 void AudioRendererBase::Stop(const base::Closure& callback) { |
61 OnStop(); | 93 if (!stopped_) { |
| 94 DCHECK(sink_.get()); |
| 95 sink_->Stop(); |
| 96 |
| 97 stopped_ = true; |
| 98 } |
62 { | 99 { |
63 base::AutoLock auto_lock(lock_); | 100 base::AutoLock auto_lock(lock_); |
64 state_ = kStopped; | 101 state_ = kStopped; |
65 algorithm_.reset(NULL); | 102 algorithm_.reset(NULL); |
66 time_cb_.Reset(); | 103 time_cb_.Reset(); |
67 underflow_cb_.Reset(); | 104 underflow_cb_.Reset(); |
68 } | 105 } |
69 if (!callback.is_null()) { | 106 if (!callback.is_null()) { |
70 callback.Run(); | 107 callback.Run(); |
71 } | 108 } |
72 } | 109 } |
73 | 110 |
74 void AudioRendererBase::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { | 111 void AudioRendererBase::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { |
75 base::AutoLock auto_lock(lock_); | 112 base::AutoLock auto_lock(lock_); |
76 DCHECK_EQ(kPaused, state_); | 113 DCHECK_EQ(kPaused, state_); |
77 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 114 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
78 DCHECK(pause_cb_.is_null()); | 115 DCHECK(pause_cb_.is_null()); |
79 DCHECK(seek_cb_.is_null()); | 116 DCHECK(seek_cb_.is_null()); |
80 state_ = kSeeking; | 117 state_ = kSeeking; |
81 seek_cb_ = cb; | 118 seek_cb_ = cb; |
82 seek_timestamp_ = time; | 119 seek_timestamp_ = time; |
83 | 120 |
84 // Throw away everything and schedule our reads. | 121 // Throw away everything and schedule our reads. |
85 last_fill_buffer_time_ = base::TimeDelta(); | 122 audio_time_buffered_ = base::TimeDelta(); |
86 received_end_of_stream_ = false; | 123 received_end_of_stream_ = false; |
87 rendered_end_of_stream_ = false; | 124 rendered_end_of_stream_ = false; |
88 | 125 |
89 // |algorithm_| will request more reads. | 126 // |algorithm_| will request more reads. |
90 algorithm_->FlushBuffers(); | 127 algorithm_->FlushBuffers(); |
| 128 |
| 129 if (stopped_) |
| 130 return; |
| 131 |
| 132 DoSeek(); |
| 133 } |
| 134 |
| 135 void AudioRendererBase::DoSeek() { |
| 136 earliest_end_time_ = base::Time::Now(); |
| 137 |
| 138 // Pause and flush the stream when we seek to a new location. |
| 139 sink_->Pause(true); |
91 } | 140 } |
92 | 141 |
93 void AudioRendererBase::Initialize(const scoped_refptr<AudioDecoder>& decoder, | 142 void AudioRendererBase::Initialize(const scoped_refptr<AudioDecoder>& decoder, |
94 const PipelineStatusCB& init_cb, | 143 const PipelineStatusCB& init_cb, |
95 const base::Closure& underflow_cb, | 144 const base::Closure& underflow_cb, |
96 const TimeCB& time_cb) { | 145 const TimeCB& time_cb) { |
97 DCHECK(decoder); | 146 DCHECK(decoder); |
98 DCHECK(!init_cb.is_null()); | 147 DCHECK(!init_cb.is_null()); |
99 DCHECK(!underflow_cb.is_null()); | 148 DCHECK(!underflow_cb.is_null()); |
100 DCHECK(!time_cb.is_null()); | 149 DCHECK(!time_cb.is_null()); |
(...skipping 12 matching lines...) Expand all Loading... |
113 // and a callback to request more reads from the data source. | 162 // and a callback to request more reads from the data source. |
114 ChannelLayout channel_layout = decoder_->channel_layout(); | 163 ChannelLayout channel_layout = decoder_->channel_layout(); |
115 int channels = ChannelLayoutToChannelCount(channel_layout); | 164 int channels = ChannelLayoutToChannelCount(channel_layout); |
116 int bits_per_channel = decoder_->bits_per_channel(); | 165 int bits_per_channel = decoder_->bits_per_channel(); |
117 int sample_rate = decoder_->samples_per_second(); | 166 int sample_rate = decoder_->samples_per_second(); |
118 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame. | 167 // TODO(vrk): Add method to AudioDecoder to compute bytes per frame. |
119 bytes_per_frame_ = channels * bits_per_channel / 8; | 168 bytes_per_frame_ = channels * bits_per_channel / 8; |
120 | 169 |
121 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate, | 170 bool config_ok = algorithm_->ValidateConfig(channels, sample_rate, |
122 bits_per_channel); | 171 bits_per_channel); |
123 if (config_ok) | 172 if (!config_ok || is_initialized_) { |
124 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb); | |
125 | |
126 // Give the subclass an opportunity to initialize itself. | |
127 if (!config_ok || !OnInitialize(bits_per_channel, channel_layout, | |
128 sample_rate)) { | |
129 init_cb.Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 173 init_cb.Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
130 return; | 174 return; |
131 } | 175 } |
132 | 176 |
| 177 if (config_ok) |
| 178 algorithm_->Initialize(channels, sample_rate, bits_per_channel, 0.0f, cb); |
| 179 |
| 180 // We use the AUDIO_PCM_LINEAR flag because AUDIO_PCM_LOW_LATENCY |
| 181 // does not currently support all the sample-rates that we require. |
| 182 // Please see: http://code.google.com/p/chromium/issues/detail?id=103627 |
| 183 // for more details. |
| 184 audio_parameters_ = AudioParameters( |
| 185 AudioParameters::AUDIO_PCM_LINEAR, channel_layout, sample_rate, |
| 186 bits_per_channel, GetHighLatencyOutputBufferSize(sample_rate)); |
| 187 |
| 188 bytes_per_second_ = audio_parameters_.GetBytesPerSecond(); |
| 189 |
| 190 DCHECK(sink_.get()); |
| 191 DCHECK(!is_initialized_); |
| 192 |
| 193 sink_->Initialize(audio_parameters_, this); |
| 194 |
| 195 sink_->Start(); |
| 196 is_initialized_ = true; |
| 197 |
133 // Finally, execute the start callback. | 198 // Finally, execute the start callback. |
134 state_ = kPaused; | 199 state_ = kPaused; |
135 init_cb.Run(PIPELINE_OK); | 200 init_cb.Run(PIPELINE_OK); |
136 } | 201 } |
137 | 202 |
138 bool AudioRendererBase::HasEnded() { | 203 bool AudioRendererBase::HasEnded() { |
139 base::AutoLock auto_lock(lock_); | 204 base::AutoLock auto_lock(lock_); |
140 DCHECK(!rendered_end_of_stream_ || algorithm_->NeedsMoreData()); | 205 DCHECK(!rendered_end_of_stream_ || algorithm_->NeedsMoreData()); |
141 | 206 |
142 return received_end_of_stream_ && rendered_end_of_stream_; | 207 return received_end_of_stream_ && rendered_end_of_stream_; |
143 } | 208 } |
144 | 209 |
145 void AudioRendererBase::ResumeAfterUnderflow(bool buffer_more_audio) { | 210 void AudioRendererBase::ResumeAfterUnderflow(bool buffer_more_audio) { |
146 base::AutoLock auto_lock(lock_); | 211 base::AutoLock auto_lock(lock_); |
147 if (state_ == kUnderflow) { | 212 if (state_ == kUnderflow) { |
148 if (buffer_more_audio) | 213 if (buffer_more_audio) |
149 algorithm_->IncreaseQueueCapacity(); | 214 algorithm_->IncreaseQueueCapacity(); |
150 | 215 |
151 state_ = kRebuffering; | 216 state_ = kRebuffering; |
152 } | 217 } |
153 } | 218 } |
154 | 219 |
| 220 void AudioRendererBase::SetVolume(float volume) { |
| 221 if (stopped_) |
| 222 return; |
| 223 sink_->SetVolume(volume); |
| 224 } |
| 225 |
155 void AudioRendererBase::DecodedAudioReady(scoped_refptr<Buffer> buffer) { | 226 void AudioRendererBase::DecodedAudioReady(scoped_refptr<Buffer> buffer) { |
156 base::AutoLock auto_lock(lock_); | 227 base::AutoLock auto_lock(lock_); |
157 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying || | 228 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying || |
158 state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped); | 229 state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped); |
159 | 230 |
160 CHECK(pending_read_); | 231 CHECK(pending_read_); |
161 pending_read_ = false; | 232 pending_read_ = false; |
162 | 233 |
163 if (buffer && buffer->IsEndOfStream()) { | 234 if (buffer && buffer->IsEndOfStream()) { |
164 received_end_of_stream_ = true; | 235 received_end_of_stream_ = true; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 case kUnderflow: | 267 case kUnderflow: |
197 case kRebuffering: | 268 case kRebuffering: |
198 if (buffer && !buffer->IsEndOfStream()) | 269 if (buffer && !buffer->IsEndOfStream()) |
199 algorithm_->EnqueueBuffer(buffer); | 270 algorithm_->EnqueueBuffer(buffer); |
200 return; | 271 return; |
201 case kStopped: | 272 case kStopped: |
202 return; | 273 return; |
203 } | 274 } |
204 } | 275 } |
205 | 276 |
| 277 void AudioRendererBase::SignalEndOfStream() { |
| 278 DCHECK(received_end_of_stream_); |
| 279 if (!rendered_end_of_stream_) { |
| 280 rendered_end_of_stream_ = true; |
| 281 host()->NotifyEnded(); |
| 282 } |
| 283 } |
| 284 |
| 285 void AudioRendererBase::ScheduleRead_Locked() { |
| 286 lock_.AssertAcquired(); |
| 287 if (pending_read_ || state_ == kPaused) |
| 288 return; |
| 289 pending_read_ = true; |
| 290 decoder_->Read(read_cb_); |
| 291 } |
| 292 |
| 293 void AudioRendererBase::SetPlaybackRate(float playback_rate) { |
| 294 DCHECK_LE(0.0f, playback_rate); |
| 295 |
| 296 if (!stopped_) { |
| 297 // Notify sink of new playback rate. |
| 298 sink_->SetPlaybackRate(playback_rate); |
| 299 |
| 300 // We have two cases here: |
| 301 // Play: GetPlaybackRate() == 0.0 && playback_rate != 0.0 |
| 302 // Pause: GetPlaybackRate() != 0.0 && playback_rate == 0.0 |
| 303 if (GetPlaybackRate() == 0.0f && playback_rate != 0.0f) { |
| 304 DoPlay(); |
| 305 } else if (GetPlaybackRate() != 0.0f && playback_rate == 0.0f) { |
| 306 // Pause is easy, we can always pause. |
| 307 DoPause(); |
| 308 } |
| 309 } |
| 310 |
| 311 base::AutoLock auto_lock(lock_); |
| 312 algorithm_->SetPlaybackRate(playback_rate); |
| 313 } |
| 314 |
| 315 float AudioRendererBase::GetPlaybackRate() { |
| 316 base::AutoLock auto_lock(lock_); |
| 317 return algorithm_->playback_rate(); |
| 318 } |
| 319 |
| 320 bool AudioRendererBase::IsBeforeSeekTime(const scoped_refptr<Buffer>& buffer) { |
| 321 return (state_ == kSeeking) && buffer && !buffer->IsEndOfStream() && |
| 322 (buffer->GetTimestamp() + buffer->GetDuration()) < seek_timestamp_; |
| 323 } |
| 324 |
| 325 int AudioRendererBase::Render(const std::vector<float*>& audio_data, |
| 326 int number_of_frames, |
| 327 int audio_delay_milliseconds) { |
| 328 if (stopped_ || GetPlaybackRate() == 0.0f) { |
| 329 // Output silence if stopped. |
| 330 for (size_t i = 0; i < audio_data.size(); ++i) |
| 331 memset(audio_data[i], 0, sizeof(float) * number_of_frames); |
| 332 return 0; |
| 333 } |
| 334 |
| 335 // Adjust the playback delay. |
| 336 base::TimeDelta request_delay = |
| 337 base::TimeDelta::FromMilliseconds(audio_delay_milliseconds); |
| 338 |
| 339 // Finally we need to adjust the delay according to playback rate. |
| 340 if (GetPlaybackRate() != 1.0f) { |
| 341 request_delay = base::TimeDelta::FromMicroseconds( |
| 342 static_cast<int64>(ceil(request_delay.InMicroseconds() * |
| 343 GetPlaybackRate()))); |
| 344 } |
| 345 |
| 346 int bytes_per_frame = audio_parameters_.GetBytesPerFrame(); |
| 347 |
| 348 const int buf_size = number_of_frames * bytes_per_frame; |
| 349 scoped_array<uint8> buf(new uint8[buf_size]); |
| 350 |
| 351 int frames_filled = FillBuffer(buf.get(), number_of_frames, request_delay); |
| 352 int bytes_filled = frames_filled * bytes_per_frame; |
| 353 DCHECK_LE(bytes_filled, buf_size); |
| 354 UpdateEarliestEndTime(bytes_filled, request_delay, base::Time::Now()); |
| 355 |
| 356 // Deinterleave each audio channel. |
| 357 int channels = audio_data.size(); |
| 358 for (int channel_index = 0; channel_index < channels; ++channel_index) { |
| 359 media::DeinterleaveAudioChannel(buf.get(), |
| 360 audio_data[channel_index], |
| 361 channels, |
| 362 channel_index, |
| 363 bytes_per_frame / channels, |
| 364 frames_filled); |
| 365 |
| 366 // If FillBuffer() didn't give us enough data then zero out the remainder. |
| 367 if (frames_filled < number_of_frames) { |
| 368 int frames_to_zero = number_of_frames - frames_filled; |
| 369 memset(audio_data[channel_index] + frames_filled, |
| 370 0, |
| 371 sizeof(float) * frames_to_zero); |
| 372 } |
| 373 } |
| 374 return frames_filled; |
| 375 } |
| 376 |
206 uint32 AudioRendererBase::FillBuffer(uint8* dest, | 377 uint32 AudioRendererBase::FillBuffer(uint8* dest, |
207 uint32 requested_frames, | 378 uint32 requested_frames, |
208 const base::TimeDelta& playback_delay) { | 379 const base::TimeDelta& playback_delay) { |
209 // The timestamp of the last buffer written during the last call to | 380 // The |audio_time_buffered_| is the ending timestamp of the last frame |
210 // FillBuffer(). | 381 // buffered at the audio device. |playback_delay| is the amount of time |
211 base::TimeDelta last_fill_buffer_time; | 382 // buffered at the audio device. The current time can be computed by their |
| 383 // difference. |
| 384 base::TimeDelta current_time = audio_time_buffered_ - playback_delay; |
| 385 |
212 size_t frames_written = 0; | 386 size_t frames_written = 0; |
213 base::Closure underflow_cb; | 387 base::Closure underflow_cb; |
214 { | 388 { |
215 base::AutoLock auto_lock(lock_); | 389 base::AutoLock auto_lock(lock_); |
216 | 390 |
217 if (state_ == kRebuffering && algorithm_->IsQueueFull()) | 391 if (state_ == kRebuffering && algorithm_->IsQueueFull()) |
218 state_ = kPlaying; | 392 state_ = kPlaying; |
219 | 393 |
220 // Mute audio by returning 0 when not playing. | 394 // Mute audio by returning 0 when not playing. |
221 if (state_ != kPlaying) { | 395 if (state_ != kPlaying) { |
222 // TODO(scherkus): To keep the audio hardware busy we write at most 8k of | 396 // TODO(scherkus): To keep the audio hardware busy we write at most 8k of |
223 // zeros. This gets around the tricky situation of pausing and resuming | 397 // zeros. This gets around the tricky situation of pausing and resuming |
224 // the audio IPC layer in Chrome. Ideally, we should return zero and then | 398 // the audio IPC layer in Chrome. Ideally, we should return zero and then |
225 // the subclass can restart the conversation. | 399 // the subclass can restart the conversation. |
226 // | 400 // |
227 // This should get handled by the subclass http://crbug.com/106600 | 401 // This should get handled by the subclass http://crbug.com/106600 |
228 const uint32 kZeroLength = 8192; | 402 const uint32 kZeroLength = 8192; |
229 size_t zeros_to_write = | 403 size_t zeros_to_write = |
230 std::min(kZeroLength, requested_frames * bytes_per_frame_); | 404 std::min(kZeroLength, requested_frames * bytes_per_frame_); |
231 memset(dest, 0, zeros_to_write); | 405 memset(dest, 0, zeros_to_write); |
232 return zeros_to_write / bytes_per_frame_; | 406 return zeros_to_write / bytes_per_frame_; |
233 } | 407 } |
234 | 408 |
235 // Save a local copy of last fill buffer time and reset the member. | |
236 last_fill_buffer_time = last_fill_buffer_time_; | |
237 last_fill_buffer_time_ = base::TimeDelta(); | |
238 | |
239 // Use three conditions to determine the end of playback: | 409 // Use three conditions to determine the end of playback: |
240 // 1. Algorithm needs more audio data. | 410 // 1. Algorithm needs more audio data. |
241 // 2. We've received an end of stream buffer. | 411 // 2. We've received an end of stream buffer. |
242 // (received_end_of_stream_ == true) | 412 // (received_end_of_stream_ == true) |
243 // 3. Browser process has no audio data being played. | 413 // 3. Browser process has no audio data being played. |
244 // There is no way to check that condition that would work for all | 414 // There is no way to check that condition that would work for all |
245 // derived classes, so call virtual method that would either render | 415 // derived classes, so call virtual method that would either render |
246 // end of stream or schedule such rendering. | 416 // end of stream or schedule such rendering. |
247 // | 417 // |
248 // Three conditions determine when an underflow occurs: | 418 // Three conditions determine when an underflow occurs: |
249 // 1. Algorithm has no audio data. | 419 // 1. Algorithm has no audio data. |
250 // 2. Currently in the kPlaying state. | 420 // 2. Currently in the kPlaying state. |
251 // 3. Have not received an end of stream buffer. | 421 // 3. Have not received an end of stream buffer. |
252 if (algorithm_->NeedsMoreData()) { | 422 if (algorithm_->NeedsMoreData()) { |
253 if (received_end_of_stream_) { | 423 if (received_end_of_stream_) { |
254 OnRenderEndOfStream(); | 424 // TODO(enal): schedule callback instead of polling. |
| 425 if (base::Time::Now() >= earliest_end_time_) |
| 426 SignalEndOfStream(); |
255 } else if (state_ == kPlaying) { | 427 } else if (state_ == kPlaying) { |
256 state_ = kUnderflow; | 428 state_ = kUnderflow; |
257 underflow_cb = underflow_cb_; | 429 underflow_cb = underflow_cb_; |
258 } | 430 } |
259 } else { | 431 } else { |
260 // Otherwise fill the buffer. | 432 // Otherwise fill the buffer. |
261 frames_written = algorithm_->FillBuffer(dest, requested_frames); | 433 frames_written = algorithm_->FillBuffer(dest, requested_frames); |
262 } | 434 } |
263 | |
264 // Get the current time. | |
265 last_fill_buffer_time_ = algorithm_->GetTime(); | |
266 } | 435 } |
267 | 436 |
268 // Update the pipeline's time if it was set last time. | 437 base::TimeDelta previous_time_buffered = audio_time_buffered_; |
269 base::TimeDelta new_current_time = last_fill_buffer_time - playback_delay; | 438 // The call to FillBuffer() on |algorithm_| has increased the amount of |
270 if (last_fill_buffer_time.InMicroseconds() > 0 && | 439 // buffered audio data. Update the new amount of time buffered. |
271 (last_fill_buffer_time != last_fill_buffer_time_ || | 440 audio_time_buffered_ = algorithm_->GetTime(); |
272 new_current_time > host()->GetTime())) { | 441 |
273 time_cb_.Run(new_current_time, last_fill_buffer_time); | 442 if (previous_time_buffered.InMicroseconds() > 0 && |
| 443 (previous_time_buffered != audio_time_buffered_ || |
| 444 current_time > host()->GetTime())) { |
| 445 time_cb_.Run(current_time, audio_time_buffered_); |
274 } | 446 } |
275 | 447 |
276 if (!underflow_cb.is_null()) | 448 if (!underflow_cb.is_null()) |
277 underflow_cb.Run(); | 449 underflow_cb.Run(); |
278 | 450 |
279 return frames_written; | 451 return frames_written; |
280 } | 452 } |
281 | 453 |
282 void AudioRendererBase::SignalEndOfStream() { | 454 void AudioRendererBase::UpdateEarliestEndTime(int bytes_filled, |
283 DCHECK(received_end_of_stream_); | 455 base::TimeDelta request_delay, |
284 if (!rendered_end_of_stream_) { | 456 base::Time time_now) { |
285 rendered_end_of_stream_ = true; | 457 if (bytes_filled != 0) { |
286 host()->NotifyEnded(); | 458 base::TimeDelta predicted_play_time = ConvertToDuration(bytes_filled); |
| 459 float playback_rate = GetPlaybackRate(); |
| 460 if (playback_rate != 1.0f) { |
| 461 predicted_play_time = base::TimeDelta::FromMicroseconds( |
| 462 static_cast<int64>(ceil(predicted_play_time.InMicroseconds() * |
| 463 playback_rate))); |
| 464 } |
| 465 earliest_end_time_ = |
| 466 std::max(earliest_end_time_, |
| 467 time_now + request_delay + predicted_play_time); |
287 } | 468 } |
288 } | 469 } |
289 | 470 |
290 void AudioRendererBase::ScheduleRead_Locked() { | 471 base::TimeDelta AudioRendererBase::ConvertToDuration(int bytes) { |
291 lock_.AssertAcquired(); | 472 if (bytes_per_second_) { |
292 if (pending_read_ || state_ == kPaused) | 473 return base::TimeDelta::FromMicroseconds( |
293 return; | 474 base::Time::kMicrosecondsPerSecond * bytes / bytes_per_second_); |
294 pending_read_ = true; | 475 } |
295 decoder_->Read(read_cb_); | 476 return base::TimeDelta(); |
296 } | 477 } |
297 | 478 |
298 void AudioRendererBase::SetPlaybackRate(float playback_rate) { | 479 void AudioRendererBase::OnRenderError() { |
299 base::AutoLock auto_lock(lock_); | 480 host()->DisableAudioRenderer(); |
300 algorithm_->SetPlaybackRate(playback_rate); | |
301 } | |
302 | |
303 float AudioRendererBase::GetPlaybackRate() { | |
304 base::AutoLock auto_lock(lock_); | |
305 return algorithm_->playback_rate(); | |
306 } | |
307 | |
308 bool AudioRendererBase::IsBeforeSeekTime(const scoped_refptr<Buffer>& buffer) { | |
309 return (state_ == kSeeking) && buffer && !buffer->IsEndOfStream() && | |
310 (buffer->GetTimestamp() + buffer->GetDuration()) < seek_timestamp_; | |
311 } | 481 } |
312 | 482 |
313 } // namespace media | 483 } // namespace media |
OLD | NEW |