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 <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 state_ = kPaused; | 50 state_ = kPaused; |
51 } | 51 } |
52 } | 52 } |
53 | 53 |
54 void AudioRendererBase::Stop(const base::Closure& callback) { | 54 void AudioRendererBase::Stop(const base::Closure& callback) { |
55 OnStop(); | 55 OnStop(); |
56 { | 56 { |
57 base::AutoLock auto_lock(lock_); | 57 base::AutoLock auto_lock(lock_); |
58 state_ = kStopped; | 58 state_ = kStopped; |
59 algorithm_.reset(NULL); | 59 algorithm_.reset(NULL); |
| 60 audio_time_cb_.Reset(); |
| 61 underflow_callback_.Reset(); |
60 } | 62 } |
61 if (!callback.is_null()) { | 63 if (!callback.is_null()) { |
62 callback.Run(); | 64 callback.Run(); |
63 } | 65 } |
64 } | 66 } |
65 | 67 |
66 void AudioRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 68 void AudioRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
67 base::AutoLock auto_lock(lock_); | 69 base::AutoLock auto_lock(lock_); |
68 DCHECK_EQ(kPaused, state_); | 70 DCHECK_EQ(kPaused, state_); |
69 DCHECK(!pending_read_) << "Pending read must complete before seeking"; | 71 DCHECK(!pending_read_) << "Pending read must complete before seeking"; |
70 DCHECK(seek_cb_.is_null()); | 72 DCHECK(seek_cb_.is_null()); |
71 state_ = kSeeking; | 73 state_ = kSeeking; |
72 seek_cb_ = cb; | 74 seek_cb_ = cb; |
73 seek_timestamp_ = time; | 75 seek_timestamp_ = time; |
74 | 76 |
75 // Throw away everything and schedule our reads. | 77 // Throw away everything and schedule our reads. |
76 last_fill_buffer_time_ = base::TimeDelta(); | 78 last_fill_buffer_time_ = base::TimeDelta(); |
77 recieved_end_of_stream_ = false; | 79 recieved_end_of_stream_ = false; |
78 rendered_end_of_stream_ = false; | 80 rendered_end_of_stream_ = false; |
79 | 81 |
80 // |algorithm_| will request more reads. | 82 // |algorithm_| will request more reads. |
81 algorithm_->FlushBuffers(); | 83 algorithm_->FlushBuffers(); |
82 } | 84 } |
83 | 85 |
84 void AudioRendererBase::Initialize(AudioDecoder* decoder, | 86 void AudioRendererBase::Initialize(AudioDecoder* decoder, |
85 const base::Closure& init_callback, | 87 const base::Closure& init_callback, |
86 const base::Closure& underflow_callback) { | 88 const base::Closure& underflow_callback, |
| 89 const AudioTimeCB& audio_time_cb) { |
87 DCHECK(decoder); | 90 DCHECK(decoder); |
88 DCHECK(!init_callback.is_null()); | 91 DCHECK(!init_callback.is_null()); |
89 DCHECK(!underflow_callback.is_null()); | 92 DCHECK(!underflow_callback.is_null()); |
| 93 DCHECK(!audio_time_cb.is_null()); |
90 DCHECK_EQ(kUninitialized, state_); | 94 DCHECK_EQ(kUninitialized, state_); |
91 decoder_ = decoder; | 95 decoder_ = decoder; |
92 underflow_callback_ = underflow_callback; | 96 underflow_callback_ = underflow_callback; |
| 97 audio_time_cb_ = audio_time_cb; |
93 | 98 |
94 // Create a callback so our algorithm can request more reads. | 99 // Create a callback so our algorithm can request more reads. |
95 base::Closure cb = base::Bind(&AudioRendererBase::ScheduleRead_Locked, this); | 100 base::Closure cb = base::Bind(&AudioRendererBase::ScheduleRead_Locked, this); |
96 | 101 |
97 // Construct the algorithm. | 102 // Construct the algorithm. |
98 algorithm_.reset(new AudioRendererAlgorithmBase()); | 103 algorithm_.reset(new AudioRendererAlgorithmBase()); |
99 | 104 |
100 // Initialize our algorithm with media properties, initial playback rate, | 105 // Initialize our algorithm with media properties, initial playback rate, |
101 // and a callback to request more reads from the data source. | 106 // and a callback to request more reads from the data source. |
102 ChannelLayout channel_layout = decoder_->channel_layout(); | 107 ChannelLayout channel_layout = decoder_->channel_layout(); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 } else { | 248 } else { |
244 // Otherwise fill the buffer. | 249 // Otherwise fill the buffer. |
245 dest_written = algorithm_->FillBuffer(dest, dest_len); | 250 dest_written = algorithm_->FillBuffer(dest, dest_len); |
246 } | 251 } |
247 | 252 |
248 // Get the current time. | 253 // Get the current time. |
249 last_fill_buffer_time_ = algorithm_->GetTime(); | 254 last_fill_buffer_time_ = algorithm_->GetTime(); |
250 } | 255 } |
251 | 256 |
252 // Update the pipeline's time if it was set last time. | 257 // Update the pipeline's time if it was set last time. |
| 258 base::TimeDelta new_current_time = last_fill_buffer_time - playback_delay; |
253 if (last_fill_buffer_time.InMicroseconds() > 0 && | 259 if (last_fill_buffer_time.InMicroseconds() > 0 && |
254 (last_fill_buffer_time != last_fill_buffer_time_ || | 260 (last_fill_buffer_time != last_fill_buffer_time_ || |
255 (last_fill_buffer_time - playback_delay) > host()->GetTime())) { | 261 new_current_time > host()->GetTime())) { |
256 // Adjust the |last_fill_buffer_time| with the playback delay. | 262 audio_time_cb_.Run(new_current_time, last_fill_buffer_time); |
257 // TODO(hclam): If there is a playback delay, the pipeline would not be | |
258 // updated with a correct timestamp when the stream is played at the very | |
259 // end since we use decoded packets to trigger time updates. A better | |
260 // solution is to start a timer when an audio packet is decoded to allow | |
261 // finer time update events. | |
262 last_fill_buffer_time -= playback_delay; | |
263 host()->SetTime(last_fill_buffer_time); | |
264 } | 263 } |
265 | 264 |
266 if (!underflow_cb.is_null()) | 265 if (!underflow_cb.is_null()) |
267 underflow_cb.Run(); | 266 underflow_cb.Run(); |
268 | 267 |
269 return dest_written; | 268 return dest_written; |
270 } | 269 } |
271 | 270 |
272 void AudioRendererBase::ScheduleRead_Locked() { | 271 void AudioRendererBase::ScheduleRead_Locked() { |
273 lock_.AssertAcquired(); | 272 lock_.AssertAcquired(); |
274 if (pending_read_) | 273 if (pending_read_) |
275 return; | 274 return; |
276 pending_read_ = true; | 275 pending_read_ = true; |
277 decoder_->Read(read_cb_); | 276 decoder_->Read(read_cb_); |
278 } | 277 } |
279 | 278 |
280 void AudioRendererBase::SetPlaybackRate(float playback_rate) { | 279 void AudioRendererBase::SetPlaybackRate(float playback_rate) { |
281 base::AutoLock auto_lock(lock_); | 280 base::AutoLock auto_lock(lock_); |
282 algorithm_->SetPlaybackRate(playback_rate); | 281 algorithm_->SetPlaybackRate(playback_rate); |
283 } | 282 } |
284 | 283 |
285 float AudioRendererBase::GetPlaybackRate() { | 284 float AudioRendererBase::GetPlaybackRate() { |
286 base::AutoLock auto_lock(lock_); | 285 base::AutoLock auto_lock(lock_); |
287 return algorithm_->playback_rate(); | 286 return algorithm_->playback_rate(); |
288 } | 287 } |
289 | 288 |
290 } // namespace media | 289 } // namespace media |
OLD | NEW |