OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/callback.h" | 10 #include "base/callback.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 pending_reads_(0) { | 21 pending_reads_(0) { |
22 } | 22 } |
23 | 23 |
24 AudioRendererBase::~AudioRendererBase() { | 24 AudioRendererBase::~AudioRendererBase() { |
25 // Stop() should have been called and |algorithm_| should have been destroyed. | 25 // Stop() should have been called and |algorithm_| should have been destroyed. |
26 DCHECK(state_ == kUninitialized || state_ == kStopped); | 26 DCHECK(state_ == kUninitialized || state_ == kStopped); |
27 DCHECK(!algorithm_.get()); | 27 DCHECK(!algorithm_.get()); |
28 } | 28 } |
29 | 29 |
30 void AudioRendererBase::Play(FilterCallback* callback) { | 30 void AudioRendererBase::Play(FilterCallback* callback) { |
31 AutoLock auto_lock(lock_); | 31 base::AutoLock auto_lock(lock_); |
32 DCHECK_EQ(kPaused, state_); | 32 DCHECK_EQ(kPaused, state_); |
33 scoped_ptr<FilterCallback> c(callback); | 33 scoped_ptr<FilterCallback> c(callback); |
34 state_ = kPlaying; | 34 state_ = kPlaying; |
35 callback->Run(); | 35 callback->Run(); |
36 } | 36 } |
37 | 37 |
38 void AudioRendererBase::Pause(FilterCallback* callback) { | 38 void AudioRendererBase::Pause(FilterCallback* callback) { |
39 AutoLock auto_lock(lock_); | 39 base::AutoLock auto_lock(lock_); |
40 DCHECK_EQ(kPlaying, state_); | 40 DCHECK_EQ(kPlaying, state_); |
41 pause_callback_.reset(callback); | 41 pause_callback_.reset(callback); |
42 state_ = kPaused; | 42 state_ = kPaused; |
43 | 43 |
44 // We'll only pause when we've finished all pending reads. | 44 // We'll only pause when we've finished all pending reads. |
45 if (pending_reads_ == 0) { | 45 if (pending_reads_ == 0) { |
46 pause_callback_->Run(); | 46 pause_callback_->Run(); |
47 pause_callback_.reset(); | 47 pause_callback_.reset(); |
48 } else { | 48 } else { |
49 state_ = kPaused; | 49 state_ = kPaused; |
50 } | 50 } |
51 } | 51 } |
52 | 52 |
53 void AudioRendererBase::Stop(FilterCallback* callback) { | 53 void AudioRendererBase::Stop(FilterCallback* callback) { |
54 OnStop(); | 54 OnStop(); |
55 { | 55 { |
56 AutoLock auto_lock(lock_); | 56 base::AutoLock auto_lock(lock_); |
57 state_ = kStopped; | 57 state_ = kStopped; |
58 algorithm_.reset(NULL); | 58 algorithm_.reset(NULL); |
59 } | 59 } |
60 if (callback) { | 60 if (callback) { |
61 callback->Run(); | 61 callback->Run(); |
62 delete callback; | 62 delete callback; |
63 } | 63 } |
64 } | 64 } |
65 | 65 |
66 void AudioRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { | 66 void AudioRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { |
67 AutoLock auto_lock(lock_); | 67 base::AutoLock auto_lock(lock_); |
68 DCHECK_EQ(kPaused, state_); | 68 DCHECK_EQ(kPaused, state_); |
69 DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed"; | 69 DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed"; |
70 state_ = kSeeking; | 70 state_ = kSeeking; |
71 seek_callback_.reset(callback); | 71 seek_callback_.reset(callback); |
72 seek_timestamp_ = time; | 72 seek_timestamp_ = time; |
73 | 73 |
74 // Throw away everything and schedule our reads. | 74 // Throw away everything and schedule our reads. |
75 last_fill_buffer_time_ = base::TimeDelta(); | 75 last_fill_buffer_time_ = base::TimeDelta(); |
76 recieved_end_of_stream_ = false; | 76 recieved_end_of_stream_ = false; |
77 rendered_end_of_stream_ = false; | 77 rendered_end_of_stream_ = false; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 callback->Run(); | 122 callback->Run(); |
123 return; | 123 return; |
124 } | 124 } |
125 | 125 |
126 // Finally, execute the start callback. | 126 // Finally, execute the start callback. |
127 state_ = kPaused; | 127 state_ = kPaused; |
128 callback->Run(); | 128 callback->Run(); |
129 } | 129 } |
130 | 130 |
131 bool AudioRendererBase::HasEnded() { | 131 bool AudioRendererBase::HasEnded() { |
132 AutoLock auto_lock(lock_); | 132 base::AutoLock auto_lock(lock_); |
133 if (rendered_end_of_stream_) { | 133 if (rendered_end_of_stream_) { |
134 DCHECK(algorithm_->IsQueueEmpty()) | 134 DCHECK(algorithm_->IsQueueEmpty()) |
135 << "Audio queue should be empty if we have rendered end of stream"; | 135 << "Audio queue should be empty if we have rendered end of stream"; |
136 } | 136 } |
137 return recieved_end_of_stream_ && rendered_end_of_stream_; | 137 return recieved_end_of_stream_ && rendered_end_of_stream_; |
138 } | 138 } |
139 | 139 |
140 void AudioRendererBase::ConsumeAudioSamples(scoped_refptr<Buffer> buffer_in) { | 140 void AudioRendererBase::ConsumeAudioSamples(scoped_refptr<Buffer> buffer_in) { |
141 AutoLock auto_lock(lock_); | 141 base::AutoLock auto_lock(lock_); |
142 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying); | 142 DCHECK(state_ == kPaused || state_ == kSeeking || state_ == kPlaying); |
143 DCHECK_GT(pending_reads_, 0u); | 143 DCHECK_GT(pending_reads_, 0u); |
144 --pending_reads_; | 144 --pending_reads_; |
145 | 145 |
146 // TODO(scherkus): this happens due to a race, primarily because Stop() is a | 146 // TODO(scherkus): this happens due to a race, primarily because Stop() is a |
147 // synchronous call when it should be asynchronous and accept a callback. | 147 // synchronous call when it should be asynchronous and accept a callback. |
148 // Refer to http://crbug.com/16059 | 148 // Refer to http://crbug.com/16059 |
149 if (state_ == kStopped) { | 149 if (state_ == kStopped) { |
150 return; | 150 return; |
151 } | 151 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 | 184 |
185 uint32 AudioRendererBase::FillBuffer(uint8* dest, | 185 uint32 AudioRendererBase::FillBuffer(uint8* dest, |
186 uint32 dest_len, | 186 uint32 dest_len, |
187 const base::TimeDelta& playback_delay, | 187 const base::TimeDelta& playback_delay, |
188 bool buffers_empty) { | 188 bool buffers_empty) { |
189 // The timestamp of the last buffer written during the last call to | 189 // The timestamp of the last buffer written during the last call to |
190 // FillBuffer(). | 190 // FillBuffer(). |
191 base::TimeDelta last_fill_buffer_time; | 191 base::TimeDelta last_fill_buffer_time; |
192 size_t dest_written = 0; | 192 size_t dest_written = 0; |
193 { | 193 { |
194 AutoLock auto_lock(lock_); | 194 base::AutoLock auto_lock(lock_); |
195 | 195 |
196 // Mute audio by returning 0 when not playing. | 196 // Mute audio by returning 0 when not playing. |
197 if (state_ != kPlaying) { | 197 if (state_ != kPlaying) { |
198 // TODO(scherkus): To keep the audio hardware busy we write at most 8k of | 198 // TODO(scherkus): To keep the audio hardware busy we write at most 8k of |
199 // zeros. This gets around the tricky situation of pausing and resuming | 199 // zeros. This gets around the tricky situation of pausing and resuming |
200 // the audio IPC layer in Chrome. Ideally, we should return zero and then | 200 // the audio IPC layer in Chrome. Ideally, we should return zero and then |
201 // the subclass can restart the conversation. | 201 // the subclass can restart the conversation. |
202 const uint32 kZeroLength = 8192; | 202 const uint32 kZeroLength = 8192; |
203 dest_written = std::min(kZeroLength, dest_len); | 203 dest_written = std::min(kZeroLength, dest_len); |
204 memset(dest, 0, dest_written); | 204 memset(dest, 0, dest_written); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 | 269 |
270 void AudioRendererBase::SetPlaybackRate(float playback_rate) { | 270 void AudioRendererBase::SetPlaybackRate(float playback_rate) { |
271 algorithm_->set_playback_rate(playback_rate); | 271 algorithm_->set_playback_rate(playback_rate); |
272 } | 272 } |
273 | 273 |
274 float AudioRendererBase::GetPlaybackRate() { | 274 float AudioRendererBase::GetPlaybackRate() { |
275 return algorithm_->playback_rate(); | 275 return algorithm_->playback_rate(); |
276 } | 276 } |
277 | 277 |
278 } // namespace media | 278 } // namespace media |
OLD | NEW |