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

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

Issue 1903753002: 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: Improvements based on tests where default output device was changed 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 <algorithm>
8 #include <vector>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/mac/mac_logging.h" 12 #include "base/mac/mac_logging.h"
12 #include "base/mac/scoped_cftyperef.h" 13 #include "base/mac/scoped_cftyperef.h"
13 #include "base/macros.h" 14 #include "base/macros.h"
14 #include "base/memory/free_deleter.h" 15 #include "base/memory/free_deleter.h"
15 #include "base/power_monitor/power_monitor.h" 16 #include "base/power_monitor/power_monitor.h"
16 #include "base/power_monitor/power_observer.h" 17 #include "base/power_monitor/power_observer.h"
17 #include "base/strings/sys_string_conversions.h" 18 #include "base/strings/sys_string_conversions.h"
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 // see if the size can actually be changed. If there is any other active 855 // see if the size can actually be changed. If there is any other active
855 // streams on the same device, either input or output, a larger size than 856 // streams on the same device, either input or output, a larger size than
856 // their requested buffer size can't be set. The reason is that an existing 857 // their requested buffer size can't be set. The reason is that an existing
857 // stream can't handle buffer size larger than its requested buffer size. 858 // stream can't handle buffer size larger than its requested buffer size.
858 // See http://crbug.com/428706 for a reason why. 859 // See http://crbug.com/428706 for a reason why.
859 860
860 if (buffer_size == desired_buffer_size) 861 if (buffer_size == desired_buffer_size)
861 return true; 862 return true;
862 863
863 if (desired_buffer_size > buffer_size) { 864 if (desired_buffer_size > buffer_size) {
864 // Do NOT set the buffer size if there is another output stream using 865 // Do NOT set the buffer size if there is another output stream using
o1ka 2016/04/22 12:24:24 May we probably skip those checks when called from
henrika (OOO until Aug 14) 2016/04/25 13:54:13 Latest implementation only calls it once for all s
o1ka 2016/04/25 15:13:26 Acknowledged.
865 // the same device with a smaller requested buffer size. 866 // the same device with a smaller requested buffer size.
866 // Note, for the caller stream, its requested_buffer_size() will be the same 867 // Note, for the caller stream, its requested_buffer_size() will be the same
867 // as |desired_buffer_size|, so it won't return true due to comparing with 868 // as |desired_buffer_size|, so it won't return true due to comparing with
868 // itself. 869 // itself.
869 for (auto* stream : output_streams_) { 870 for (auto* stream : output_streams_) {
870 if (stream->device_id() == device_id && 871 if (stream->device_id() == device_id &&
871 stream->requested_buffer_size() < desired_buffer_size) { 872 stream->requested_buffer_size() < desired_buffer_size) {
872 return true; 873 return true;
873 } 874 }
874 } 875 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed. " 911 << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed. "
911 << "Size:: " << buffer_size; 912 << "Size:: " << buffer_size;
912 *size_was_changed = (result == noErr); 913 *size_was_changed = (result == noErr);
913 DVLOG_IF(1, result == noErr) << "IO buffer size changed to: " << buffer_size; 914 DVLOG_IF(1, result == noErr) << "IO buffer size changed to: " << buffer_size;
914 // Store the currently used (after a change) I/O buffer frame size. 915 // Store the currently used (after a change) I/O buffer frame size.
915 *io_buffer_frame_size = buffer_size; 916 *io_buffer_frame_size = buffer_size;
916 917
917 return (result == noErr); 918 return (result == noErr);
918 } 919 }
919 920
921 #if !defined(NDEBUG)
922 void AudioManagerMac::PrintOutputBufferSizes() {
923 for (auto* stream : output_streams_) {
924 DVLOG(1) << "[id=0x" << std::hex << stream->device_id() << "] " << std::dec
925 << "requested: " << stream->requested_buffer_size() << ", "
926 << "actual: " << stream->actual_buffer_size();
927 }
928 }
929 #endif // !defined(NDEBUG)
930
931 bool AudioManagerMac::IncreaseIOBufferSizeIfPossible(AudioDeviceID device_id) {
o1ka 2016/04/22 12:24:24 Add a thread check for clarity?
henrika (OOO until Aug 14) 2016/04/25 13:54:13 Done.
932 DVLOG(1) << "IncreaseIOBufferSizeIfPossible(id=0x" << std::hex << device_id
933 << ")";
934 // Build a map of buffer sizes [requested, actual] from all existing output
935 // audio streams using the specified |device_id|.
936 std::map<size_t, size_t> size_map;
937 std::list<AUHALStream*> output_streams;
938 for (auto* stream : output_streams_) {
939 if (stream->device_id() == device_id) {
940 size_map[stream->requested_buffer_size()] = stream->actual_buffer_size();
o1ka 2016/04/22 12:24:24 Shouldn't it be that all the streams have the same
henrika (OOO until Aug 14) 2016/04/25 13:54:13 Now changed.
941 output_streams.push_back(stream);
942 }
943 }
944
945 if (size_map.empty()) {
946 DVLOG(1) << "No action since there is no active stream for given device id";
947 return false;
948 }
949
950 // The elements are sorted according to the key object which is the
951 // requested buffer size in this case. The associated value is the actual
952 // buffer size and if these are equal for the first pair in the lists it means
953 // that we are already using the lowest possible buffer size. Hence, it is not
954 // possible to do any increase.
955 if (size_map.begin()->first == size_map.begin()->second) {
956 DVLOG(1) << "No action since lowest possible size is already in use: "
957 << size_map.begin()->first;
958 return false;
959 }
960
961 // Add a handy log message to track the current status before trying to make
962 // a change.
963 for (auto it = size_map.begin(); it != size_map.end(); ++it) {
964 DVLOG(1) << "requested:" << it->first << " actual: " << it->second;
965 }
966
967 // First pair in the map now contains the lowest requested buffer size that
968 // is not yet in use since another stream required a smaller value. It should
969 // now be safe to increase the I/O buffer size to this new (higher) value.
970 // Doing so will save system resources.
971 const size_t increased_io_buffer_frame_size = size_map.begin()->first;
972
973 bool size_was_changed = false;
974 size_t io_buffer_frame_size = 0;
975 bool result = false;
976 for (auto* stream : output_streams) {
977 result = MaybeChangeBufferSize(device_id, stream->audio_unit(), 0,
978 increased_io_buffer_frame_size,
979 &size_was_changed, &io_buffer_frame_size);
980 DCHECK(size_was_changed);
981 DCHECK_EQ(io_buffer_frame_size, increased_io_buffer_frame_size);
982 }
983
984 return true;
985 }
986
987 bool AudioManagerMac::AudioDeviceIsUsedForInput(AudioDeviceID device_id) {
988 if (!basic_input_streams_.empty()) {
989 // For Audio Queues and in the default case (Mac OS X), the audio comes
990 // from the system’s default audio input device as set by a user in System
991 // Preferences.
992 AudioDeviceID default_id;
993 GetDefaultDevice(&default_id, true);
994 if (default_id == device_id)
995 return true;
996 }
997
998 // Each low latency streams has its own device ID.
999 for (auto* stream : low_latency_input_streams_) {
1000 if (stream->device_id() == device_id)
1001 return true;
1002 }
1003 return false;
1004 }
1005
920 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) { 1006 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) {
o1ka 2016/04/22 12:24:24 I assume it can't race with MakeLowLatencyOutputSt
henrika (OOO until Aug 14) 2016/04/25 13:54:13 Added thread checks.
1007 const AudioDeviceID id = static_cast<AUHALStream*>(stream)->device_id();
1008 DVLOG(1) << "Closing down output stream with id=0x" << std::hex << id;
1009
1010 // Start by closing down the specified output stream.
921 output_streams_.remove(static_cast<AUHALStream*>(stream)); 1011 output_streams_.remove(static_cast<AUHALStream*>(stream));
1012 #if !defined(NDEBUG)
1013 PrintOutputBufferSizes();
1014 #endif // !defined(NDEBUG)
922 AudioManagerBase::ReleaseOutputStream(stream); 1015 AudioManagerBase::ReleaseOutputStream(stream);
1016
1017 // Prevent attempt to alter buffer size if the released stream was the last
1018 // output stream.
1019 if (output_streams_.empty())
1020 return;
1021
1022 if (!AudioDeviceIsUsedForInput(id)) {
1023 // The current audio device is not used for input. See if it is possible to
1024 // increase the IO buffer size (saves power) given the remaining output
1025 // audio streams and their buffer size requirements.
1026 IncreaseIOBufferSizeIfPossible(id);
1027 }
923 } 1028 }
924 1029
925 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { 1030 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) {
926 auto stream_it = std::find(basic_input_streams_.begin(), 1031 auto stream_it = std::find(basic_input_streams_.begin(),
927 basic_input_streams_.end(), 1032 basic_input_streams_.end(),
928 stream); 1033 stream);
929 if (stream_it == basic_input_streams_.end()) 1034 if (stream_it == basic_input_streams_.end())
930 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream)); 1035 low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
931 else 1036 else
932 basic_input_streams_.erase(stream_it); 1037 basic_input_streams_.erase(stream_it);
933 1038
934 AudioManagerBase::ReleaseInputStream(stream); 1039 AudioManagerBase::ReleaseInputStream(stream);
935 } 1040 }
936 1041
937 ScopedAudioManagerPtr CreateAudioManager( 1042 ScopedAudioManagerPtr CreateAudioManager(
938 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 1043 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
939 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, 1044 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
940 AudioLogFactory* audio_log_factory) { 1045 AudioLogFactory* audio_log_factory) {
941 return ScopedAudioManagerPtr( 1046 return ScopedAudioManagerPtr(
942 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner), 1047 new AudioManagerMac(std::move(task_runner), std::move(worker_task_runner),
943 audio_log_factory)); 1048 audio_log_factory));
944 } 1049 }
945 1050
946 } // namespace media 1051 } // namespace media
OLDNEW
« media/audio/mac/audio_manager_mac.h ('K') | « 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