Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Side by Side Diff: content/renderer/media/webrtc_audio_renderer.cc

Issue 1809093003: Moving SwitchOutputDevice out of OutputDevice interface, eliminating OutputDevice (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing guidou's comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 delegate_->Stop(); 111 delegate_->Stop();
112 } 112 }
113 113
114 void SetVolume(float volume) override { 114 void SetVolume(float volume) override {
115 DCHECK(thread_checker_.CalledOnValidThread()); 115 DCHECK(thread_checker_.CalledOnValidThread());
116 DCHECK(volume >= 0.0f && volume <= 1.0f); 116 DCHECK(volume >= 0.0f && volume <= 1.0f);
117 playing_state_.set_volume(volume); 117 playing_state_.set_volume(volume);
118 on_play_state_changed_.Run(media_stream_, &playing_state_); 118 on_play_state_changed_.Run(media_stream_, &playing_state_);
119 } 119 }
120 120
121 media::OutputDevice* GetOutputDevice() override { 121 media::OutputDeviceInfo GetOutputDeviceInfo() override {
122 DCHECK(thread_checker_.CalledOnValidThread()); 122 DCHECK(thread_checker_.CalledOnValidThread());
123 return delegate_->GetOutputDevice(); 123 return delegate_->GetOutputDeviceInfo();
124 }
125
126 void SwitchOutputDevice(
127 const std::string& device_id,
128 const url::Origin& security_origin,
129 const media::OutputDeviceStatusCB& callback) override {
130 DCHECK(thread_checker_.CalledOnValidThread());
131 return delegate_->SwitchOutputDevice(device_id, security_origin, callback);
124 } 132 }
125 133
126 base::TimeDelta GetCurrentRenderTime() const override { 134 base::TimeDelta GetCurrentRenderTime() const override {
127 DCHECK(thread_checker_.CalledOnValidThread()); 135 DCHECK(thread_checker_.CalledOnValidThread());
128 return delegate_->GetCurrentRenderTime(); 136 return delegate_->GetCurrentRenderTime();
129 } 137 }
130 138
131 bool IsLocalRenderer() const override { 139 bool IsLocalRenderer() const override {
132 DCHECK(thread_checker_.CalledOnValidThread()); 140 DCHECK(thread_checker_.CalledOnValidThread());
133 return delegate_->IsLocalRenderer(); 141 return delegate_->IsLocalRenderer();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 { 225 {
218 base::AutoLock auto_lock(lock_); 226 base::AutoLock auto_lock(lock_);
219 DCHECK_EQ(state_, UNINITIALIZED); 227 DCHECK_EQ(state_, UNINITIALIZED);
220 DCHECK(!source_); 228 DCHECK(!source_);
221 } 229 }
222 230
223 sink_ = AudioDeviceFactory::NewAudioRendererSink( 231 sink_ = AudioDeviceFactory::NewAudioRendererSink(
224 AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, session_id_, 232 AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, session_id_,
225 output_device_id_, security_origin_); 233 output_device_id_, security_origin_);
226 234
227 if (sink_->GetOutputDevice()->GetDeviceStatus() != 235 if (sink_->GetOutputDeviceInfo().device_status() !=
228 media::OUTPUT_DEVICE_STATUS_OK) { 236 media::OUTPUT_DEVICE_STATUS_OK) {
229 return false; 237 return false;
230 } 238 }
231 239
232 PrepareSink(); 240 PrepareSink();
233 { 241 {
234 // No need to reassert the preconditions because the other thread accessing 242 // No need to reassert the preconditions because the other thread accessing
235 // the fields (checked by |audio_renderer_thread_checker_|) only reads them. 243 // the fields (checked by |audio_renderer_thread_checker_|) only reads them.
236 base::AutoLock auto_lock(lock_); 244 base::AutoLock auto_lock(lock_);
237 source_ = source; 245 source_ = source;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 } 356 }
349 357
350 void WebRtcAudioRenderer::SetVolume(float volume) { 358 void WebRtcAudioRenderer::SetVolume(float volume) {
351 DCHECK(thread_checker_.CalledOnValidThread()); 359 DCHECK(thread_checker_.CalledOnValidThread());
352 DCHECK(volume >= 0.0f && volume <= 1.0f); 360 DCHECK(volume >= 0.0f && volume <= 1.0f);
353 361
354 playing_state_.set_volume(volume); 362 playing_state_.set_volume(volume);
355 OnPlayStateChanged(media_stream_, &playing_state_); 363 OnPlayStateChanged(media_stream_, &playing_state_);
356 } 364 }
357 365
358 media::OutputDevice* WebRtcAudioRenderer::GetOutputDevice() { 366 media::OutputDeviceInfo WebRtcAudioRenderer::GetOutputDeviceInfo() {
359 DCHECK(thread_checker_.CalledOnValidThread()); 367 DCHECK(thread_checker_.CalledOnValidThread());
360 return this; 368 return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo();
361 } 369 }
362 370
363 base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const { 371 base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const {
364 DCHECK(thread_checker_.CalledOnValidThread()); 372 DCHECK(thread_checker_.CalledOnValidThread());
365 base::AutoLock auto_lock(lock_); 373 base::AutoLock auto_lock(lock_);
366 return current_time_; 374 return current_time_;
367 } 375 }
368 376
369 bool WebRtcAudioRenderer::IsLocalRenderer() const { 377 bool WebRtcAudioRenderer::IsLocalRenderer() const {
370 return false; 378 return false;
371 } 379 }
372 380
373 void WebRtcAudioRenderer::SwitchOutputDevice( 381 void WebRtcAudioRenderer::SwitchOutputDevice(
374 const std::string& device_id, 382 const std::string& device_id,
375 const url::Origin& security_origin, 383 const url::Origin& security_origin,
376 const media::SwitchOutputDeviceCB& callback) { 384 const media::OutputDeviceStatusCB& callback) {
377 DVLOG(1) << "WebRtcAudioRenderer::SwitchOutputDevice()"; 385 DVLOG(1) << "WebRtcAudioRenderer::SwitchOutputDevice()";
378 DCHECK(thread_checker_.CalledOnValidThread()); 386 DCHECK(thread_checker_.CalledOnValidThread());
379 DCHECK_GE(session_id_, 0); 387 DCHECK_GE(session_id_, 0);
380 { 388 {
381 base::AutoLock auto_lock(lock_); 389 base::AutoLock auto_lock(lock_);
382 DCHECK(source_); 390 DCHECK(source_);
383 DCHECK_NE(state_, UNINITIALIZED); 391 DCHECK_NE(state_, UNINITIALIZED);
384 } 392 }
385 393
386 scoped_refptr<media::AudioRendererSink> new_sink = 394 scoped_refptr<media::AudioRendererSink> new_sink =
387 AudioDeviceFactory::NewAudioRendererSink( 395 AudioDeviceFactory::NewAudioRendererSink(
388 AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, 396 AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_,
389 session_id_, device_id, security_origin); 397 session_id_, device_id, security_origin);
390 if (new_sink->GetOutputDevice()->GetDeviceStatus() != 398 media::OutputDeviceStatus status =
391 media::OUTPUT_DEVICE_STATUS_OK) { 399 new_sink->GetOutputDeviceInfo().device_status();
392 callback.Run(new_sink->GetOutputDevice()->GetDeviceStatus()); 400 if (status != media::OUTPUT_DEVICE_STATUS_OK) {
401 callback.Run(status);
393 return; 402 return;
394 } 403 }
395 404
396 // Make sure to stop the sink while _not_ holding the lock since the Render() 405 // Make sure to stop the sink while _not_ holding the lock since the Render()
397 // callback may currently be executing and trying to grab the lock while we're 406 // callback may currently be executing and trying to grab the lock while we're
398 // stopping the thread on which it runs. 407 // stopping the thread on which it runs.
399 sink_->Stop(); 408 sink_->Stop();
400 audio_renderer_thread_checker_.DetachFromThread(); 409 audio_renderer_thread_checker_.DetachFromThread();
401 sink_ = new_sink; 410 sink_ = new_sink;
402 output_device_id_ = device_id; 411 output_device_id_ = device_id;
403 security_origin_ = security_origin; 412 security_origin_ = security_origin;
404 { 413 {
405 base::AutoLock auto_lock(lock_); 414 base::AutoLock auto_lock(lock_);
406 source_->AudioRendererThreadStopped(); 415 source_->AudioRendererThreadStopped();
407 } 416 }
408 PrepareSink(); 417 PrepareSink();
409 sink_->Start(); 418 sink_->Start();
410 419
411 callback.Run(media::OUTPUT_DEVICE_STATUS_OK); 420 callback.Run(media::OUTPUT_DEVICE_STATUS_OK);
412 } 421 }
413 422
414 media::AudioParameters WebRtcAudioRenderer::GetOutputParameters() {
415 DCHECK(thread_checker_.CalledOnValidThread());
416 if (!sink_.get())
417 return media::AudioParameters();
418
419 return sink_->GetOutputDevice()->GetOutputParameters();
420 }
421
422 media::OutputDeviceStatus WebRtcAudioRenderer::GetDeviceStatus() {
423 DCHECK(thread_checker_.CalledOnValidThread());
424 if (!sink_.get())
425 return media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
426
427 return sink_->GetOutputDevice()->GetDeviceStatus();
428 }
429
430 int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus, 423 int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus,
431 uint32_t frames_delayed, 424 uint32_t frames_delayed,
432 uint32_t frames_skipped) { 425 uint32_t frames_skipped) {
433 DCHECK(audio_renderer_thread_checker_.CalledOnValidThread()); 426 DCHECK(audio_renderer_thread_checker_.CalledOnValidThread());
434 base::AutoLock auto_lock(lock_); 427 base::AutoLock auto_lock(lock_);
435 if (!source_) 428 if (!source_)
436 return 0; 429 return 0;
437 430
438 // TODO(grunell): Converting from frames to milliseconds will potentially lose 431 // TODO(grunell): Converting from frames to milliseconds will potentially lose
439 // hundreds of microseconds which may cause audio video drift. Update 432 // hundreds of microseconds which may cause audio video drift. Update
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 } 613 }
621 } 614 }
622 615
623 void WebRtcAudioRenderer::PrepareSink() { 616 void WebRtcAudioRenderer::PrepareSink() {
624 DCHECK(thread_checker_.CalledOnValidThread()); 617 DCHECK(thread_checker_.CalledOnValidThread());
625 media::AudioParameters new_sink_params; 618 media::AudioParameters new_sink_params;
626 { 619 {
627 base::AutoLock lock(lock_); 620 base::AutoLock lock(lock_);
628 new_sink_params = sink_params_; 621 new_sink_params = sink_params_;
629 } 622 }
623
624 const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo();
625 DCHECK(device_info.device_status() == media::OUTPUT_DEVICE_STATUS_OK);
626
630 // WebRTC does not yet support higher rates than 96000 on the client side 627 // WebRTC does not yet support higher rates than 96000 on the client side
631 // and 48000 is the preferred sample rate. Therefore, if 192000 is detected, 628 // and 48000 is the preferred sample rate. Therefore, if 192000 is detected,
632 // we change the rate to 48000 instead. The consequence is that the native 629 // we change the rate to 48000 instead. The consequence is that the native
633 // layer will be opened up at 192kHz but WebRTC will provide data at 48kHz 630 // layer will be opened up at 192kHz but WebRTC will provide data at 48kHz
634 // which will then be resampled by the audio converted on the browser side 631 // which will then be resampled by the audio converted on the browser side
635 // to match the native audio layer. 632 // to match the native audio layer.
636 int sample_rate = 633 int sample_rate = device_info.output_params().sample_rate();
637 sink_->GetOutputDevice()->GetOutputParameters().sample_rate();
638 DVLOG(1) << "Audio output hardware sample rate: " << sample_rate; 634 DVLOG(1) << "Audio output hardware sample rate: " << sample_rate;
639 if (sample_rate >= 192000) { 635 if (sample_rate >= 192000) {
640 DVLOG(1) << "Resampling from 48000 to " << sample_rate << " is required"; 636 DVLOG(1) << "Resampling from 48000 to " << sample_rate << " is required";
641 sample_rate = 48000; 637 sample_rate = 48000;
642 } 638 }
643 media::AudioSampleRate asr; 639 media::AudioSampleRate asr;
644 if (media::ToAudioSampleRate(sample_rate, &asr)) { 640 if (media::ToAudioSampleRate(sample_rate, &asr)) {
645 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputSampleRate", asr, 641 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputSampleRate", asr,
646 media::kAudioSampleRateMax + 1); 642 media::kAudioSampleRateMax + 1);
647 } else { 643 } else {
648 UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputSampleRateUnexpected", sample_rate); 644 UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputSampleRateUnexpected", sample_rate);
649 } 645 }
650 646
651 // Calculate the frames per buffer for the source, i.e. the WebRTC client. We 647 // Calculate the frames per buffer for the source, i.e. the WebRTC client. We
652 // use 10 ms of data since the WebRTC client only supports multiples of 10 ms 648 // use 10 ms of data since the WebRTC client only supports multiples of 10 ms
653 // as buffer size where 10 ms is preferred for lowest possible delay. 649 // as buffer size where 10 ms is preferred for lowest possible delay.
654 const int source_frames_per_buffer = (sample_rate / 100); 650 const int source_frames_per_buffer = (sample_rate / 100);
655 DVLOG(1) << "Using WebRTC output buffer size: " << source_frames_per_buffer; 651 DVLOG(1) << "Using WebRTC output buffer size: " << source_frames_per_buffer;
656 652
657 // Setup sink parameters. 653 // Setup sink parameters.
658 const int sink_frames_per_buffer = GetOptimalBufferSize( 654 const int sink_frames_per_buffer = GetOptimalBufferSize(
659 sample_rate, 655 sample_rate, device_info.output_params().frames_per_buffer());
660 sink_->GetOutputDevice()->GetOutputParameters().frames_per_buffer());
661 new_sink_params.set_sample_rate(sample_rate); 656 new_sink_params.set_sample_rate(sample_rate);
662 new_sink_params.set_frames_per_buffer(sink_frames_per_buffer); 657 new_sink_params.set_frames_per_buffer(sink_frames_per_buffer);
663 658
664 // Create a FIFO if re-buffering is required to match the source input with 659 // Create a FIFO if re-buffering is required to match the source input with
665 // the sink request. The source acts as provider here and the sink as 660 // the sink request. The source acts as provider here and the sink as
666 // consumer. 661 // consumer.
667 const bool different_source_sink_frames = 662 const bool different_source_sink_frames =
668 source_frames_per_buffer != new_sink_params.frames_per_buffer(); 663 source_frames_per_buffer != new_sink_params.frames_per_buffer();
669 if (different_source_sink_frames) { 664 if (different_source_sink_frames) {
670 DVLOG(1) << "Rebuffering from " << source_frames_per_buffer << " to " 665 DVLOG(1) << "Rebuffering from " << source_frames_per_buffer << " to "
671 << new_sink_params.frames_per_buffer(); 666 << new_sink_params.frames_per_buffer();
672 } 667 }
673 { 668 {
674 base::AutoLock lock(lock_); 669 base::AutoLock lock(lock_);
675 if ((!audio_fifo_ && different_source_sink_frames) || 670 if ((!audio_fifo_ && different_source_sink_frames) ||
676 (audio_fifo_ && 671 (audio_fifo_ &&
677 audio_fifo_->SizeInFrames() != source_frames_per_buffer)) { 672 audio_fifo_->SizeInFrames() != source_frames_per_buffer)) {
678 audio_fifo_.reset(new media::AudioPullFifo( 673 audio_fifo_.reset(new media::AudioPullFifo(
679 kChannels, source_frames_per_buffer, 674 kChannels, source_frames_per_buffer,
680 base::Bind(&WebRtcAudioRenderer::SourceCallback, 675 base::Bind(&WebRtcAudioRenderer::SourceCallback,
681 base::Unretained(this)))); 676 base::Unretained(this))));
682 } 677 }
683 sink_params_ = new_sink_params; 678 sink_params_ = new_sink_params;
684 } 679 }
685 680
686 sink_->Initialize(new_sink_params, this); 681 sink_->Initialize(new_sink_params, this);
687 } 682 }
688 683
689 } // namespace content 684 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698