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

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

Issue 1936553002: Revert of Restores larger output buffer size when output stream requiring smaller size is closed (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 <algorithm> 7 #include <stdint.h>
8 #include <limits>
9 #include <vector>
10 8
11 #include "base/bind.h" 9 #include "base/bind.h"
12 #include "base/command_line.h" 10 #include "base/command_line.h"
13 #include "base/mac/mac_logging.h" 11 #include "base/mac/mac_logging.h"
14 #include "base/mac/scoped_cftyperef.h" 12 #include "base/mac/scoped_cftyperef.h"
15 #include "base/macros.h" 13 #include "base/macros.h"
16 #include "base/memory/free_deleter.h" 14 #include "base/memory/free_deleter.h"
17 #include "base/power_monitor/power_monitor.h" 15 #include "base/power_monitor/power_monitor.h"
18 #include "base/power_monitor/power_observer.h" 16 #include "base/power_monitor/power_observer.h"
19 #include "base/strings/sys_string_conversions.h" 17 #include "base/strings/sys_string_conversions.h"
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } 474 }
477 475
478 void AudioManagerMac::GetAudioOutputDeviceNames( 476 void AudioManagerMac::GetAudioOutputDeviceNames(
479 media::AudioDeviceNames* device_names) { 477 media::AudioDeviceNames* device_names) {
480 DCHECK(device_names->empty()); 478 DCHECK(device_names->empty());
481 GetAudioDeviceInfo(false, device_names); 479 GetAudioDeviceInfo(false, device_names);
482 } 480 }
483 481
484 AudioParameters AudioManagerMac::GetInputStreamParameters( 482 AudioParameters AudioManagerMac::GetInputStreamParameters(
485 const std::string& device_id) { 483 const std::string& device_id) {
486 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
487 AudioDeviceID device = GetAudioDeviceIdByUId(true, device_id); 484 AudioDeviceID device = GetAudioDeviceIdByUId(true, device_id);
488 if (device == kAudioObjectUnknown) { 485 if (device == kAudioObjectUnknown) {
489 DLOG(ERROR) << "Invalid device " << device_id; 486 DLOG(ERROR) << "Invalid device " << device_id;
490 return AudioParameters( 487 return AudioParameters(
491 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 488 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
492 kFallbackSampleRate, 16, ChooseBufferSize(true, kFallbackSampleRate)); 489 kFallbackSampleRate, 16, ChooseBufferSize(true, kFallbackSampleRate));
493 } 490 }
494 491
495 int channels = 0; 492 int channels = 0;
496 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; 493 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 if (default_device == *iter) 589 if (default_device == *iter)
593 return *iter; 590 return *iter;
594 } 591 }
595 592
596 // Failed to figure out which is the matching device, return an empty string. 593 // Failed to figure out which is the matching device, return an empty string.
597 return std::string(); 594 return std::string();
598 } 595 }
599 596
600 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream( 597 AudioOutputStream* AudioManagerMac::MakeLinearOutputStream(
601 const AudioParameters& params) { 598 const AudioParameters& params) {
602 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
603 return MakeLowLatencyOutputStream(params, std::string()); 599 return MakeLowLatencyOutputStream(params, std::string());
604 } 600 }
605 601
606 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream( 602 AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
607 const AudioParameters& params, 603 const AudioParameters& params,
608 const std::string& device_id) { 604 const std::string& device_id) {
609 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
610 bool device_listener_first_init = false; 605 bool device_listener_first_init = false;
611 // Lazily create the audio device listener on the first stream creation, 606 // Lazily create the audio device listener on the first stream creation,
612 // even if getting an audio device fails. Otherwise, if we have 0 audio 607 // even if getting an audio device fails. Otherwise, if we have 0 audio
613 // devices, the listener will never be initialized, and new valid devices 608 // devices, the listener will never be initialized, and new valid devices
614 // will never be detected. 609 // will never be detected.
615 if (!output_device_listener_) { 610 if (!output_device_listener_) {
616 // NOTE: Use BindToCurrentLoop() to ensure the callback is always PostTask'd 611 // NOTE: Use BindToCurrentLoop() to ensure the callback is always PostTask'd
617 // even if OSX calls us on the right thread. Some CoreAudio drivers will 612 // even if OSX calls us on the right thread. Some CoreAudio drivers will
618 // fire the callbacks during stream creation, leading to re-entrancy issues 613 // fire the callbacks during stream creation, leading to re-entrancy issues
619 // otherwise. See http://crbug.com/349604 614 // otherwise. See http://crbug.com/349604
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 return std::string(); 663 return std::string();
669 664
670 std::string ret(base::SysCFStringRefToUTF8(device_uid)); 665 std::string ret(base::SysCFStringRefToUTF8(device_uid));
671 CFRelease(device_uid); 666 CFRelease(device_uid);
672 667
673 return ret; 668 return ret;
674 } 669 }
675 670
676 AudioInputStream* AudioManagerMac::MakeLinearInputStream( 671 AudioInputStream* AudioManagerMac::MakeLinearInputStream(
677 const AudioParameters& params, const std::string& device_id) { 672 const AudioParameters& params, const std::string& device_id) {
678 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
679 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 673 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
680 AudioInputStream* stream = new PCMQueueInAudioInputStream(this, params); 674 AudioInputStream* stream = new PCMQueueInAudioInputStream(this, params);
681 basic_input_streams_.push_back(stream); 675 basic_input_streams_.push_back(stream);
682 return stream; 676 return stream;
683 } 677 }
684 678
685 AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream( 679 AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream(
686 const AudioParameters& params, const std::string& device_id) { 680 const AudioParameters& params, const std::string& device_id) {
687 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
688 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 681 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
689 // Gets the AudioDeviceID that refers to the AudioInputDevice with the device 682 // Gets the AudioDeviceID that refers to the AudioInputDevice with the device
690 // unique id. This AudioDeviceID is used to set the device for Audio Unit. 683 // unique id. This AudioDeviceID is used to set the device for Audio Unit.
691 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id); 684 AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id);
692 AUAudioInputStream* stream = NULL; 685 AUAudioInputStream* stream = NULL;
693 if (audio_device_id != kAudioObjectUnknown) { 686 if (audio_device_id != kAudioObjectUnknown) {
694 stream = new AUAudioInputStream(this, params, audio_device_id); 687 stream = new AUAudioInputStream(this, params, audio_device_id);
695 low_latency_input_streams_.push_back(stream); 688 low_latency_input_streams_.push_back(stream);
696 } 689 }
697 690
698 return stream; 691 return stream;
699 } 692 }
700 693
701 AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters( 694 AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters(
702 const std::string& output_device_id, 695 const std::string& output_device_id,
703 const AudioParameters& input_params) { 696 const AudioParameters& input_params) {
704 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
705 const AudioDeviceID device = GetAudioDeviceIdByUId(false, output_device_id); 697 const AudioDeviceID device = GetAudioDeviceIdByUId(false, output_device_id);
706 if (device == kAudioObjectUnknown) { 698 if (device == kAudioObjectUnknown) {
707 DLOG(ERROR) << "Invalid output device " << output_device_id; 699 DLOG(ERROR) << "Invalid output device " << output_device_id;
708 return input_params.IsValid() ? input_params : AudioParameters( 700 return input_params.IsValid() ? input_params : AudioParameters(
709 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 701 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
710 kFallbackSampleRate, 16, ChooseBufferSize(false, kFallbackSampleRate)); 702 kFallbackSampleRate, 16, ChooseBufferSize(false, kFallbackSampleRate));
711 } 703 }
712 704
713 const bool has_valid_input_params = input_params.IsValid(); 705 const bool has_valid_input_params = input_params.IsValid();
714 const int hardware_sample_rate = HardwareSampleRateForDevice(device); 706 const int hardware_sample_rate = HardwareSampleRateForDevice(device);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 848
857 // Check if a buffer size change is required. If the caller asks for a 849 // Check if a buffer size change is required. If the caller asks for a
858 // reduced size (|desired_buffer_size| < |buffer_size|), the new lower size 850 // reduced size (|desired_buffer_size| < |buffer_size|), the new lower size
859 // will be set. For larger buffer sizes, we have to perform some checks to 851 // will be set. For larger buffer sizes, we have to perform some checks to
860 // see if the size can actually be changed. If there is any other active 852 // see if the size can actually be changed. If there is any other active
861 // streams on the same device, either input or output, a larger size than 853 // streams on the same device, either input or output, a larger size than
862 // their requested buffer size can't be set. The reason is that an existing 854 // their requested buffer size can't be set. The reason is that an existing
863 // stream can't handle buffer size larger than its requested buffer size. 855 // stream can't handle buffer size larger than its requested buffer size.
864 // See http://crbug.com/428706 for a reason why. 856 // See http://crbug.com/428706 for a reason why.
865 857
866 // Update map of actual buffer size given device id if the map is empty.
867 // Stores a base value that most likely be modified as last action in this
868 // method.
869 if (!is_input && output_io_buffer_size_map_.count(device_id) == 0)
870 output_io_buffer_size_map_[device_id] = buffer_size;
871
872 if (buffer_size == desired_buffer_size) 858 if (buffer_size == desired_buffer_size)
873 return true; 859 return true;
874 860
875 if (desired_buffer_size > buffer_size) { 861 if (desired_buffer_size > buffer_size) {
876 // Do NOT set the buffer size if there is another output stream using 862 // Do NOT set the buffer size if there is another output stream using
877 // the same device with a smaller requested buffer size. 863 // the same device with a smaller requested buffer size.
878 // Note, for the caller stream, its requested_buffer_size() will be the same 864 // Note, for the caller stream, its requested_buffer_size() will be the same
879 // as |desired_buffer_size|, so it won't return true due to comparing with 865 // as |desired_buffer_size|, so it won't return true due to comparing with
880 // itself. 866 // itself.
881 for (auto* stream : output_streams_) { 867 for (auto* stream : output_streams_) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 kAudioUnitScope_Global, 0, &buffer_size, 905 kAudioUnitScope_Global, 0, &buffer_size,
920 sizeof(buffer_size)); 906 sizeof(buffer_size));
921 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 907 OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
922 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed. " 908 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed. "
923 << "Size:: " << buffer_size; 909 << "Size:: " << buffer_size;
924 *size_was_changed = (result == noErr); 910 *size_was_changed = (result == noErr);
925 DVLOG_IF(1, result == noErr) << "IO buffer size changed to: " << buffer_size; 911 DVLOG_IF(1, result == noErr) << "IO buffer size changed to: " << buffer_size;
926 // Store the currently used (after a change) I/O buffer frame size. 912 // Store the currently used (after a change) I/O buffer frame size.
927 *io_buffer_frame_size = buffer_size; 913 *io_buffer_frame_size = buffer_size;
928 914
929 // If the size was changed, update the actual output buffer size used for the
930 // given device ID.
931 DCHECK(!output_io_buffer_size_map_.empty());
932 if (!is_input && (result == noErr)) {
933 output_io_buffer_size_map_[device_id] = buffer_size;
934 }
935
936 return (result == noErr); 915 return (result == noErr);
937 } 916 }
938 917
939 bool AudioManagerMac::IncreaseIOBufferSizeIfPossible(AudioDeviceID device_id) {
940 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
941 DVLOG(1) << "IncreaseIOBufferSizeIfPossible(id=0x" << std::hex << device_id
942 << ")";
943 // Start by storing the actual I/O buffer size. Then scan all active output
944 // streams using the specified |device_id| and find the minimum requested
945 // buffer size. In addition, store a reference to the audio unit of the first
946 // output stream using |device_id|.
947 DCHECK(!output_io_buffer_size_map_.empty());
948 // All active output streams use the same actual I/O buffer size given
949 // a unique device ID.
950 const size_t& actual_size = output_io_buffer_size_map_[device_id];
951 AudioUnit audio_unit;
952 size_t min_requested_size = std::numeric_limits<std::size_t>::max();
953 for (auto* stream : output_streams_) {
954 if (stream->device_id() == device_id) {
955 if (min_requested_size == std::numeric_limits<std::size_t>::max()) {
956 // Store reference to the first audio unit using the specified ID.
957 audio_unit = stream->audio_unit();
958 }
959 if (stream->requested_buffer_size() < min_requested_size)
960 min_requested_size = stream->requested_buffer_size();
961 DVLOG(1) << "requested:" << stream->requested_buffer_size()
962 << " actual: " << actual_size;
963 }
964 }
965
966 if (min_requested_size == std::numeric_limits<std::size_t>::max()) {
967 DVLOG(1) << "No action since there is no active stream for given device id";
968 return false;
969 }
970
971 // It is only possible to revert to a larger buffer size if the lowest
972 // requested is not in use. Example: if the actual I/O buffer size is 256 and
973 // at least one output stream has asked for 256 as its buffer size, we can't
974 // start using a larger I/O buffer size.
975 DCHECK_GE(min_requested_size, actual_size);
976 if (min_requested_size == actual_size) {
977 DVLOG(1) << "No action since lowest possible size is already in use: "
978 << actual_size;
979 return false;
980 }
981
982 // It should now be safe to increase the I/O buffer size to a new (higher)
983 // value using the |min_requested_size|. Doing so will save system resources.
984 // All active output streams with the same |device_id| are affected by this
985 // change but it is only required to apply the change to one of the streams.
986 DVLOG(1) << "min_requested_size: " << min_requested_size;
987 bool size_was_changed = false;
988 size_t io_buffer_frame_size = 0;
989 bool result =
990 MaybeChangeBufferSize(device_id, audio_unit, 0, min_requested_size,
991 &size_was_changed, &io_buffer_frame_size);
992 DCHECK_EQ(io_buffer_frame_size, min_requested_size);
993 DCHECK(size_was_changed);
994 return result;
995 }
996
997 bool AudioManagerMac::AudioDeviceIsUsedForInput(AudioDeviceID device_id) {
998 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
999 if (!basic_input_streams_.empty()) {
1000 // For Audio Queues and in the default case (Mac OS X), the audio comes
1001 // from the system’s default audio input device as set by a user in System
1002 // Preferences.
1003 AudioDeviceID default_id;
1004 GetDefaultDevice(&default_id, true);
1005 if (default_id == device_id)
1006 return true;
1007 }
1008
1009 // Each low latency streams has its own device ID.
1010 for (auto* stream : low_latency_input_streams_) {
1011 if (stream->device_id() == device_id)
1012 return true;
1013 }
1014 return false;
1015 }
1016
1017 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) { 918 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) {
1018 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
1019 const AudioDeviceID id = static_cast<AUHALStream*>(stream)->device_id();
1020 DVLOG(1) << "Closing down output stream with id=0x" << std::hex << id;
1021
1022 // Start by closing down the specified output stream.
1023 output_streams_.remove(static_cast<AUHALStream*>(stream)); 919 output_streams_.remove(static_cast<AUHALStream*>(stream));
1024 AudioManagerBase::ReleaseOutputStream(stream); 920 AudioManagerBase::ReleaseOutputStream(stream);
1025
1026 // Prevent attempt to alter buffer size if the released stream was the last
1027 // output stream.
1028 if (output_streams_.empty())
1029 return;
1030
1031 if (!AudioDeviceIsUsedForInput(id)) {
1032 // The current audio device is not used for input. See if it is possible to
1033 // increase the IO buffer size (saves power) given the remaining output
1034 // audio streams and their buffer size requirements.
1035 IncreaseIOBufferSizeIfPossible(id);
1036 }
1037 } 921 }
1038 922
1039 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { 923 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) {
1040 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
1041 auto stream_it = std::find(basic_input_streams_.begin(), 924 auto stream_it = std::find(basic_input_streams_.begin(),
1042 basic_input_streams_.end(), 925 basic_input_streams_.end(),
1043 stream); 926 stream);
1044 if (stream_it == basic_input_streams_.end()) 927 if (stream_it == basic_input_streams_.end())
1045 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream)); 928 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
1046 else 929 else
1047 basic_input_streams_.erase(stream_it); 930 basic_input_streams_.erase(stream_it);
1048 931
1049 AudioManagerBase::ReleaseInputStream(stream); 932 AudioManagerBase::ReleaseInputStream(stream);
1050 } 933 }
1051 934
1052 ScopedAudioManagerPtr CreateAudioManager( 935 ScopedAudioManagerPtr CreateAudioManager(
1053 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 936 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
1054 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, 937 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
1055 AudioLogFactory* audio_log_factory) { 938 AudioLogFactory* audio_log_factory) {
1056 return ScopedAudioManagerPtr( 939 return ScopedAudioManagerPtr(
1057 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner), 940 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner),
1058 audio_log_factory)); 941 audio_log_factory));
1059 } 942 }
1060 943
1061 } // namespace media 944 } // 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