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

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

Issue 1806313003: Pass task runners to AudioManager constructor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed AudioManagerBase::Shutdown Created 4 years, 8 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 "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 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 358
359 bool is_suspending_; 359 bool is_suspending_;
360 const bool is_monitoring_; 360 const bool is_monitoring_;
361 base::TimeTicks earliest_start_time_; 361 base::TimeTicks earliest_start_time_;
362 base::ThreadChecker thread_checker_; 362 base::ThreadChecker thread_checker_;
363 size_t num_resume_notifications_; 363 size_t num_resume_notifications_;
364 364
365 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); 365 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver);
366 }; 366 };
367 367
368 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) 368 AudioManagerMac::AudioManagerMac(
369 : AudioManagerBase(audio_log_factory), 369 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
370 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
371 AudioLogFactory* audio_log_factory)
372 : AudioManagerBase(std::move(task_runner),
373 std::move(worker_task_runner),
374 audio_log_factory),
370 current_sample_rate_(0), 375 current_sample_rate_(0),
371 current_output_device_(kAudioDeviceUnknown) { 376 current_output_device_(kAudioDeviceUnknown) {
372 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 377 SetMaxOutputStreamsAllowed(kMaxOutputStreams);
373 378
374 // CoreAudio calls must occur on the main thread of the process, which in our
375 // case is sadly the browser UI thread. Failure to execute calls on the right
376 // thread leads to crashes and odd behavior. See http://crbug.com/158170.
377 // TODO(dalecurtis): We should require the message loop to be passed in.
378 task_runner_ = base::MessageLoopForUI::IsCurrent()
379 ? base::ThreadTaskRunnerHandle::Get()
380 : AudioManagerBase::GetTaskRunner();
381
382 // Task must be posted last to avoid races from handing out "this" to the 379 // Task must be posted last to avoid races from handing out "this" to the
383 // audio thread. Always PostTask even if we're on the right thread since 380 // audio thread. Always PostTask even if we're on the right thread since
384 // AudioManager creation is on the startup path and this may be slow. 381 // AudioManager creation is on the startup path and this may be slow.
385 task_runner_->PostTask(FROM_HERE, 382 GetTaskRunner()->PostTask(
386 base::Bind(&AudioManagerMac::InitializeOnAudioThread, 383 FROM_HERE, base::Bind(&AudioManagerMac::InitializeOnAudioThread,
387 base::Unretained(this))); 384 base::Unretained(this)));
388 } 385 }
389 386
390 AudioManagerMac::~AudioManagerMac() { 387 AudioManagerMac::~AudioManagerMac() {
391 if (task_runner_->BelongsToCurrentThread()) { 388 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
392 ShutdownOnAudioThread(); 389 output_device_listener_.reset();
393 } else { 390 power_observer_.reset();
394 // It's safe to post a task here since Shutdown() will wait for all tasks to
395 // complete before returning.
396 task_runner_->PostTask(FROM_HERE,
397 base::Bind(&AudioManagerMac::ShutdownOnAudioThread,
398 base::Unretained(this)));
399 }
400 391
401 Shutdown(); 392 // Since CoreAudio calls have to run on the UI thread and browser shutdown
DaleCurtis 2016/04/06 22:07:49 These should be removable if you change the scoped
alokp 2016/04/07 00:38:10 Done.
402 } 393 // doesn't wait for outstanding tasks to complete, we may have input/output
403 394 // streams still running at shutdown.
404 scoped_refptr<base::SingleThreadTaskRunner> AudioManagerMac::GetTaskRunner() { 395 //
405 return task_runner_; 396 // To avoid calls into destructed classes, we need to stop the OS callbacks
406 } 397 // by stopping the streams. Note: The streams are leaked since process
407 398 // destruction is imminent.
408 scoped_refptr<base::SingleThreadTaskRunner> 399 //
409 AudioManagerMac::GetWorkerTaskRunner() { 400 // See http://crbug.com/354139 for crash details.
410 if (!worker_thread_) { 401 StopStreams(&basic_input_streams_);
411 worker_thread_.reset(new base::Thread("AudioWorkerThread")); 402 StopStreams(&low_latency_input_streams_);
412 CHECK(worker_thread_->Start()); 403 StopStreams(&output_streams_);
413 }
414 return worker_thread_->task_runner();
415 } 404 }
416 405
417 bool AudioManagerMac::HasAudioOutputDevices() { 406 bool AudioManagerMac::HasAudioOutputDevices() {
418 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); 407 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
419 } 408 }
420 409
421 bool AudioManagerMac::HasAudioInputDevices() { 410 bool AudioManagerMac::HasAudioInputDevices() {
422 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); 411 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
423 } 412 }
424 413
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 const int buffer_size = ChooseBufferSize(true, sample_rate); 533 const int buffer_size = ChooseBufferSize(true, sample_rate);
545 534
546 // TODO(xians): query the native channel layout for the specific device. 535 // TODO(xians): query the native channel layout for the specific device.
547 return AudioParameters( 536 return AudioParameters(
548 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 537 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
549 sample_rate, 16, buffer_size); 538 sample_rate, 16, buffer_size);
550 } 539 }
551 540
552 std::string AudioManagerMac::GetAssociatedOutputDeviceID( 541 std::string AudioManagerMac::GetAssociatedOutputDeviceID(
553 const std::string& input_device_id) { 542 const std::string& input_device_id) {
554 DCHECK(task_runner_->BelongsToCurrentThread()); 543 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
555 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); 544 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
556 if (device == kAudioObjectUnknown) 545 if (device == kAudioObjectUnknown)
557 return std::string(); 546 return std::string();
558 547
559 UInt32 size = 0; 548 UInt32 size = 0;
560 AudioObjectPropertyAddress pa = { 549 AudioObjectPropertyAddress pa = {
561 kAudioDevicePropertyRelatedDevices, 550 kAudioDevicePropertyRelatedDevices,
562 kAudioDevicePropertyScopeOutput, 551 kAudioDevicePropertyScopeOutput,
563 kAudioObjectPropertyElementMaster 552 kAudioObjectPropertyElementMaster
564 }; 553 };
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 // rates on OSX. 658 // rates on OSX.
670 current_sample_rate_ = params.sample_rate(); 659 current_sample_rate_ = params.sample_rate();
671 } 660 }
672 661
673 AUHALStream* stream = new AUHALStream(this, params, device); 662 AUHALStream* stream = new AUHALStream(this, params, device);
674 output_streams_.push_back(stream); 663 output_streams_.push_back(stream);
675 return stream; 664 return stream;
676 } 665 }
677 666
678 std::string AudioManagerMac::GetDefaultOutputDeviceID() { 667 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
679 DCHECK(task_runner_->BelongsToCurrentThread()); 668 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
680 AudioDeviceID device_id = kAudioObjectUnknown; 669 AudioDeviceID device_id = kAudioObjectUnknown;
681 if (!GetDefaultOutputDevice(&device_id)) 670 if (!GetDefaultOutputDevice(&device_id))
682 return std::string(); 671 return std::string();
683 672
684 const AudioObjectPropertyAddress property_address = { 673 const AudioObjectPropertyAddress property_address = {
685 kAudioDevicePropertyDeviceUID, 674 kAudioDevicePropertyDeviceUID,
686 kAudioObjectPropertyScopeGlobal, 675 kAudioObjectPropertyScopeGlobal,
687 kAudioObjectPropertyElementMaster 676 kAudioObjectPropertyElementMaster
688 }; 677 };
689 CFStringRef device_uid = NULL; 678 CFStringRef device_uid = NULL;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 channel_layout = CHANNEL_LAYOUT_DISCRETE; 757 channel_layout = CHANNEL_LAYOUT_DISCRETE;
769 } 758 }
770 759
771 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 760 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
772 hardware_sample_rate, 16, buffer_size); 761 hardware_sample_rate, 16, buffer_size);
773 params.set_channels_for_discrete(output_channels); 762 params.set_channels_for_discrete(output_channels);
774 return params; 763 return params;
775 } 764 }
776 765
777 void AudioManagerMac::InitializeOnAudioThread() { 766 void AudioManagerMac::InitializeOnAudioThread() {
778 DCHECK(task_runner_->BelongsToCurrentThread()); 767 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
779 power_observer_.reset(new AudioPowerObserver()); 768 power_observer_.reset(new AudioPowerObserver());
780 } 769 }
781 770
782 void AudioManagerMac::ShutdownOnAudioThread() {
783 DCHECK(task_runner_->BelongsToCurrentThread());
784 output_device_listener_.reset();
785 power_observer_.reset();
786
787 // Since CoreAudio calls have to run on the UI thread and browser shutdown
788 // doesn't wait for outstanding tasks to complete, we may have input/output
789 // streams still running at shutdown.
790 //
791 // To avoid calls into destructed classes, we need to stop the OS callbacks
792 // by stopping the streams. Note: The streams are leaked since process
793 // destruction is imminent.
794 //
795 // See http://crbug.com/354139 for crash details.
796 StopStreams(&basic_input_streams_);
797 StopStreams(&low_latency_input_streams_);
798 StopStreams(&output_streams_);
799 }
800
801 void AudioManagerMac::HandleDeviceChanges() { 771 void AudioManagerMac::HandleDeviceChanges() {
802 DCHECK(task_runner_->BelongsToCurrentThread()); 772 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
803 const int new_sample_rate = HardwareSampleRate(); 773 const int new_sample_rate = HardwareSampleRate();
804 AudioDeviceID new_output_device; 774 AudioDeviceID new_output_device;
805 GetDefaultOutputDevice(&new_output_device); 775 GetDefaultOutputDevice(&new_output_device);
806 776
807 if (current_sample_rate_ == new_sample_rate && 777 if (current_sample_rate_ == new_sample_rate &&
808 current_output_device_ == new_output_device) { 778 current_output_device_ == new_output_device) {
809 return; 779 return;
810 } 780 }
811 781
812 current_sample_rate_ = new_sample_rate; 782 current_sample_rate_ = new_sample_rate;
(...skipping 21 matching lines...) Expand all
834 if (sample_rate <= 96000) 804 if (sample_rate <= 96000)
835 buffer_size = 2 * kMinimumInputOutputBufferSize; 805 buffer_size = 2 * kMinimumInputOutputBufferSize;
836 else if (sample_rate <= 192000) 806 else if (sample_rate <= 192000)
837 buffer_size = 4 * kMinimumInputOutputBufferSize; 807 buffer_size = 4 * kMinimumInputOutputBufferSize;
838 } 808 }
839 809
840 return buffer_size; 810 return buffer_size;
841 } 811 }
842 812
843 bool AudioManagerMac::ShouldDeferStreamStart() const { 813 bool AudioManagerMac::ShouldDeferStreamStart() const {
844 DCHECK(task_runner_->BelongsToCurrentThread()); 814 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
845 return power_observer_->ShouldDeferStreamStart(); 815 return power_observer_->ShouldDeferStreamStart();
846 } 816 }
847 817
848 bool AudioManagerMac::IsOnBatteryPower() const { 818 bool AudioManagerMac::IsOnBatteryPower() const {
849 DCHECK(task_runner_->BelongsToCurrentThread()); 819 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
850 return power_observer_->IsOnBatteryPower(); 820 return power_observer_->IsOnBatteryPower();
851 } 821 }
852 822
853 size_t AudioManagerMac::GetNumberOfResumeNotifications() const { 823 size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
854 DCHECK(task_runner_->BelongsToCurrentThread()); 824 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
855 return power_observer_->num_resume_notifications(); 825 return power_observer_->num_resume_notifications();
856 } 826 }
857 827
858 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, 828 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id,
859 AudioUnit audio_unit, 829 AudioUnit audio_unit,
860 AudioUnitElement element, 830 AudioUnitElement element,
861 size_t desired_buffer_size, 831 size_t desired_buffer_size,
862 bool* size_was_changed, 832 bool* size_was_changed,
863 size_t* io_buffer_frame_size) { 833 size_t* io_buffer_frame_size) {
864 DCHECK(task_runner_->BelongsToCurrentThread()); 834 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
865 const bool is_input = (element == 1); 835 const bool is_input = (element == 1);
866 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id 836 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id
867 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec 837 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
868 << desired_buffer_size << ")"; 838 << desired_buffer_size << ")";
869 839
870 *size_was_changed = false; 840 *size_was_changed = false;
871 *io_buffer_frame_size = 0; 841 *io_buffer_frame_size = 0;
872 842
873 // Log the device name (and id) for debugging purposes. 843 // Log the device name (and id) for debugging purposes.
874 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input); 844 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 basic_input_streams_.end(), 944 basic_input_streams_.end(),
975 stream); 945 stream);
976 if (stream_it == basic_input_streams_.end()) 946 if (stream_it == basic_input_streams_.end())
977 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream)); 947 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
978 else 948 else
979 basic_input_streams_.erase(stream_it); 949 basic_input_streams_.erase(stream_it);
980 950
981 AudioManagerBase::ReleaseInputStream(stream); 951 AudioManagerBase::ReleaseInputStream(stream);
982 } 952 }
983 953
984 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { 954 ScopedAudioManagerPtr CreateAudioManager(
985 return new AudioManagerMac(audio_log_factory); 955 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
956 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
957 AudioLogFactory* audio_log_factory) {
958 return ScopedAudioManagerPtr(
959 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner),
960 audio_log_factory));
986 } 961 }
987 962
988 } // namespace media 963 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698