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

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: address comments from patch 48 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
« no previous file with comments | « media/audio/mac/audio_manager_mac.h ('k') | media/audio/mock_audio_manager.h » ('j') | 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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 DLOG(ERROR) << "Error getting default AudioDevice."; 286 DLOG(ERROR) << "Error getting default AudioDevice.";
287 return false; 287 return false;
288 } 288 }
289 return true; 289 return true;
290 } 290 }
291 291
292 static bool GetDefaultOutputDevice(AudioDeviceID* device) { 292 static bool GetDefaultOutputDevice(AudioDeviceID* device) {
293 return GetDefaultDevice(device, false); 293 return GetDefaultDevice(device, false);
294 } 294 }
295 295
296 template <class T>
297 void StopStreams(std::list<T*>* streams) {
298 for (typename std::list<T*>::iterator it = streams->begin();
299 it != streams->end();
300 ++it) {
301 // Stop() is safe to call multiple times, so it doesn't matter if a stream
302 // has already been stopped.
303 (*it)->Stop();
304 }
305 streams->clear();
306 }
307
308 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver { 296 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver {
309 public: 297 public:
310 AudioPowerObserver() 298 AudioPowerObserver()
311 : is_suspending_(false), 299 : is_suspending_(false),
312 is_monitoring_(base::PowerMonitor::Get()), 300 is_monitoring_(base::PowerMonitor::Get()),
313 num_resume_notifications_(0) { 301 num_resume_notifications_(0) {
314 // The PowerMonitor requires significant setup (a CFRunLoop and preallocated 302 // The PowerMonitor requires significant setup (a CFRunLoop and preallocated
315 // IO ports) so it's not available under unit tests. See the OSX impl of 303 // IO ports) so it's not available under unit tests. See the OSX impl of
316 // base::PowerMonitorDeviceSource for more details. 304 // base::PowerMonitorDeviceSource for more details.
317 if (!is_monitoring_) 305 if (!is_monitoring_)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 351
364 bool is_suspending_; 352 bool is_suspending_;
365 const bool is_monitoring_; 353 const bool is_monitoring_;
366 base::TimeTicks earliest_start_time_; 354 base::TimeTicks earliest_start_time_;
367 base::ThreadChecker thread_checker_; 355 base::ThreadChecker thread_checker_;
368 size_t num_resume_notifications_; 356 size_t num_resume_notifications_;
369 357
370 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); 358 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver);
371 }; 359 };
372 360
373 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) 361 AudioManagerMac::AudioManagerMac(
374 : AudioManagerBase(audio_log_factory), 362 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
363 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
364 AudioLogFactory* audio_log_factory)
365 : AudioManagerBase(std::move(task_runner),
366 std::move(worker_task_runner),
367 audio_log_factory),
375 current_sample_rate_(0), 368 current_sample_rate_(0),
376 current_output_device_(kAudioDeviceUnknown) { 369 current_output_device_(kAudioDeviceUnknown) {
377 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 370 SetMaxOutputStreamsAllowed(kMaxOutputStreams);
378 371
379 // CoreAudio calls must occur on the main thread of the process, which in our
380 // case is sadly the browser UI thread. Failure to execute calls on the right
381 // thread leads to crashes and odd behavior. See http://crbug.com/158170.
382 // TODO(dalecurtis): We should require the message loop to be passed in.
383 task_runner_ = base::MessageLoopForUI::IsCurrent()
384 ? base::ThreadTaskRunnerHandle::Get()
385 : AudioManagerBase::GetTaskRunner();
386
387 // Task must be posted last to avoid races from handing out "this" to the 372 // Task must be posted last to avoid races from handing out "this" to the
388 // audio thread. Always PostTask even if we're on the right thread since 373 // audio thread. Always PostTask even if we're on the right thread since
389 // AudioManager creation is on the startup path and this may be slow. 374 // AudioManager creation is on the startup path and this may be slow.
390 task_runner_->PostTask(FROM_HERE, 375 GetTaskRunner()->PostTask(
391 base::Bind(&AudioManagerMac::InitializeOnAudioThread, 376 FROM_HERE, base::Bind(&AudioManagerMac::InitializeOnAudioThread,
392 base::Unretained(this))); 377 base::Unretained(this)));
393 } 378 }
394 379
395 AudioManagerMac::~AudioManagerMac() { 380 AudioManagerMac::~AudioManagerMac() {
396 if (task_runner_->BelongsToCurrentThread()) {
397 ShutdownOnAudioThread();
398 } else {
399 // It's safe to post a task here since Shutdown() will wait for all tasks to
400 // complete before returning.
401 task_runner_->PostTask(FROM_HERE,
402 base::Bind(&AudioManagerMac::ShutdownOnAudioThread,
403 base::Unretained(this)));
404 }
405
406 Shutdown(); 381 Shutdown();
407 } 382 }
408 383
409 scoped_refptr<base::SingleThreadTaskRunner> AudioManagerMac::GetTaskRunner() {
410 return task_runner_;
411 }
412
413 scoped_refptr<base::SingleThreadTaskRunner>
414 AudioManagerMac::GetWorkerTaskRunner() {
415 if (!worker_thread_) {
416 worker_thread_.reset(new base::Thread("AudioWorkerThread"));
417 CHECK(worker_thread_->Start());
418 }
419 return worker_thread_->task_runner();
420 }
421
422 bool AudioManagerMac::HasAudioOutputDevices() { 384 bool AudioManagerMac::HasAudioOutputDevices() {
423 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); 385 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
424 } 386 }
425 387
426 bool AudioManagerMac::HasAudioInputDevices() { 388 bool AudioManagerMac::HasAudioInputDevices() {
427 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); 389 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
428 } 390 }
429 391
430 // static 392 // static
431 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device, 393 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 const int buffer_size = ChooseBufferSize(true, sample_rate); 511 const int buffer_size = ChooseBufferSize(true, sample_rate);
550 512
551 // TODO(xians): query the native channel layout for the specific device. 513 // TODO(xians): query the native channel layout for the specific device.
552 return AudioParameters( 514 return AudioParameters(
553 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 515 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
554 sample_rate, 16, buffer_size); 516 sample_rate, 16, buffer_size);
555 } 517 }
556 518
557 std::string AudioManagerMac::GetAssociatedOutputDeviceID( 519 std::string AudioManagerMac::GetAssociatedOutputDeviceID(
558 const std::string& input_device_id) { 520 const std::string& input_device_id) {
559 DCHECK(task_runner_->BelongsToCurrentThread()); 521 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
560 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); 522 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
561 if (device == kAudioObjectUnknown) 523 if (device == kAudioObjectUnknown)
562 return std::string(); 524 return std::string();
563 525
564 UInt32 size = 0; 526 UInt32 size = 0;
565 AudioObjectPropertyAddress pa = { 527 AudioObjectPropertyAddress pa = {
566 kAudioDevicePropertyRelatedDevices, 528 kAudioDevicePropertyRelatedDevices,
567 kAudioDevicePropertyScopeOutput, 529 kAudioDevicePropertyScopeOutput,
568 kAudioObjectPropertyElementMaster 530 kAudioObjectPropertyElementMaster
569 }; 531 };
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 // rates on OSX. 636 // rates on OSX.
675 current_sample_rate_ = params.sample_rate(); 637 current_sample_rate_ = params.sample_rate();
676 } 638 }
677 639
678 AUHALStream* stream = new AUHALStream(this, params, device); 640 AUHALStream* stream = new AUHALStream(this, params, device);
679 output_streams_.push_back(stream); 641 output_streams_.push_back(stream);
680 return stream; 642 return stream;
681 } 643 }
682 644
683 std::string AudioManagerMac::GetDefaultOutputDeviceID() { 645 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
684 DCHECK(task_runner_->BelongsToCurrentThread()); 646 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
685 AudioDeviceID device_id = kAudioObjectUnknown; 647 AudioDeviceID device_id = kAudioObjectUnknown;
686 if (!GetDefaultOutputDevice(&device_id)) 648 if (!GetDefaultOutputDevice(&device_id))
687 return std::string(); 649 return std::string();
688 650
689 const AudioObjectPropertyAddress property_address = { 651 const AudioObjectPropertyAddress property_address = {
690 kAudioDevicePropertyDeviceUID, 652 kAudioDevicePropertyDeviceUID,
691 kAudioObjectPropertyScopeGlobal, 653 kAudioObjectPropertyScopeGlobal,
692 kAudioObjectPropertyElementMaster 654 kAudioObjectPropertyElementMaster
693 }; 655 };
694 CFStringRef device_uid = NULL; 656 CFStringRef device_uid = NULL;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 channel_layout = CHANNEL_LAYOUT_DISCRETE; 735 channel_layout = CHANNEL_LAYOUT_DISCRETE;
774 } 736 }
775 737
776 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 738 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
777 hardware_sample_rate, 16, buffer_size); 739 hardware_sample_rate, 16, buffer_size);
778 params.set_channels_for_discrete(output_channels); 740 params.set_channels_for_discrete(output_channels);
779 return params; 741 return params;
780 } 742 }
781 743
782 void AudioManagerMac::InitializeOnAudioThread() { 744 void AudioManagerMac::InitializeOnAudioThread() {
783 DCHECK(task_runner_->BelongsToCurrentThread()); 745 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
784 power_observer_.reset(new AudioPowerObserver()); 746 power_observer_.reset(new AudioPowerObserver());
785 } 747 }
786 748
787 void AudioManagerMac::ShutdownOnAudioThread() {
788 DCHECK(task_runner_->BelongsToCurrentThread());
789 output_device_listener_.reset();
790 power_observer_.reset();
791
792 // Since CoreAudio calls have to run on the UI thread and browser shutdown
793 // doesn't wait for outstanding tasks to complete, we may have input/output
794 // streams still running at shutdown.
795 //
796 // To avoid calls into destructed classes, we need to stop the OS callbacks
797 // by stopping the streams. Note: The streams are leaked since process
798 // destruction is imminent.
799 //
800 // See http://crbug.com/354139 for crash details.
801 StopStreams(&basic_input_streams_);
802 StopStreams(&low_latency_input_streams_);
803 StopStreams(&output_streams_);
804 }
805
806 void AudioManagerMac::HandleDeviceChanges() { 749 void AudioManagerMac::HandleDeviceChanges() {
807 DCHECK(task_runner_->BelongsToCurrentThread()); 750 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
808 const int new_sample_rate = HardwareSampleRate(); 751 const int new_sample_rate = HardwareSampleRate();
809 AudioDeviceID new_output_device; 752 AudioDeviceID new_output_device;
810 GetDefaultOutputDevice(&new_output_device); 753 GetDefaultOutputDevice(&new_output_device);
811 754
812 if (current_sample_rate_ == new_sample_rate && 755 if (current_sample_rate_ == new_sample_rate &&
813 current_output_device_ == new_output_device) { 756 current_output_device_ == new_output_device) {
814 return; 757 return;
815 } 758 }
816 759
817 current_sample_rate_ = new_sample_rate; 760 current_sample_rate_ = new_sample_rate;
(...skipping 21 matching lines...) Expand all
839 if (sample_rate <= 96000) 782 if (sample_rate <= 96000)
840 buffer_size = 2 * kMinimumInputOutputBufferSize; 783 buffer_size = 2 * kMinimumInputOutputBufferSize;
841 else if (sample_rate <= 192000) 784 else if (sample_rate <= 192000)
842 buffer_size = 4 * kMinimumInputOutputBufferSize; 785 buffer_size = 4 * kMinimumInputOutputBufferSize;
843 } 786 }
844 787
845 return buffer_size; 788 return buffer_size;
846 } 789 }
847 790
848 bool AudioManagerMac::IsSuspending() const { 791 bool AudioManagerMac::IsSuspending() const {
849 DCHECK(task_runner_->BelongsToCurrentThread()); 792 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
850 return power_observer_->IsSuspending(); 793 return power_observer_->IsSuspending();
851 } 794 }
852 795
853 bool AudioManagerMac::ShouldDeferStreamStart() const { 796 bool AudioManagerMac::ShouldDeferStreamStart() const {
854 DCHECK(task_runner_->BelongsToCurrentThread()); 797 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
855 return power_observer_->ShouldDeferStreamStart(); 798 return power_observer_->ShouldDeferStreamStart();
856 } 799 }
857 800
858 bool AudioManagerMac::IsOnBatteryPower() const { 801 bool AudioManagerMac::IsOnBatteryPower() const {
859 DCHECK(task_runner_->BelongsToCurrentThread()); 802 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
860 return power_observer_->IsOnBatteryPower(); 803 return power_observer_->IsOnBatteryPower();
861 } 804 }
862 805
863 size_t AudioManagerMac::GetNumberOfResumeNotifications() const { 806 size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
864 DCHECK(task_runner_->BelongsToCurrentThread()); 807 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
865 return power_observer_->num_resume_notifications(); 808 return power_observer_->num_resume_notifications();
866 } 809 }
867 810
868 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, 811 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id,
869 AudioUnit audio_unit, 812 AudioUnit audio_unit,
870 AudioUnitElement element, 813 AudioUnitElement element,
871 size_t desired_buffer_size, 814 size_t desired_buffer_size,
872 bool* size_was_changed, 815 bool* size_was_changed,
873 size_t* io_buffer_frame_size) { 816 size_t* io_buffer_frame_size) {
874 DCHECK(task_runner_->BelongsToCurrentThread()); 817 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
875 const bool is_input = (element == 1); 818 const bool is_input = (element == 1);
876 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id 819 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id
877 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec 820 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
878 << desired_buffer_size << ")"; 821 << desired_buffer_size << ")";
879 822
880 *size_was_changed = false; 823 *size_was_changed = false;
881 *io_buffer_frame_size = 0; 824 *io_buffer_frame_size = 0;
882 825
883 // Log the device name (and id) for debugging purposes. 826 // Log the device name (and id) for debugging purposes.
884 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input); 827 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 basic_input_streams_.end(), 927 basic_input_streams_.end(),
985 stream); 928 stream);
986 if (stream_it == basic_input_streams_.end()) 929 if (stream_it == basic_input_streams_.end())
987 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream)); 930 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
988 else 931 else
989 basic_input_streams_.erase(stream_it); 932 basic_input_streams_.erase(stream_it);
990 933
991 AudioManagerBase::ReleaseInputStream(stream); 934 AudioManagerBase::ReleaseInputStream(stream);
992 } 935 }
993 936
994 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { 937 ScopedAudioManagerPtr CreateAudioManager(
995 return new AudioManagerMac(audio_log_factory); 938 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
939 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
940 AudioLogFactory* audio_log_factory) {
941 return ScopedAudioManagerPtr(
942 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner),
943 audio_log_factory));
996 } 944 }
997 945
998 } // namespace media 946 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/mac/audio_manager_mac.h ('k') | media/audio/mock_audio_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698