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/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 const url::Origin& security_origin) | 180 const url::Origin& security_origin) |
181 : state_(UNINITIALIZED), | 181 : state_(UNINITIALIZED), |
182 source_render_frame_id_(source_render_frame_id), | 182 source_render_frame_id_(source_render_frame_id), |
183 session_id_(session_id), | 183 session_id_(session_id), |
184 signaling_thread_(signaling_thread), | 184 signaling_thread_(signaling_thread), |
185 media_stream_(media_stream), | 185 media_stream_(media_stream), |
186 source_(NULL), | 186 source_(NULL), |
187 play_ref_count_(0), | 187 play_ref_count_(0), |
188 start_ref_count_(0), | 188 start_ref_count_(0), |
189 audio_delay_milliseconds_(0), | 189 audio_delay_milliseconds_(0), |
190 fifo_delay_milliseconds_(0), | |
191 sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 190 sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
192 media::CHANNEL_LAYOUT_STEREO, | 191 media::CHANNEL_LAYOUT_STEREO, |
193 0, | 192 0, |
194 16, | 193 16, |
195 0), | 194 0), |
196 output_device_id_(device_id), | 195 output_device_id_(device_id), |
197 security_origin_(security_origin), | 196 security_origin_(security_origin), |
198 render_callback_count_(0) { | 197 render_callback_count_(0) { |
199 WebRtcLogMessage(base::StringPrintf( | 198 WebRtcLogMessage(base::StringPrintf( |
200 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", | 199 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 base::AutoLock auto_lock(lock_); | 426 base::AutoLock auto_lock(lock_); |
428 if (!source_) | 427 if (!source_) |
429 return 0; | 428 return 0; |
430 | 429 |
431 DVLOG(2) << "WebRtcAudioRenderer::Render()"; | 430 DVLOG(2) << "WebRtcAudioRenderer::Render()"; |
432 DVLOG(2) << "audio_delay_milliseconds: " << audio_delay_milliseconds; | 431 DVLOG(2) << "audio_delay_milliseconds: " << audio_delay_milliseconds; |
433 | 432 |
434 DCHECK_LE(audio_delay_milliseconds, static_cast<uint32_t>(INT_MAX)); | 433 DCHECK_LE(audio_delay_milliseconds, static_cast<uint32_t>(INT_MAX)); |
435 audio_delay_milliseconds_ = static_cast<int>(audio_delay_milliseconds); | 434 audio_delay_milliseconds_ = static_cast<int>(audio_delay_milliseconds); |
436 | 435 |
436 // If there are skipped frames, pull and throw away the same amount. | |
437 if (frames_skipped > 0) { | |
438 const uint32_t frames_per_10ms = | |
439 static_cast<uint32_t>(sink_params_.sample_rate() / 100); | |
440 if (!audio_fifo_ && frames_skipped != frames_per_10ms) { | |
441 audio_fifo_.reset(new media::AudioPullFifo( | |
442 sink_params_.channels(), frames_per_10ms, | |
443 base::Bind(&WebRtcAudioRenderer::SourceCallback, | |
444 base::Unretained(this)))); | |
445 } | |
446 | |
447 scoped_ptr<media::AudioBus> drop_bus = | |
448 media::AudioBus::Create(audio_bus->channels(), frames_skipped); | |
449 if (audio_fifo_) | |
450 audio_fifo_->Consume(drop_bus.get(), drop_bus->frames()); | |
451 else | |
452 SourceCallback(0, drop_bus.get()); | |
453 } | |
454 | |
455 // Pull the data we shall deliver. | |
tommi (sloooow) - chröme
2016/01/15 18:50:03
nit: s/shall/will
Henrik Grunell
2016/01/18 13:00:54
Done.
| |
437 if (audio_fifo_) | 456 if (audio_fifo_) |
438 audio_fifo_->Consume(audio_bus, audio_bus->frames()); | 457 audio_fifo_->Consume(audio_bus, audio_bus->frames()); |
439 else | 458 else |
440 SourceCallback(0, audio_bus); | 459 SourceCallback(0, audio_bus); |
441 | 460 |
442 return (state_ == PLAYING) ? audio_bus->frames() : 0; | 461 return (state_ == PLAYING) ? audio_bus->frames() : 0; |
443 } | 462 } |
444 | 463 |
445 void WebRtcAudioRenderer::OnRenderError() { | 464 void WebRtcAudioRenderer::OnRenderError() { |
446 NOTIMPLEMENTED(); | 465 NOTIMPLEMENTED(); |
447 LOG(ERROR) << "OnRenderError()"; | 466 LOG(ERROR) << "OnRenderError()"; |
448 } | 467 } |
449 | 468 |
450 // Called by AudioPullFifo when more data is necessary. | 469 // Called by AudioPullFifo when more data is necessary. |
451 void WebRtcAudioRenderer::SourceCallback( | 470 void WebRtcAudioRenderer::SourceCallback( |
452 int fifo_frame_delay, media::AudioBus* audio_bus) { | 471 int fifo_frame_delay, media::AudioBus* audio_bus) { |
453 DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); | 472 DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); |
454 base::TimeTicks start_time = base::TimeTicks::Now(); | 473 base::TimeTicks start_time = base::TimeTicks::Now(); |
455 DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" | 474 DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" |
456 << fifo_frame_delay << ", " | 475 << fifo_frame_delay << ", " |
457 << audio_bus->frames() << ")"; | 476 << audio_bus->frames() << ")"; |
458 | 477 |
459 int output_delay_milliseconds = audio_delay_milliseconds_; | 478 int output_delay_milliseconds = audio_delay_milliseconds_; |
460 output_delay_milliseconds += fifo_delay_milliseconds_; | 479 output_delay_milliseconds += fifo_frame_delay * |
480 base::Time::kMillisecondsPerSecond / | |
481 sink_params_.sample_rate(); | |
461 DVLOG(2) << "output_delay_milliseconds: " << output_delay_milliseconds; | 482 DVLOG(2) << "output_delay_milliseconds: " << output_delay_milliseconds; |
462 | 483 |
463 // We need to keep render data for the |source_| regardless of |state_|, | 484 // We need to keep render data for the |source_| regardless of |state_|, |
464 // otherwise the data will be buffered up inside |source_|. | 485 // otherwise the data will be buffered up inside |source_|. |
465 source_->RenderData(audio_bus, sink_params_.sample_rate(), | 486 source_->RenderData(audio_bus, sink_params_.sample_rate(), |
466 output_delay_milliseconds, | 487 output_delay_milliseconds, |
467 ¤t_time_); | 488 ¤t_time_); |
468 | 489 |
469 // Avoid filling up the audio bus if we are not playing; instead | 490 // Avoid filling up the audio bus if we are not playing; instead |
470 // return here and ensure that the returned value in Render() is 0. | 491 // return here and ensure that the returned value in Render() is 0. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
620 const int frames_per_buffer = GetOptimalBufferSize( | 641 const int frames_per_buffer = GetOptimalBufferSize( |
621 sample_rate, sink_->GetOutputParameters().frames_per_buffer()); | 642 sample_rate, sink_->GetOutputParameters().frames_per_buffer()); |
622 | 643 |
623 new_sink_params.Reset( | 644 new_sink_params.Reset( |
624 new_sink_params.format(), new_sink_params.channel_layout(), | 645 new_sink_params.format(), new_sink_params.channel_layout(), |
625 sample_rate, 16, frames_per_buffer); | 646 sample_rate, 16, frames_per_buffer); |
626 | 647 |
627 // Create a FIFO if re-buffering is required to match the source input with | 648 // Create a FIFO if re-buffering is required to match the source input with |
628 // the sink request. The source acts as provider here and the sink as | 649 // the sink request. The source acts as provider here and the sink as |
629 // consumer. | 650 // consumer. |
630 int new_fifo_delay_milliseconds = 0; | |
631 scoped_ptr<media::AudioPullFifo> new_audio_fifo; | 651 scoped_ptr<media::AudioPullFifo> new_audio_fifo; |
632 if (source_params.frames_per_buffer() != | 652 DCHECK_EQ(source_params.channels(), |
633 new_sink_params.frames_per_buffer()) { | 653 media::ChannelLayoutToChannelCount(media::CHANNEL_LAYOUT_STEREO)); |
tommi (sloooow) - chröme
2016/01/15 18:50:03
new assumption or did the previous code assume thi
Henrik Grunell
2016/01/18 13:00:54
Actually, the assumption is that source and sink o
| |
654 const bool different_source_sink_frames = | |
655 source_params.frames_per_buffer() != new_sink_params.frames_per_buffer(); | |
656 if (different_source_sink_frames) { | |
634 DVLOG(1) << "Rebuffering from " << source_params.frames_per_buffer() | 657 DVLOG(1) << "Rebuffering from " << source_params.frames_per_buffer() |
635 << " to " << new_sink_params.frames_per_buffer(); | 658 << " to " << new_sink_params.frames_per_buffer(); |
636 new_audio_fifo.reset(new media::AudioPullFifo( | |
637 source_params.channels(), source_params.frames_per_buffer(), | |
638 base::Bind(&WebRtcAudioRenderer::SourceCallback, | |
639 base::Unretained(this)))); | |
640 | |
641 if (new_sink_params.frames_per_buffer() > | |
642 source_params.frames_per_buffer()) { | |
643 int frame_duration_milliseconds = | |
644 base::Time::kMillisecondsPerSecond / | |
645 static_cast<double>(source_params.sample_rate()); | |
646 new_fifo_delay_milliseconds = (new_sink_params.frames_per_buffer() - | |
647 source_params.frames_per_buffer()) * | |
648 frame_duration_milliseconds; | |
649 } | |
650 } | 659 } |
651 | 660 |
652 { | 661 { |
653 base::AutoLock lock(lock_); | 662 base::AutoLock lock(lock_); |
663 const bool source_frames_changed = | |
664 audio_fifo_->SizeInFrames() != source_params.frames_per_buffer(); | |
665 if ((!audio_fifo_ && different_source_sink_frames) || | |
666 (audio_fifo_ && source_frames_changed)) { | |
667 audio_fifo_.reset(new media::AudioPullFifo( | |
668 source_params.channels(), source_params.frames_per_buffer(), | |
669 base::Bind(&WebRtcAudioRenderer::SourceCallback, | |
670 base::Unretained(this)))); | |
671 } | |
654 sink_params_ = new_sink_params; | 672 sink_params_ = new_sink_params; |
655 fifo_delay_milliseconds_ = new_fifo_delay_milliseconds; | |
656 if (new_audio_fifo.get()) | |
657 audio_fifo_ = std::move(new_audio_fifo); | |
658 } | 673 } |
659 | 674 |
660 sink_->Initialize(new_sink_params, this); | 675 sink_->Initialize(new_sink_params, this); |
661 } | 676 } |
662 | 677 |
663 } // namespace content | 678 } // namespace content |
OLD | NEW |