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

Side by Side Diff: media/audio/mac/audio_manager_mac.cc

Issue 1780333007: AudioManagerBase: Create and run the audio thread lazily. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: 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
« no previous file with comments | « media/audio/mac/audio_manager_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "media/audio/mac/audio_manager_mac.h" 5 #include "media/audio/mac/audio_manager_mac.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 363
364 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); 364 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver);
365 }; 365 };
366 366
367 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) 367 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory)
368 : AudioManagerBase(audio_log_factory), 368 : AudioManagerBase(audio_log_factory),
369 current_sample_rate_(0), 369 current_sample_rate_(0),
370 current_output_device_(kAudioDeviceUnknown) { 370 current_output_device_(kAudioDeviceUnknown) {
371 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 371 SetMaxOutputStreamsAllowed(kMaxOutputStreams);
372 372
373 // CoreAudio calls must occur on the main thread of the process, which in our
374 // case is sadly the browser UI thread. Failure to execute calls on the right
375 // thread leads to crashes and odd behavior. See http://crbug.com/158170.
376 // TODO(dalecurtis): We should require the message loop to be passed in.
377 CHECK(base::MessageLoopForUI::IsCurrent());
378 task_runner_ = base::ThreadTaskRunnerHandle::Get();
379
373 // Task must be posted last to avoid races from handing out "this" to the 380 // Task must be posted last to avoid races from handing out "this" to the
374 // audio thread. Always PostTask even if we're on the right thread since 381 // audio thread. Always PostTask even if we're on the right thread since
375 // AudioManager creation is on the startup path and this may be slow. 382 // AudioManager creation is on the startup path and this may be slow.
376 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( 383 task_runner_->PostTask(FROM_HERE,
377 &AudioManagerMac::InitializeOnAudioThread, base::Unretained(this))); 384 base::Bind(&AudioManagerMac::InitializeOnAudioThread,
385 base::Unretained(this)));
378 } 386 }
379 387
380 AudioManagerMac::~AudioManagerMac() { 388 AudioManagerMac::~AudioManagerMac() {
381 if (GetTaskRunner()->BelongsToCurrentThread()) { 389 if (GetTaskRunner()->BelongsToCurrentThread()) {
382 ShutdownOnAudioThread(); 390 ShutdownOnAudioThread();
383 } else { 391 } else {
384 // It's safe to post a task here since Shutdown() will wait for all tasks to 392 // It's safe to post a task here since Shutdown() will wait for all tasks to
385 // complete before returning. 393 // complete before returning.
386 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( 394 GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
387 &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this))); 395 &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this)));
388 } 396 }
389 397
390 Shutdown(); 398 Shutdown();
391 } 399 }
392 400
401 scoped_refptr<base::SingleThreadTaskRunner> AudioManagerMac::GetTaskRunner() {
402 return task_runner_;
403 }
404
405 scoped_refptr<base::SingleThreadTaskRunner>
406 AudioManagerMac::GetWorkerTaskRunner() {
407 if (!worker_thread_) {
408 worker_thread_.reset(new base::Thread("AudioWorkerThread"));
409 CHECK(worker_thread_->Start());
410 }
411 return worker_thread_->task_runner();
412 }
413
393 bool AudioManagerMac::HasAudioOutputDevices() { 414 bool AudioManagerMac::HasAudioOutputDevices() {
394 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); 415 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
395 } 416 }
396 417
397 bool AudioManagerMac::HasAudioInputDevices() { 418 bool AudioManagerMac::HasAudioInputDevices() {
398 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); 419 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
399 } 420 }
400 421
401 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device, 422 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
402 AudioObjectPropertyScope scope, 423 AudioObjectPropertyScope scope,
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 const int buffer_size = ChooseBufferSize(true, sample_rate); 538 const int buffer_size = ChooseBufferSize(true, sample_rate);
518 539
519 // TODO(xians): query the native channel layout for the specific device. 540 // TODO(xians): query the native channel layout for the specific device.
520 return AudioParameters( 541 return AudioParameters(
521 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 542 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
522 sample_rate, 16, buffer_size); 543 sample_rate, 16, buffer_size);
523 } 544 }
524 545
525 std::string AudioManagerMac::GetAssociatedOutputDeviceID( 546 std::string AudioManagerMac::GetAssociatedOutputDeviceID(
526 const std::string& input_device_id) { 547 const std::string& input_device_id) {
527 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 548 DCHECK(task_runner_->BelongsToCurrentThread());
DaleCurtis 2016/03/14 21:46:09 Why this change? Seems better to use the GetTaskRu
alokp 2016/03/14 22:07:17 reverted in the new patch.
528 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); 549 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
529 if (device == kAudioObjectUnknown) 550 if (device == kAudioObjectUnknown)
530 return std::string(); 551 return std::string();
531 552
532 UInt32 size = 0; 553 UInt32 size = 0;
533 AudioObjectPropertyAddress pa = { 554 AudioObjectPropertyAddress pa = {
534 kAudioDevicePropertyRelatedDevices, 555 kAudioDevicePropertyRelatedDevices,
535 kAudioDevicePropertyScopeOutput, 556 kAudioDevicePropertyScopeOutput,
536 kAudioObjectPropertyElementMaster 557 kAudioObjectPropertyElementMaster
537 }; 558 };
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 // rates on OSX. 653 // rates on OSX.
633 current_sample_rate_ = params.sample_rate(); 654 current_sample_rate_ = params.sample_rate();
634 } 655 }
635 656
636 AUHALStream* stream = new AUHALStream(this, params, device); 657 AUHALStream* stream = new AUHALStream(this, params, device);
637 output_streams_.push_back(stream); 658 output_streams_.push_back(stream);
638 return stream; 659 return stream;
639 } 660 }
640 661
641 std::string AudioManagerMac::GetDefaultOutputDeviceID() { 662 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
642 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 663 DCHECK(task_runner_->BelongsToCurrentThread());
643 AudioDeviceID device_id = kAudioObjectUnknown; 664 AudioDeviceID device_id = kAudioObjectUnknown;
644 if (!GetDefaultOutputDevice(&device_id)) 665 if (!GetDefaultOutputDevice(&device_id))
645 return std::string(); 666 return std::string();
646 667
647 const AudioObjectPropertyAddress property_address = { 668 const AudioObjectPropertyAddress property_address = {
648 kAudioDevicePropertyDeviceUID, 669 kAudioDevicePropertyDeviceUID,
649 kAudioObjectPropertyScopeGlobal, 670 kAudioObjectPropertyScopeGlobal,
650 kAudioObjectPropertyElementMaster 671 kAudioObjectPropertyElementMaster
651 }; 672 };
652 CFStringRef device_uid = NULL; 673 CFStringRef device_uid = NULL;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 channel_layout = CHANNEL_LAYOUT_DISCRETE; 752 channel_layout = CHANNEL_LAYOUT_DISCRETE;
732 } 753 }
733 754
734 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 755 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
735 hardware_sample_rate, 16, buffer_size); 756 hardware_sample_rate, 16, buffer_size);
736 params.set_channels_for_discrete(output_channels); 757 params.set_channels_for_discrete(output_channels);
737 return params; 758 return params;
738 } 759 }
739 760
740 void AudioManagerMac::InitializeOnAudioThread() { 761 void AudioManagerMac::InitializeOnAudioThread() {
741 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 762 DCHECK(task_runner_->BelongsToCurrentThread());
742 power_observer_.reset(new AudioPowerObserver()); 763 power_observer_.reset(new AudioPowerObserver());
743 } 764 }
744 765
745 void AudioManagerMac::ShutdownOnAudioThread() { 766 void AudioManagerMac::ShutdownOnAudioThread() {
746 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 767 DCHECK(task_runner_->BelongsToCurrentThread());
747 output_device_listener_.reset(); 768 output_device_listener_.reset();
748 power_observer_.reset(); 769 power_observer_.reset();
749 770
750 // Since CoreAudio calls have to run on the UI thread and browser shutdown 771 // Since CoreAudio calls have to run on the UI thread and browser shutdown
751 // doesn't wait for outstanding tasks to complete, we may have input/output 772 // doesn't wait for outstanding tasks to complete, we may have input/output
752 // streams still running at shutdown. 773 // streams still running at shutdown.
753 // 774 //
754 // To avoid calls into destructed classes, we need to stop the OS callbacks 775 // To avoid calls into destructed classes, we need to stop the OS callbacks
755 // by stopping the streams. Note: The streams are leaked since process 776 // by stopping the streams. Note: The streams are leaked since process
756 // destruction is imminent. 777 // destruction is imminent.
757 // 778 //
758 // See http://crbug.com/354139 for crash details. 779 // See http://crbug.com/354139 for crash details.
759 StopStreams(&basic_input_streams_); 780 StopStreams(&basic_input_streams_);
760 StopStreams(&low_latency_input_streams_); 781 StopStreams(&low_latency_input_streams_);
761 StopStreams(&output_streams_); 782 StopStreams(&output_streams_);
762 } 783 }
763 784
764 void AudioManagerMac::HandleDeviceChanges() { 785 void AudioManagerMac::HandleDeviceChanges() {
765 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 786 DCHECK(task_runner_->BelongsToCurrentThread());
766 const int new_sample_rate = HardwareSampleRate(); 787 const int new_sample_rate = HardwareSampleRate();
767 AudioDeviceID new_output_device; 788 AudioDeviceID new_output_device;
768 GetDefaultOutputDevice(&new_output_device); 789 GetDefaultOutputDevice(&new_output_device);
769 790
770 if (current_sample_rate_ == new_sample_rate && 791 if (current_sample_rate_ == new_sample_rate &&
771 current_output_device_ == new_output_device) { 792 current_output_device_ == new_output_device) {
772 return; 793 return;
773 } 794 }
774 795
775 current_sample_rate_ = new_sample_rate; 796 current_sample_rate_ = new_sample_rate;
(...skipping 21 matching lines...) Expand all
797 if (sample_rate <= 96000) 818 if (sample_rate <= 96000)
798 buffer_size = 2 * kMinimumInputOutputBufferSize; 819 buffer_size = 2 * kMinimumInputOutputBufferSize;
799 else if (sample_rate <= 192000) 820 else if (sample_rate <= 192000)
800 buffer_size = 4 * kMinimumInputOutputBufferSize; 821 buffer_size = 4 * kMinimumInputOutputBufferSize;
801 } 822 }
802 823
803 return buffer_size; 824 return buffer_size;
804 } 825 }
805 826
806 bool AudioManagerMac::ShouldDeferStreamStart() const { 827 bool AudioManagerMac::ShouldDeferStreamStart() const {
807 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 828 DCHECK(task_runner_->BelongsToCurrentThread());
808 return power_observer_->ShouldDeferStreamStart(); 829 return power_observer_->ShouldDeferStreamStart();
809 } 830 }
810 831
811 bool AudioManagerMac::IsOnBatteryPower() const { 832 bool AudioManagerMac::IsOnBatteryPower() const {
812 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 833 DCHECK(task_runner_->BelongsToCurrentThread());
813 return power_observer_->IsOnBatteryPower(); 834 return power_observer_->IsOnBatteryPower();
814 } 835 }
815 836
816 size_t AudioManagerMac::GetNumberOfResumeNotifications() const { 837 size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
817 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 838 DCHECK(task_runner_->BelongsToCurrentThread());
818 return power_observer_->num_resume_notifications(); 839 return power_observer_->num_resume_notifications();
819 } 840 }
820 841
821 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, 842 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id,
822 AudioUnit audio_unit, 843 AudioUnit audio_unit,
823 AudioUnitElement element, 844 AudioUnitElement element,
824 size_t desired_buffer_size, 845 size_t desired_buffer_size,
825 bool* size_was_changed, 846 bool* size_was_changed,
826 size_t* io_buffer_frame_size) { 847 size_t* io_buffer_frame_size) {
827 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 848 DCHECK(task_runner_->BelongsToCurrentThread());
828 const bool is_input = (element == 1); 849 const bool is_input = (element == 1);
829 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id 850 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id
830 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec 851 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
831 << desired_buffer_size << ")"; 852 << desired_buffer_size << ")";
832 853
833 *size_was_changed = false; 854 *size_was_changed = false;
834 *io_buffer_frame_size = 0; 855 *io_buffer_frame_size = 0;
835 856
836 // Log the device name (and id) for debugging purposes. 857 // Log the device name (and id) for debugging purposes.
837 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input); 858 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 basic_input_streams_.erase(stream_it); 963 basic_input_streams_.erase(stream_it);
943 964
944 AudioManagerBase::ReleaseInputStream(stream); 965 AudioManagerBase::ReleaseInputStream(stream);
945 } 966 }
946 967
947 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { 968 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
948 return new AudioManagerMac(audio_log_factory); 969 return new AudioManagerMac(audio_log_factory);
949 } 970 }
950 971
951 } // namespace media 972 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/mac/audio_manager_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698