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

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

Issue 1901583005: Revert of Pass task runners to AudioManager constructor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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
296 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver { 308 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver {
297 public: 309 public:
298 AudioPowerObserver() 310 AudioPowerObserver()
299 : is_suspending_(false), 311 : is_suspending_(false),
300 is_monitoring_(base::PowerMonitor::Get()), 312 is_monitoring_(base::PowerMonitor::Get()),
301 num_resume_notifications_(0) { 313 num_resume_notifications_(0) {
302 // The PowerMonitor requires significant setup (a CFRunLoop and preallocated 314 // The PowerMonitor requires significant setup (a CFRunLoop and preallocated
303 // IO ports) so it's not available under unit tests. See the OSX impl of 315 // IO ports) so it's not available under unit tests. See the OSX impl of
304 // base::PowerMonitorDeviceSource for more details. 316 // base::PowerMonitorDeviceSource for more details.
305 if (!is_monitoring_) 317 if (!is_monitoring_)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 363
352 bool is_suspending_; 364 bool is_suspending_;
353 const bool is_monitoring_; 365 const bool is_monitoring_;
354 base::TimeTicks earliest_start_time_; 366 base::TimeTicks earliest_start_time_;
355 base::ThreadChecker thread_checker_; 367 base::ThreadChecker thread_checker_;
356 size_t num_resume_notifications_; 368 size_t num_resume_notifications_;
357 369
358 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); 370 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver);
359 }; 371 };
360 372
361 AudioManagerMac::AudioManagerMac( 373 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory)
362 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 374 : AudioManagerBase(audio_log_factory),
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),
368 current_sample_rate_(0), 375 current_sample_rate_(0),
369 current_output_device_(kAudioDeviceUnknown) { 376 current_output_device_(kAudioDeviceUnknown) {
370 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 377 SetMaxOutputStreamsAllowed(kMaxOutputStreams);
371 378
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
372 // Task must be posted last to avoid races from handing out "this" to the 387 // Task must be posted last to avoid races from handing out "this" to the
373 // audio thread. Always PostTask even if we're on the right thread since 388 // audio thread. Always PostTask even if we're on the right thread since
374 // AudioManager creation is on the startup path and this may be slow. 389 // AudioManager creation is on the startup path and this may be slow.
375 GetTaskRunner()->PostTask( 390 task_runner_->PostTask(FROM_HERE,
376 FROM_HERE, base::Bind(&AudioManagerMac::InitializeOnAudioThread, 391 base::Bind(&AudioManagerMac::InitializeOnAudioThread,
377 base::Unretained(this))); 392 base::Unretained(this)));
378 } 393 }
379 394
380 AudioManagerMac::~AudioManagerMac() { 395 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
381 Shutdown(); 406 Shutdown();
382 } 407 }
383 408
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
384 bool AudioManagerMac::HasAudioOutputDevices() { 422 bool AudioManagerMac::HasAudioOutputDevices() {
385 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); 423 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
386 } 424 }
387 425
388 bool AudioManagerMac::HasAudioInputDevices() { 426 bool AudioManagerMac::HasAudioInputDevices() {
389 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); 427 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
390 } 428 }
391 429
392 // static 430 // static
393 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device, 431 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 const int buffer_size = ChooseBufferSize(true, sample_rate); 549 const int buffer_size = ChooseBufferSize(true, sample_rate);
512 550
513 // TODO(xians): query the native channel layout for the specific device. 551 // TODO(xians): query the native channel layout for the specific device.
514 return AudioParameters( 552 return AudioParameters(
515 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 553 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
516 sample_rate, 16, buffer_size); 554 sample_rate, 16, buffer_size);
517 } 555 }
518 556
519 std::string AudioManagerMac::GetAssociatedOutputDeviceID( 557 std::string AudioManagerMac::GetAssociatedOutputDeviceID(
520 const std::string& input_device_id) { 558 const std::string& input_device_id) {
521 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 559 DCHECK(task_runner_->BelongsToCurrentThread());
522 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); 560 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
523 if (device == kAudioObjectUnknown) 561 if (device == kAudioObjectUnknown)
524 return std::string(); 562 return std::string();
525 563
526 UInt32 size = 0; 564 UInt32 size = 0;
527 AudioObjectPropertyAddress pa = { 565 AudioObjectPropertyAddress pa = {
528 kAudioDevicePropertyRelatedDevices, 566 kAudioDevicePropertyRelatedDevices,
529 kAudioDevicePropertyScopeOutput, 567 kAudioDevicePropertyScopeOutput,
530 kAudioObjectPropertyElementMaster 568 kAudioObjectPropertyElementMaster
531 }; 569 };
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 // rates on OSX. 674 // rates on OSX.
637 current_sample_rate_ = params.sample_rate(); 675 current_sample_rate_ = params.sample_rate();
638 } 676 }
639 677
640 AUHALStream* stream = new AUHALStream(this, params, device); 678 AUHALStream* stream = new AUHALStream(this, params, device);
641 output_streams_.push_back(stream); 679 output_streams_.push_back(stream);
642 return stream; 680 return stream;
643 } 681 }
644 682
645 std::string AudioManagerMac::GetDefaultOutputDeviceID() { 683 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
646 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 684 DCHECK(task_runner_->BelongsToCurrentThread());
647 AudioDeviceID device_id = kAudioObjectUnknown; 685 AudioDeviceID device_id = kAudioObjectUnknown;
648 if (!GetDefaultOutputDevice(&device_id)) 686 if (!GetDefaultOutputDevice(&device_id))
649 return std::string(); 687 return std::string();
650 688
651 const AudioObjectPropertyAddress property_address = { 689 const AudioObjectPropertyAddress property_address = {
652 kAudioDevicePropertyDeviceUID, 690 kAudioDevicePropertyDeviceUID,
653 kAudioObjectPropertyScopeGlobal, 691 kAudioObjectPropertyScopeGlobal,
654 kAudioObjectPropertyElementMaster 692 kAudioObjectPropertyElementMaster
655 }; 693 };
656 CFStringRef device_uid = NULL; 694 CFStringRef device_uid = NULL;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 channel_layout = CHANNEL_LAYOUT_DISCRETE; 773 channel_layout = CHANNEL_LAYOUT_DISCRETE;
736 } 774 }
737 775
738 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 776 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
739 hardware_sample_rate, 16, buffer_size); 777 hardware_sample_rate, 16, buffer_size);
740 params.set_channels_for_discrete(output_channels); 778 params.set_channels_for_discrete(output_channels);
741 return params; 779 return params;
742 } 780 }
743 781
744 void AudioManagerMac::InitializeOnAudioThread() { 782 void AudioManagerMac::InitializeOnAudioThread() {
745 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 783 DCHECK(task_runner_->BelongsToCurrentThread());
746 power_observer_.reset(new AudioPowerObserver()); 784 power_observer_.reset(new AudioPowerObserver());
747 } 785 }
748 786
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
749 void AudioManagerMac::HandleDeviceChanges() { 806 void AudioManagerMac::HandleDeviceChanges() {
750 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 807 DCHECK(task_runner_->BelongsToCurrentThread());
751 const int new_sample_rate = HardwareSampleRate(); 808 const int new_sample_rate = HardwareSampleRate();
752 AudioDeviceID new_output_device; 809 AudioDeviceID new_output_device;
753 GetDefaultOutputDevice(&new_output_device); 810 GetDefaultOutputDevice(&new_output_device);
754 811
755 if (current_sample_rate_ == new_sample_rate && 812 if (current_sample_rate_ == new_sample_rate &&
756 current_output_device_ == new_output_device) { 813 current_output_device_ == new_output_device) {
757 return; 814 return;
758 } 815 }
759 816
760 current_sample_rate_ = new_sample_rate; 817 current_sample_rate_ = new_sample_rate;
(...skipping 21 matching lines...) Expand all
782 if (sample_rate <= 96000) 839 if (sample_rate <= 96000)
783 buffer_size = 2 * kMinimumInputOutputBufferSize; 840 buffer_size = 2 * kMinimumInputOutputBufferSize;
784 else if (sample_rate <= 192000) 841 else if (sample_rate <= 192000)
785 buffer_size = 4 * kMinimumInputOutputBufferSize; 842 buffer_size = 4 * kMinimumInputOutputBufferSize;
786 } 843 }
787 844
788 return buffer_size; 845 return buffer_size;
789 } 846 }
790 847
791 bool AudioManagerMac::IsSuspending() const { 848 bool AudioManagerMac::IsSuspending() const {
792 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 849 DCHECK(task_runner_->BelongsToCurrentThread());
793 return power_observer_->IsSuspending(); 850 return power_observer_->IsSuspending();
794 } 851 }
795 852
796 bool AudioManagerMac::ShouldDeferStreamStart() const { 853 bool AudioManagerMac::ShouldDeferStreamStart() const {
797 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 854 DCHECK(task_runner_->BelongsToCurrentThread());
798 return power_observer_->ShouldDeferStreamStart(); 855 return power_observer_->ShouldDeferStreamStart();
799 } 856 }
800 857
801 bool AudioManagerMac::IsOnBatteryPower() const { 858 bool AudioManagerMac::IsOnBatteryPower() const {
802 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 859 DCHECK(task_runner_->BelongsToCurrentThread());
803 return power_observer_->IsOnBatteryPower(); 860 return power_observer_->IsOnBatteryPower();
804 } 861 }
805 862
806 size_t AudioManagerMac::GetNumberOfResumeNotifications() const { 863 size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
807 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 864 DCHECK(task_runner_->BelongsToCurrentThread());
808 return power_observer_->num_resume_notifications(); 865 return power_observer_->num_resume_notifications();
809 } 866 }
810 867
811 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, 868 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id,
812 AudioUnit audio_unit, 869 AudioUnit audio_unit,
813 AudioUnitElement element, 870 AudioUnitElement element,
814 size_t desired_buffer_size, 871 size_t desired_buffer_size,
815 bool* size_was_changed, 872 bool* size_was_changed,
816 size_t* io_buffer_frame_size) { 873 size_t* io_buffer_frame_size) {
817 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 874 DCHECK(task_runner_->BelongsToCurrentThread());
818 const bool is_input = (element == 1); 875 const bool is_input = (element == 1);
819 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id 876 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id
820 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec 877 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
821 << desired_buffer_size << ")"; 878 << desired_buffer_size << ")";
822 879
823 *size_was_changed = false; 880 *size_was_changed = false;
824 *io_buffer_frame_size = 0; 881 *io_buffer_frame_size = 0;
825 882
826 // Log the device name (and id) for debugging purposes. 883 // Log the device name (and id) for debugging purposes.
827 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input); 884 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 basic_input_streams_.end(), 984 basic_input_streams_.end(),
928 stream); 985 stream);
929 if (stream_it == basic_input_streams_.end()) 986 if (stream_it == basic_input_streams_.end())
930 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream)); 987 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
931 else 988 else
932 basic_input_streams_.erase(stream_it); 989 basic_input_streams_.erase(stream_it);
933 990
934 AudioManagerBase::ReleaseInputStream(stream); 991 AudioManagerBase::ReleaseInputStream(stream);
935 } 992 }
936 993
937 ScopedAudioManagerPtr CreateAudioManager( 994 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
938 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 995 return new AudioManagerMac(audio_log_factory);
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));
944 } 996 }
945 997
946 } // namespace media 998 } // 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