| 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 |