Chromium Code Reviews| Index: media/audio/mac/audio_manager_mac.cc |
| diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc |
| index 0b29dcc13967e6c15caf57f412181f1cb3a8e581..927224f152fcd180aab3196a741be6d39f0e97ca 100644 |
| --- a/media/audio/mac/audio_manager_mac.cc |
| +++ b/media/audio/mac/audio_manager_mac.cc |
| @@ -4,7 +4,8 @@ |
| #include "media/audio/mac/audio_manager_mac.h" |
| -#include <stdint.h> |
| +#include <algorithm> |
| +#include <vector> |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| @@ -917,9 +918,113 @@ bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, |
| return (result == noErr); |
| } |
| +#if !defined(NDEBUG) |
| +void AudioManagerMac::PrintOutputBufferSizes() { |
| + for (auto* stream : output_streams_) { |
| + DVLOG(1) << "[id=0x" << std::hex << stream->device_id() << "] " << std::dec |
| + << "requested: " << stream->requested_buffer_size() << ", " |
| + << "actual: " << stream->actual_buffer_size(); |
| + } |
| +} |
| +#endif // !defined(NDEBUG) |
| + |
| +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.
|
| + DVLOG(1) << "IncreaseIOBufferSizeIfPossible(id=0x" << std::hex << device_id |
| + << ")"; |
| + // Build a map of buffer sizes [requested, actual] from all existing output |
| + // audio streams using the specified |device_id|. |
| + std::map<size_t, size_t> size_map; |
| + std::list<AUHALStream*> output_streams; |
| + for (auto* stream : output_streams_) { |
| + if (stream->device_id() == device_id) { |
| + 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.
|
| + output_streams.push_back(stream); |
| + } |
| + } |
| + |
| + if (size_map.empty()) { |
| + DVLOG(1) << "No action since there is no active stream for given device id"; |
| + return false; |
| + } |
| + |
| + // The elements are sorted according to the key object which is the |
| + // requested buffer size in this case. The associated value is the actual |
| + // buffer size and if these are equal for the first pair in the lists it means |
| + // that we are already using the lowest possible buffer size. Hence, it is not |
| + // possible to do any increase. |
| + if (size_map.begin()->first == size_map.begin()->second) { |
| + DVLOG(1) << "No action since lowest possible size is already in use: " |
| + << size_map.begin()->first; |
| + return false; |
| + } |
| + |
| + // Add a handy log message to track the current status before trying to make |
| + // a change. |
| + for (auto it = size_map.begin(); it != size_map.end(); ++it) { |
| + DVLOG(1) << "requested:" << it->first << " actual: " << it->second; |
| + } |
| + |
| + // First pair in the map now contains the lowest requested buffer size that |
| + // is not yet in use since another stream required a smaller value. It should |
| + // now be safe to increase the I/O buffer size to this new (higher) value. |
| + // Doing so will save system resources. |
| + const size_t increased_io_buffer_frame_size = size_map.begin()->first; |
| + |
| + bool size_was_changed = false; |
| + size_t io_buffer_frame_size = 0; |
| + bool result = false; |
| + for (auto* stream : output_streams) { |
| + result = MaybeChangeBufferSize(device_id, stream->audio_unit(), 0, |
| + increased_io_buffer_frame_size, |
| + &size_was_changed, &io_buffer_frame_size); |
| + DCHECK(size_was_changed); |
| + DCHECK_EQ(io_buffer_frame_size, increased_io_buffer_frame_size); |
| + } |
| + |
| + return true; |
| +} |
| + |
| +bool AudioManagerMac::AudioDeviceIsUsedForInput(AudioDeviceID device_id) { |
| + if (!basic_input_streams_.empty()) { |
| + // For Audio Queues and in the default case (Mac OS X), the audio comes |
| + // from the system’s default audio input device as set by a user in System |
| + // Preferences. |
| + AudioDeviceID default_id; |
| + GetDefaultDevice(&default_id, true); |
| + if (default_id == device_id) |
| + return true; |
| + } |
| + |
| + // Each low latency streams has its own device ID. |
| + for (auto* stream : low_latency_input_streams_) { |
| + if (stream->device_id() == device_id) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| 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.
|
| + const AudioDeviceID id = static_cast<AUHALStream*>(stream)->device_id(); |
| + DVLOG(1) << "Closing down output stream with id=0x" << std::hex << id; |
| + |
| + // Start by closing down the specified output stream. |
| output_streams_.remove(static_cast<AUHALStream*>(stream)); |
| +#if !defined(NDEBUG) |
| + PrintOutputBufferSizes(); |
| +#endif // !defined(NDEBUG) |
| AudioManagerBase::ReleaseOutputStream(stream); |
| + |
| + // Prevent attempt to alter buffer size if the released stream was the last |
| + // output stream. |
| + if (output_streams_.empty()) |
| + return; |
| + |
| + if (!AudioDeviceIsUsedForInput(id)) { |
| + // The current audio device is not used for input. See if it is possible to |
| + // increase the IO buffer size (saves power) given the remaining output |
| + // audio streams and their buffer size requirements. |
| + IncreaseIOBufferSizeIfPossible(id); |
| + } |
| } |
| void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { |