Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: media/filters/audio_renderer_base.cc

Issue 9155003: Fix media timeline so that thumb never exceeds buffered data (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698