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 "content/renderer/media/audio_renderer_impl.h" | 5 #include "content/renderer/media/audio_renderer_impl.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "chrome/common/render_messages.h" | |
10 #include "chrome/common/render_messages_params.h" | |
11 #include "chrome/renderer/render_thread.h" | 9 #include "chrome/renderer/render_thread.h" |
| 10 #include "content/common/audio_messages.h" |
12 #include "content/renderer/render_view.h" | 11 #include "content/renderer/render_view.h" |
13 #include "media/base/filter_host.h" | 12 #include "media/base/filter_host.h" |
14 | 13 |
15 namespace { | 14 namespace { |
16 | 15 |
17 // We will try to fill 200 ms worth of audio samples in each packet. A round | 16 // We will try to fill 200 ms worth of audio samples in each packet. A round |
18 // trip latency for IPC messages are typically 10 ms, this should give us | 17 // trip latency for IPC messages are typically 10 ms, this should give us |
19 // plenty of time to avoid clicks. | 18 // plenty of time to avoid clicks. |
20 const int kMillisecondsPerPacket = 200; | 19 const int kMillisecondsPerPacket = 200; |
21 | 20 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 base::AutoLock auto_lock(lock_); | 201 base::AutoLock auto_lock(lock_); |
203 DCHECK(!pending_request_); | 202 DCHECK(!pending_request_); |
204 pending_request_ = true; | 203 pending_request_ = true; |
205 request_buffers_state_ = buffers_state; | 204 request_buffers_state_ = buffers_state; |
206 } | 205 } |
207 | 206 |
208 // Try to fill in the fulfill the packet request. | 207 // Try to fill in the fulfill the packet request. |
209 NotifyPacketReadyTask(); | 208 NotifyPacketReadyTask(); |
210 } | 209 } |
211 | 210 |
212 void AudioRendererImpl::OnStateChanged( | 211 void AudioRendererImpl::OnStateChanged(AudioStreamState state) { |
213 const ViewMsg_AudioStreamState_Params& state) { | |
214 DCHECK(MessageLoop::current() == io_loop_); | 212 DCHECK(MessageLoop::current() == io_loop_); |
215 | 213 |
216 base::AutoLock auto_lock(lock_); | 214 base::AutoLock auto_lock(lock_); |
217 if (stopped_) | 215 if (stopped_) |
218 return; | 216 return; |
219 | 217 |
220 switch (state.state) { | 218 switch (state) { |
221 case ViewMsg_AudioStreamState_Params::kError: | 219 case kAudioStreamError: |
222 // We receive this error if we counter an hardware error on the browser | 220 // We receive this error if we counter an hardware error on the browser |
223 // side. We can proceed with ignoring the audio stream. | 221 // side. We can proceed with ignoring the audio stream. |
224 // TODO(hclam): We need more handling of these kind of error. For example | 222 // 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 | 223 // 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. | 224 // nicely and report to demuxer that the whole audio stream is discarded. |
227 host()->DisableAudioRenderer(); | 225 host()->DisableAudioRenderer(); |
228 break; | 226 break; |
229 // TODO(hclam): handle these events. | 227 // TODO(hclam): handle these events. |
230 case ViewMsg_AudioStreamState_Params::kPlaying: | 228 case kAudioStreamPlaying: |
231 case ViewMsg_AudioStreamState_Params::kPaused: | 229 case kAudioStreamPaused: |
232 break; | 230 break; |
233 default: | 231 default: |
234 NOTREACHED(); | 232 NOTREACHED(); |
235 break; | 233 break; |
236 } | 234 } |
237 } | 235 } |
238 | 236 |
239 void AudioRendererImpl::OnVolume(double volume) { | 237 void AudioRendererImpl::OnVolume(double volume) { |
240 // TODO(hclam): decide whether we need to report the current volume to | 238 // TODO(hclam): decide whether we need to report the current volume to |
241 // pipeline. | 239 // pipeline. |
242 } | 240 } |
243 | 241 |
244 void AudioRendererImpl::CreateStreamTask(const AudioParameters& audio_params) { | 242 void AudioRendererImpl::CreateStreamTask(const AudioParameters& audio_params) { |
245 DCHECK(MessageLoop::current() == io_loop_); | 243 DCHECK(MessageLoop::current() == io_loop_); |
246 | 244 |
247 base::AutoLock auto_lock(lock_); | 245 base::AutoLock auto_lock(lock_); |
248 if (stopped_) | 246 if (stopped_) |
249 return; | 247 return; |
250 | 248 |
251 // Make sure we don't call create more than once. | 249 // Make sure we don't call create more than once. |
252 DCHECK_EQ(0, stream_id_); | 250 DCHECK_EQ(0, stream_id_); |
253 stream_id_ = filter_->AddDelegate(this); | 251 stream_id_ = filter_->AddDelegate(this); |
254 io_loop_->AddDestructionObserver(this); | 252 io_loop_->AddDestructionObserver(this); |
255 | 253 |
256 ViewHostMsg_Audio_CreateStream_Params params; | 254 AudioParameters params_to_send(audio_params); |
257 params.params = audio_params; | 255 // Let the browser choose packet size. |
| 256 params_to_send.samples_per_packet = 0; |
258 | 257 |
259 // Let the browser choose packet size. | 258 filter_->Send(new AudioHostMsg_CreateStream( |
260 params.params.samples_per_packet = 0; | 259 0, stream_id_, params_to_send, false)); |
261 | |
262 filter_->Send(new ViewHostMsg_CreateAudioStream(0, stream_id_, params, | |
263 false)); | |
264 } | 260 } |
265 | 261 |
266 void AudioRendererImpl::PlayTask() { | 262 void AudioRendererImpl::PlayTask() { |
267 DCHECK(MessageLoop::current() == io_loop_); | 263 DCHECK(MessageLoop::current() == io_loop_); |
268 | 264 |
269 filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_)); | 265 filter_->Send(new AudioHostMsg_PlayStream(0, stream_id_)); |
270 } | 266 } |
271 | 267 |
272 void AudioRendererImpl::PauseTask() { | 268 void AudioRendererImpl::PauseTask() { |
273 DCHECK(MessageLoop::current() == io_loop_); | 269 DCHECK(MessageLoop::current() == io_loop_); |
274 | 270 |
275 filter_->Send(new ViewHostMsg_PauseAudioStream(0, stream_id_)); | 271 filter_->Send(new AudioHostMsg_PauseStream(0, stream_id_)); |
276 } | 272 } |
277 | 273 |
278 void AudioRendererImpl::SeekTask() { | 274 void AudioRendererImpl::SeekTask() { |
279 DCHECK(MessageLoop::current() == io_loop_); | 275 DCHECK(MessageLoop::current() == io_loop_); |
280 | 276 |
281 // We have to pause the audio stream before we can flush. | 277 // We have to pause the audio stream before we can flush. |
282 filter_->Send(new ViewHostMsg_PauseAudioStream(0, stream_id_)); | 278 filter_->Send(new AudioHostMsg_PauseStream(0, stream_id_)); |
283 filter_->Send(new ViewHostMsg_FlushAudioStream(0, stream_id_)); | 279 filter_->Send(new AudioHostMsg_FlushStream(0, stream_id_)); |
284 } | 280 } |
285 | 281 |
286 void AudioRendererImpl::DestroyTask() { | 282 void AudioRendererImpl::DestroyTask() { |
287 DCHECK(MessageLoop::current() == io_loop_); | 283 DCHECK(MessageLoop::current() == io_loop_); |
288 | 284 |
289 // Make sure we don't call destroy more than once. | 285 // Make sure we don't call destroy more than once. |
290 DCHECK_NE(0, stream_id_); | 286 DCHECK_NE(0, stream_id_); |
291 filter_->RemoveDelegate(stream_id_); | 287 filter_->RemoveDelegate(stream_id_); |
292 filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); | 288 filter_->Send(new AudioHostMsg_CloseStream(0, stream_id_)); |
293 io_loop_->RemoveDestructionObserver(this); | 289 io_loop_->RemoveDestructionObserver(this); |
294 stream_id_ = 0; | 290 stream_id_ = 0; |
295 } | 291 } |
296 | 292 |
297 void AudioRendererImpl::SetVolumeTask(double volume) { | 293 void AudioRendererImpl::SetVolumeTask(double volume) { |
298 DCHECK(MessageLoop::current() == io_loop_); | 294 DCHECK(MessageLoop::current() == io_loop_); |
299 | 295 |
300 base::AutoLock auto_lock(lock_); | 296 base::AutoLock auto_lock(lock_); |
301 if (stopped_) | 297 if (stopped_) |
302 return; | 298 return; |
303 filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); | 299 filter_->Send(new AudioHostMsg_SetVolume(0, stream_id_, volume)); |
304 } | 300 } |
305 | 301 |
306 void AudioRendererImpl::NotifyPacketReadyTask() { | 302 void AudioRendererImpl::NotifyPacketReadyTask() { |
307 DCHECK(MessageLoop::current() == io_loop_); | 303 DCHECK(MessageLoop::current() == io_loop_); |
308 | 304 |
309 base::AutoLock auto_lock(lock_); | 305 base::AutoLock auto_lock(lock_); |
310 if (stopped_) | 306 if (stopped_) |
311 return; | 307 return; |
312 if (pending_request_ && GetPlaybackRate() > 0.0f) { | 308 if (pending_request_ && GetPlaybackRate() > 0.0f) { |
313 DCHECK(shared_memory_.get()); | 309 DCHECK(shared_memory_.get()); |
(...skipping 22 matching lines...) Expand all Loading... |
336 request_delay = base::TimeDelta::FromMicroseconds( | 332 request_delay = base::TimeDelta::FromMicroseconds( |
337 static_cast<int64>(ceil(request_delay.InMicroseconds() * | 333 static_cast<int64>(ceil(request_delay.InMicroseconds() * |
338 GetPlaybackRate()))); | 334 GetPlaybackRate()))); |
339 } | 335 } |
340 | 336 |
341 uint32 filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()), | 337 uint32 filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()), |
342 shared_memory_size_, request_delay, | 338 shared_memory_size_, request_delay, |
343 request_buffers_state_.pending_bytes == 0); | 339 request_buffers_state_.pending_bytes == 0); |
344 pending_request_ = false; | 340 pending_request_ = false; |
345 // Then tell browser process we are done filling into the buffer. | 341 // Then tell browser process we are done filling into the buffer. |
346 filter_->Send( | 342 filter_->Send(new AudioHostMsg_NotifyPacketReady(0, stream_id_, filled)); |
347 new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); | |
348 } | 343 } |
349 } | 344 } |
350 | 345 |
351 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { | 346 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { |
352 DCHECK(MessageLoop::current() == io_loop_); | 347 DCHECK(MessageLoop::current() == io_loop_); |
353 | 348 |
354 // We treat the IO loop going away the same as stopping. | 349 // We treat the IO loop going away the same as stopping. |
355 base::AutoLock auto_lock(lock_); | 350 base::AutoLock auto_lock(lock_); |
356 if (stopped_) | 351 if (stopped_) |
357 return; | 352 return; |
358 | 353 |
359 stopped_ = true; | 354 stopped_ = true; |
360 DestroyTask(); | 355 DestroyTask(); |
361 } | 356 } |
OLD | NEW |