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 "chrome/renderer/media/audio_renderer_impl.h" | 5 #include "chrome/renderer/media/audio_renderer_impl.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "chrome/common/render_messages_params.h" | 9 #include "chrome/common/render_messages_params.h" |
10 #include "chrome/renderer/audio_message_filter.h" | 10 #include "chrome/renderer/audio_message_filter.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 // Calculate the number of bytes per second using information of the stream. | 64 // Calculate the number of bytes per second using information of the stream. |
65 bytes_per_second_ = params_.sample_rate * params_.channels * | 65 bytes_per_second_ = params_.sample_rate * params_.channels * |
66 params_.bits_per_sample / 8; | 66 params_.bits_per_sample / 8; |
67 | 67 |
68 io_loop_->PostTask(FROM_HERE, | 68 io_loop_->PostTask(FROM_HERE, |
69 NewRunnableMethod(this, &AudioRendererImpl::CreateStreamTask, params_)); | 69 NewRunnableMethod(this, &AudioRendererImpl::CreateStreamTask, params_)); |
70 return true; | 70 return true; |
71 } | 71 } |
72 | 72 |
73 void AudioRendererImpl::OnStop() { | 73 void AudioRendererImpl::OnStop() { |
74 AutoLock auto_lock(lock_); | 74 base::AutoLock auto_lock(lock_); |
75 if (stopped_) | 75 if (stopped_) |
76 return; | 76 return; |
77 stopped_ = true; | 77 stopped_ = true; |
78 | 78 |
79 // We should never touch |io_loop_| after being stopped, so post our final | 79 // We should never touch |io_loop_| after being stopped, so post our final |
80 // task to clean up. | 80 // task to clean up. |
81 io_loop_->PostTask(FROM_HERE, | 81 io_loop_->PostTask(FROM_HERE, |
82 NewRunnableMethod(this, &AudioRendererImpl::DestroyTask)); | 82 NewRunnableMethod(this, &AudioRendererImpl::DestroyTask)); |
83 } | 83 } |
84 | 84 |
85 void AudioRendererImpl::ConsumeAudioSamples( | 85 void AudioRendererImpl::ConsumeAudioSamples( |
86 scoped_refptr<media::Buffer> buffer_in) { | 86 scoped_refptr<media::Buffer> buffer_in) { |
87 AutoLock auto_lock(lock_); | 87 base::AutoLock auto_lock(lock_); |
88 if (stopped_) | 88 if (stopped_) |
89 return; | 89 return; |
90 | 90 |
91 // TODO(hclam): handle end of stream here. | 91 // TODO(hclam): handle end of stream here. |
92 | 92 |
93 // Use the base class to queue the buffer. | 93 // Use the base class to queue the buffer. |
94 AudioRendererBase::ConsumeAudioSamples(buffer_in); | 94 AudioRendererBase::ConsumeAudioSamples(buffer_in); |
95 | 95 |
96 // Post a task to render thread to notify a packet reception. | 96 // Post a task to render thread to notify a packet reception. |
97 io_loop_->PostTask(FROM_HERE, | 97 io_loop_->PostTask(FROM_HERE, |
98 NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); | 98 NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); |
99 } | 99 } |
100 | 100 |
101 void AudioRendererImpl::SetPlaybackRate(float rate) { | 101 void AudioRendererImpl::SetPlaybackRate(float rate) { |
102 DCHECK(rate >= 0.0f); | 102 DCHECK(rate >= 0.0f); |
103 | 103 |
104 AutoLock auto_lock(lock_); | 104 base::AutoLock auto_lock(lock_); |
105 // Handle the case where we stopped due to |io_loop_| dying. | 105 // Handle the case where we stopped due to |io_loop_| dying. |
106 if (stopped_) { | 106 if (stopped_) { |
107 AudioRendererBase::SetPlaybackRate(rate); | 107 AudioRendererBase::SetPlaybackRate(rate); |
108 return; | 108 return; |
109 } | 109 } |
110 | 110 |
111 // We have two cases here: | 111 // We have two cases here: |
112 // Play: GetPlaybackRate() == 0.0 && rate != 0.0 | 112 // Play: GetPlaybackRate() == 0.0 && rate != 0.0 |
113 // Pause: GetPlaybackRate() != 0.0 && rate == 0.0 | 113 // Pause: GetPlaybackRate() != 0.0 && rate == 0.0 |
114 if (GetPlaybackRate() == 0.0f && rate != 0.0f) { | 114 if (GetPlaybackRate() == 0.0f && rate != 0.0f) { |
(...skipping 10 matching lines...) Expand all Loading... |
125 // the previous packet request may be stalled by a pause. | 125 // the previous packet request may be stalled by a pause. |
126 if (rate > 0.0f) { | 126 if (rate > 0.0f) { |
127 io_loop_->PostTask( | 127 io_loop_->PostTask( |
128 FROM_HERE, | 128 FROM_HERE, |
129 NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); | 129 NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); |
130 } | 130 } |
131 } | 131 } |
132 | 132 |
133 void AudioRendererImpl::Pause(media::FilterCallback* callback) { | 133 void AudioRendererImpl::Pause(media::FilterCallback* callback) { |
134 AudioRendererBase::Pause(callback); | 134 AudioRendererBase::Pause(callback); |
135 AutoLock auto_lock(lock_); | 135 base::AutoLock auto_lock(lock_); |
136 if (stopped_) | 136 if (stopped_) |
137 return; | 137 return; |
138 | 138 |
139 io_loop_->PostTask(FROM_HERE, | 139 io_loop_->PostTask(FROM_HERE, |
140 NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); | 140 NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); |
141 } | 141 } |
142 | 142 |
143 void AudioRendererImpl::Seek(base::TimeDelta time, | 143 void AudioRendererImpl::Seek(base::TimeDelta time, |
144 media::FilterCallback* callback) { | 144 media::FilterCallback* callback) { |
145 AudioRendererBase::Seek(time, callback); | 145 AudioRendererBase::Seek(time, callback); |
146 AutoLock auto_lock(lock_); | 146 base::AutoLock auto_lock(lock_); |
147 if (stopped_) | 147 if (stopped_) |
148 return; | 148 return; |
149 | 149 |
150 io_loop_->PostTask(FROM_HERE, | 150 io_loop_->PostTask(FROM_HERE, |
151 NewRunnableMethod(this, &AudioRendererImpl::SeekTask)); | 151 NewRunnableMethod(this, &AudioRendererImpl::SeekTask)); |
152 } | 152 } |
153 | 153 |
154 | 154 |
155 void AudioRendererImpl::Play(media::FilterCallback* callback) { | 155 void AudioRendererImpl::Play(media::FilterCallback* callback) { |
156 AudioRendererBase::Play(callback); | 156 AudioRendererBase::Play(callback); |
157 AutoLock auto_lock(lock_); | 157 base::AutoLock auto_lock(lock_); |
158 if (stopped_) | 158 if (stopped_) |
159 return; | 159 return; |
160 | 160 |
161 if (GetPlaybackRate() != 0.0f) { | 161 if (GetPlaybackRate() != 0.0f) { |
162 io_loop_->PostTask(FROM_HERE, | 162 io_loop_->PostTask(FROM_HERE, |
163 NewRunnableMethod(this, &AudioRendererImpl::PlayTask)); | 163 NewRunnableMethod(this, &AudioRendererImpl::PlayTask)); |
164 } else { | 164 } else { |
165 io_loop_->PostTask(FROM_HERE, | 165 io_loop_->PostTask(FROM_HERE, |
166 NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); | 166 NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); |
167 } | 167 } |
168 } | 168 } |
169 | 169 |
170 void AudioRendererImpl::SetVolume(float volume) { | 170 void AudioRendererImpl::SetVolume(float volume) { |
171 AutoLock auto_lock(lock_); | 171 base::AutoLock auto_lock(lock_); |
172 if (stopped_) | 172 if (stopped_) |
173 return; | 173 return; |
174 io_loop_->PostTask(FROM_HERE, | 174 io_loop_->PostTask(FROM_HERE, |
175 NewRunnableMethod( | 175 NewRunnableMethod( |
176 this, &AudioRendererImpl::SetVolumeTask, volume)); | 176 this, &AudioRendererImpl::SetVolumeTask, volume)); |
177 } | 177 } |
178 | 178 |
179 void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle, | 179 void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle, |
180 uint32 length) { | 180 uint32 length) { |
181 DCHECK(MessageLoop::current() == io_loop_); | 181 DCHECK(MessageLoop::current() == io_loop_); |
182 | 182 |
183 AutoLock auto_lock(lock_); | 183 base::AutoLock auto_lock(lock_); |
184 if (stopped_) | 184 if (stopped_) |
185 return; | 185 return; |
186 | 186 |
187 shared_memory_.reset(new base::SharedMemory(handle, false)); | 187 shared_memory_.reset(new base::SharedMemory(handle, false)); |
188 shared_memory_->Map(length); | 188 shared_memory_->Map(length); |
189 shared_memory_size_ = length; | 189 shared_memory_size_ = length; |
190 } | 190 } |
191 | 191 |
192 void AudioRendererImpl::OnLowLatencyCreated(base::SharedMemoryHandle, | 192 void AudioRendererImpl::OnLowLatencyCreated(base::SharedMemoryHandle, |
193 base::SyncSocket::Handle, uint32) { | 193 base::SyncSocket::Handle, uint32) { |
194 // AudioRenderer should not have a low-latency audio channel. | 194 // AudioRenderer should not have a low-latency audio channel. |
195 NOTREACHED(); | 195 NOTREACHED(); |
196 } | 196 } |
197 | 197 |
198 void AudioRendererImpl::OnRequestPacket(AudioBuffersState buffers_state) { | 198 void AudioRendererImpl::OnRequestPacket(AudioBuffersState buffers_state) { |
199 DCHECK(MessageLoop::current() == io_loop_); | 199 DCHECK(MessageLoop::current() == io_loop_); |
200 | 200 |
201 { | 201 { |
202 AutoLock auto_lock(lock_); | 202 base::AutoLock auto_lock(lock_); |
203 DCHECK(!pending_request_); | 203 DCHECK(!pending_request_); |
204 pending_request_ = true; | 204 pending_request_ = true; |
205 request_buffers_state_ = buffers_state; | 205 request_buffers_state_ = buffers_state; |
206 } | 206 } |
207 | 207 |
208 // Try to fill in the fulfill the packet request. | 208 // Try to fill in the fulfill the packet request. |
209 NotifyPacketReadyTask(); | 209 NotifyPacketReadyTask(); |
210 } | 210 } |
211 | 211 |
212 void AudioRendererImpl::OnStateChanged( | 212 void AudioRendererImpl::OnStateChanged( |
213 const ViewMsg_AudioStreamState_Params& state) { | 213 const ViewMsg_AudioStreamState_Params& state) { |
214 DCHECK(MessageLoop::current() == io_loop_); | 214 DCHECK(MessageLoop::current() == io_loop_); |
215 | 215 |
216 AutoLock auto_lock(lock_); | 216 base::AutoLock auto_lock(lock_); |
217 if (stopped_) | 217 if (stopped_) |
218 return; | 218 return; |
219 | 219 |
220 switch (state.state) { | 220 switch (state.state) { |
221 case ViewMsg_AudioStreamState_Params::kError: | 221 case ViewMsg_AudioStreamState_Params::kError: |
222 // We receive this error if we counter an hardware error on the browser | 222 // We receive this error if we counter an hardware error on the browser |
223 // side. We can proceed with ignoring the audio stream. | 223 // side. We can proceed with ignoring the audio stream. |
224 // TODO(hclam): We need more handling of these kind of error. For example | 224 // TODO(hclam): We need more handling of these kind of error. For example |
225 // re-try creating the audio output stream on the browser side or fail | 225 // re-try creating the audio output stream on the browser side or fail |
226 // nicely and report to demuxer that the whole audio stream is discarded. | 226 // nicely and report to demuxer that the whole audio stream is discarded. |
(...skipping 10 matching lines...) Expand all Loading... |
237 } | 237 } |
238 | 238 |
239 void AudioRendererImpl::OnVolume(double volume) { | 239 void AudioRendererImpl::OnVolume(double volume) { |
240 // TODO(hclam): decide whether we need to report the current volume to | 240 // TODO(hclam): decide whether we need to report the current volume to |
241 // pipeline. | 241 // pipeline. |
242 } | 242 } |
243 | 243 |
244 void AudioRendererImpl::CreateStreamTask(AudioParameters audio_params) { | 244 void AudioRendererImpl::CreateStreamTask(AudioParameters audio_params) { |
245 DCHECK(MessageLoop::current() == io_loop_); | 245 DCHECK(MessageLoop::current() == io_loop_); |
246 | 246 |
247 AutoLock auto_lock(lock_); | 247 base::AutoLock auto_lock(lock_); |
248 if (stopped_) | 248 if (stopped_) |
249 return; | 249 return; |
250 | 250 |
251 // Make sure we don't call create more than once. | 251 // Make sure we don't call create more than once. |
252 DCHECK_EQ(0, stream_id_); | 252 DCHECK_EQ(0, stream_id_); |
253 stream_id_ = filter_->AddDelegate(this); | 253 stream_id_ = filter_->AddDelegate(this); |
254 io_loop_->AddDestructionObserver(this); | 254 io_loop_->AddDestructionObserver(this); |
255 | 255 |
256 ViewHostMsg_Audio_CreateStream_Params params; | 256 ViewHostMsg_Audio_CreateStream_Params params; |
257 params.params = audio_params; | 257 params.params = audio_params; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 DCHECK_NE(0, stream_id_); | 290 DCHECK_NE(0, stream_id_); |
291 filter_->RemoveDelegate(stream_id_); | 291 filter_->RemoveDelegate(stream_id_); |
292 filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); | 292 filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); |
293 io_loop_->RemoveDestructionObserver(this); | 293 io_loop_->RemoveDestructionObserver(this); |
294 stream_id_ = 0; | 294 stream_id_ = 0; |
295 } | 295 } |
296 | 296 |
297 void AudioRendererImpl::SetVolumeTask(double volume) { | 297 void AudioRendererImpl::SetVolumeTask(double volume) { |
298 DCHECK(MessageLoop::current() == io_loop_); | 298 DCHECK(MessageLoop::current() == io_loop_); |
299 | 299 |
300 AutoLock auto_lock(lock_); | 300 base::AutoLock auto_lock(lock_); |
301 if (stopped_) | 301 if (stopped_) |
302 return; | 302 return; |
303 filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); | 303 filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); |
304 } | 304 } |
305 | 305 |
306 void AudioRendererImpl::NotifyPacketReadyTask() { | 306 void AudioRendererImpl::NotifyPacketReadyTask() { |
307 DCHECK(MessageLoop::current() == io_loop_); | 307 DCHECK(MessageLoop::current() == io_loop_); |
308 | 308 |
309 AutoLock auto_lock(lock_); | 309 base::AutoLock auto_lock(lock_); |
310 if (stopped_) | 310 if (stopped_) |
311 return; | 311 return; |
312 if (pending_request_ && GetPlaybackRate() > 0.0f) { | 312 if (pending_request_ && GetPlaybackRate() > 0.0f) { |
313 DCHECK(shared_memory_.get()); | 313 DCHECK(shared_memory_.get()); |
314 | 314 |
315 // Adjust the playback delay. | 315 // Adjust the playback delay. |
316 base::Time current_time = base::Time::Now(); | 316 base::Time current_time = base::Time::Now(); |
317 | 317 |
318 base::TimeDelta request_delay = | 318 base::TimeDelta request_delay = |
319 ConvertToDuration(request_buffers_state_.total_bytes()); | 319 ConvertToDuration(request_buffers_state_.total_bytes()); |
(...skipping 25 matching lines...) Expand all Loading... |
345 // Then tell browser process we are done filling into the buffer. | 345 // Then tell browser process we are done filling into the buffer. |
346 filter_->Send( | 346 filter_->Send( |
347 new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); | 347 new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); |
348 } | 348 } |
349 } | 349 } |
350 | 350 |
351 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { | 351 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { |
352 DCHECK(MessageLoop::current() == io_loop_); | 352 DCHECK(MessageLoop::current() == io_loop_); |
353 | 353 |
354 // We treat the IO loop going away the same as stopping. | 354 // We treat the IO loop going away the same as stopping. |
355 AutoLock auto_lock(lock_); | 355 base::AutoLock auto_lock(lock_); |
356 if (stopped_) | 356 if (stopped_) |
357 return; | 357 return; |
358 | 358 |
359 stopped_ = true; | 359 stopped_ = true; |
360 DestroyTask(); | 360 DestroyTask(); |
361 } | 361 } |
OLD | NEW |