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 "content/renderer/media/webrtc_audio_renderer.h" | 5 #include "content/renderer/media/webrtc_audio_renderer.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 play_ref_count_(0), | 201 play_ref_count_(0), |
202 start_ref_count_(0), | 202 start_ref_count_(0), |
203 audio_delay_milliseconds_(0), | 203 audio_delay_milliseconds_(0), |
204 sink_params_(kFormat, kChannelLayout, 0, kBitsPerSample, 0), | 204 sink_params_(kFormat, kChannelLayout, 0, kBitsPerSample, 0), |
205 output_device_id_(device_id), | 205 output_device_id_(device_id), |
206 security_origin_(security_origin), | 206 security_origin_(security_origin), |
207 render_callback_count_(0) { | 207 render_callback_count_(0) { |
208 WebRtcLogMessage(base::StringPrintf( | 208 WebRtcLogMessage(base::StringPrintf( |
209 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", | 209 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", |
210 source_render_frame_id, session_id, sink_params_.effects())); | 210 source_render_frame_id, session_id, sink_params_.effects())); |
211 audio_renderer_thread_checker_.DetachFromThread(); | |
212 } | 211 } |
213 | 212 |
214 WebRtcAudioRenderer::~WebRtcAudioRenderer() { | 213 WebRtcAudioRenderer::~WebRtcAudioRenderer() { |
215 DCHECK(thread_checker_.CalledOnValidThread()); | 214 DCHECK(thread_checker_.CalledOnValidThread()); |
216 DCHECK_EQ(state_, UNINITIALIZED); | 215 DCHECK_EQ(state_, UNINITIALIZED); |
217 } | 216 } |
218 | 217 |
219 bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { | 218 bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { |
220 DVLOG(1) << "WebRtcAudioRenderer::Initialize()"; | 219 DVLOG(1) << "WebRtcAudioRenderer::Initialize()"; |
221 DCHECK(thread_checker_.CalledOnValidThread()); | 220 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 11 matching lines...) Expand all Loading... |
233 output_device_id_, security_origin_); | 232 output_device_id_, security_origin_); |
234 | 233 |
235 if (sink_->GetOutputDeviceInfo().device_status() != | 234 if (sink_->GetOutputDeviceInfo().device_status() != |
236 media::OUTPUT_DEVICE_STATUS_OK) { | 235 media::OUTPUT_DEVICE_STATUS_OK) { |
237 return false; | 236 return false; |
238 } | 237 } |
239 | 238 |
240 PrepareSink(); | 239 PrepareSink(); |
241 { | 240 { |
242 // No need to reassert the preconditions because the other thread accessing | 241 // No need to reassert the preconditions because the other thread accessing |
243 // the fields (checked by |audio_renderer_thread_checker_|) only reads them. | 242 // the fields only reads them. |
244 base::AutoLock auto_lock(lock_); | 243 base::AutoLock auto_lock(lock_); |
245 source_ = source; | 244 source_ = source; |
246 | 245 |
247 // User must call Play() before any audio can be heard. | 246 // User must call Play() before any audio can be heard. |
248 state_ = PAUSED; | 247 state_ = PAUSED; |
249 } | 248 } |
250 sink_->Start(); | 249 sink_->Start(); |
251 sink_->Play(); // Not all the sinks play on start. | 250 sink_->Play(); // Not all the sinks play on start. |
252 | 251 |
253 return true; | 252 return true; |
254 } | 253 } |
255 | 254 |
256 scoped_refptr<MediaStreamAudioRenderer> | 255 scoped_refptr<MediaStreamAudioRenderer> |
257 WebRtcAudioRenderer::CreateSharedAudioRendererProxy( | 256 WebRtcAudioRenderer::CreateSharedAudioRendererProxy( |
258 const blink::WebMediaStream& media_stream) { | 257 const blink::WebMediaStream& media_stream) { |
259 content::SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = | 258 content::SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = |
260 base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); | 259 base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); |
261 return new SharedAudioRenderer(this, media_stream, on_play_state_changed); | 260 return new SharedAudioRenderer(this, media_stream, on_play_state_changed); |
262 } | 261 } |
263 | 262 |
264 bool WebRtcAudioRenderer::IsStarted() const { | 263 bool WebRtcAudioRenderer::IsStarted() const { |
265 DCHECK(thread_checker_.CalledOnValidThread()); | 264 DCHECK(thread_checker_.CalledOnValidThread()); |
266 return start_ref_count_ != 0; | 265 return start_ref_count_ != 0; |
267 } | 266 } |
268 | 267 |
| 268 bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() { |
| 269 return sink_->CurrentThreadIsRenderingThread(); |
| 270 } |
| 271 |
269 void WebRtcAudioRenderer::Start() { | 272 void WebRtcAudioRenderer::Start() { |
270 DVLOG(1) << "WebRtcAudioRenderer::Start()"; | 273 DVLOG(1) << "WebRtcAudioRenderer::Start()"; |
271 DCHECK(thread_checker_.CalledOnValidThread()); | 274 DCHECK(thread_checker_.CalledOnValidThread()); |
272 ++start_ref_count_; | 275 ++start_ref_count_; |
273 } | 276 } |
274 | 277 |
275 void WebRtcAudioRenderer::Play() { | 278 void WebRtcAudioRenderer::Play() { |
276 DVLOG(1) << "WebRtcAudioRenderer::Play()"; | 279 DVLOG(1) << "WebRtcAudioRenderer::Play()"; |
277 DCHECK(thread_checker_.CalledOnValidThread()); | 280 DCHECK(thread_checker_.CalledOnValidThread()); |
278 | 281 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 new_sink->GetOutputDeviceInfo().device_status(); | 402 new_sink->GetOutputDeviceInfo().device_status(); |
400 if (status != media::OUTPUT_DEVICE_STATUS_OK) { | 403 if (status != media::OUTPUT_DEVICE_STATUS_OK) { |
401 callback.Run(status); | 404 callback.Run(status); |
402 return; | 405 return; |
403 } | 406 } |
404 | 407 |
405 // Make sure to stop the sink while _not_ holding the lock since the Render() | 408 // Make sure to stop the sink while _not_ holding the lock since the Render() |
406 // callback may currently be executing and trying to grab the lock while we're | 409 // callback may currently be executing and trying to grab the lock while we're |
407 // stopping the thread on which it runs. | 410 // stopping the thread on which it runs. |
408 sink_->Stop(); | 411 sink_->Stop(); |
409 audio_renderer_thread_checker_.DetachFromThread(); | |
410 sink_ = new_sink; | 412 sink_ = new_sink; |
411 output_device_id_ = device_id; | 413 output_device_id_ = device_id; |
412 security_origin_ = security_origin; | 414 security_origin_ = security_origin; |
413 { | 415 { |
414 base::AutoLock auto_lock(lock_); | 416 base::AutoLock auto_lock(lock_); |
415 source_->AudioRendererThreadStopped(); | 417 source_->AudioRendererThreadStopped(); |
416 } | 418 } |
417 PrepareSink(); | 419 PrepareSink(); |
418 sink_->Start(); | 420 sink_->Start(); |
419 | 421 |
420 callback.Run(media::OUTPUT_DEVICE_STATUS_OK); | 422 callback.Run(media::OUTPUT_DEVICE_STATUS_OK); |
421 } | 423 } |
422 | 424 |
423 int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus, | 425 int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus, |
424 uint32_t frames_delayed, | 426 uint32_t frames_delayed, |
425 uint32_t frames_skipped) { | 427 uint32_t frames_skipped) { |
426 DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); | 428 DCHECK(sink_->CurrentThreadIsRenderingThread()); |
427 base::AutoLock auto_lock(lock_); | 429 base::AutoLock auto_lock(lock_); |
428 if (!source_) | 430 if (!source_) |
429 return 0; | 431 return 0; |
430 | 432 |
431 // TODO(grunell): Converting from frames to milliseconds will potentially lose | 433 // TODO(grunell): Converting from frames to milliseconds will potentially lose |
432 // hundreds of microseconds which may cause audio video drift. Update | 434 // hundreds of microseconds which may cause audio video drift. Update |
433 // this class and all usage of render delay msec -> frames (possibly even | 435 // this class and all usage of render delay msec -> frames (possibly even |
434 // using a double type for frames). See http://crbug.com/586540 | 436 // using a double type for frames). See http://crbug.com/586540 |
435 uint32_t audio_delay_milliseconds = static_cast<double>(frames_delayed) * | 437 uint32_t audio_delay_milliseconds = static_cast<double>(frames_delayed) * |
436 base::Time::kMillisecondsPerSecond / | 438 base::Time::kMillisecondsPerSecond / |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 } | 475 } |
474 | 476 |
475 void WebRtcAudioRenderer::OnRenderError() { | 477 void WebRtcAudioRenderer::OnRenderError() { |
476 NOTIMPLEMENTED(); | 478 NOTIMPLEMENTED(); |
477 LOG(ERROR) << "OnRenderError()"; | 479 LOG(ERROR) << "OnRenderError()"; |
478 } | 480 } |
479 | 481 |
480 // Called by AudioPullFifo when more data is necessary. | 482 // Called by AudioPullFifo when more data is necessary. |
481 void WebRtcAudioRenderer::SourceCallback( | 483 void WebRtcAudioRenderer::SourceCallback( |
482 int fifo_frame_delay, media::AudioBus* audio_bus) { | 484 int fifo_frame_delay, media::AudioBus* audio_bus) { |
483 DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); | 485 DCHECK(sink_->CurrentThreadIsRenderingThread()); |
484 base::TimeTicks start_time = base::TimeTicks::Now(); | 486 base::TimeTicks start_time = base::TimeTicks::Now(); |
485 DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" | 487 DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" |
486 << fifo_frame_delay << ", " | 488 << fifo_frame_delay << ", " |
487 << audio_bus->frames() << ")"; | 489 << audio_bus->frames() << ")"; |
488 | 490 |
489 int output_delay_milliseconds = audio_delay_milliseconds_; | 491 int output_delay_milliseconds = audio_delay_milliseconds_; |
490 // TODO(grunell): This integer division by sample_rate will cause loss of | 492 // TODO(grunell): This integer division by sample_rate will cause loss of |
491 // partial milliseconds, and may cause avsync drift. http://crbug.com/586540 | 493 // partial milliseconds, and may cause avsync drift. http://crbug.com/586540 |
492 output_delay_milliseconds += fifo_frame_delay * | 494 output_delay_milliseconds += fifo_frame_delay * |
493 base::Time::kMillisecondsPerSecond / | 495 base::Time::kMillisecondsPerSecond / |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 base::Bind(&WebRtcAudioRenderer::SourceCallback, | 679 base::Bind(&WebRtcAudioRenderer::SourceCallback, |
678 base::Unretained(this)))); | 680 base::Unretained(this)))); |
679 } | 681 } |
680 sink_params_ = new_sink_params; | 682 sink_params_ = new_sink_params; |
681 } | 683 } |
682 | 684 |
683 sink_->Initialize(new_sink_params, this); | 685 sink_->Initialize(new_sink_params, this); |
684 } | 686 } |
685 | 687 |
686 } // namespace content | 688 } // namespace content |
OLD | NEW |