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
3 // found in the LICENSE file.
4 #include "media/audio/mac/audio_low_latency_input_mac.h"
5 
6 #include <CoreAudio/AudioHardware.h>
7 #include <CoreServices/CoreServices.h>
8 #include <dlfcn.h>
9 #include <mach-o/loader.h>
10 #include <mach/mach.h>
11 #include <string>
12 
13 #include "base/bind.h"
14 #include "base/logging.h"
15 #include "base/mac/foundation_util.h"
16 #include "base/mac/mac_logging.h"
17 #include "base/mac/mac_util.h"
18 #include "base/mac/scoped_cftyperef.h"
19 #include "base/mac/scoped_mach_port.h"
20 #include "base/metrics/histogram_functions.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/strings/strcat.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/sys_string_conversions.h"
25 #include "base/system/sys_info.h"
26 #include "base/time/time.h"
27 #include "base/trace_event/trace_event.h"
28 #include "media/audio/mac/core_audio_util_mac.h"
29 #include "media/audio/mac/scoped_audio_unit.h"
30 #include "media/base/audio_bus.h"
31 #include "media/base/audio_timestamp_helper.h"
32 #include "media/base/data_buffer.h"
33 
34 namespace {
35 extern "C" {
36 // See:
37 // https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/PAL/pal/spi/cf/CoreAudioSPI.h?rev=228264
38 OSStatus AudioDeviceDuck(AudioDeviceID inDevice,
39                          Float32 inDuckedLevel,
40                          const AudioTimeStamp* __nullable inStartTime,
41                          Float32 inRampDuration) __attribute__((weak_import));
42 }
43 
UndoDucking(AudioDeviceID output_device_id)44 void UndoDucking(AudioDeviceID output_device_id) {
45   if (AudioDeviceDuck != nullptr) {
46     // Ramp the volume back up over half a second.
47     AudioDeviceDuck(output_device_id, 1.0, nullptr, 0.5);
48   }
49 }
50 
51 }  // namespace
52 
53 namespace media {
54 
55 // Number of blocks of buffers used in the |fifo_|.
56 const int kNumberOfBlocksBufferInFifo = 2;
57 
58 // Max length of sequence of TooManyFramesToProcessError errors.
59 // The stream will be stopped as soon as this time limit is passed.
60 const int kMaxErrorTimeoutInSeconds = 1;
61 
62 // A one-shot timer is created and started in Start() and it triggers
63 // CheckInputStartupSuccess() after this amount of time. UMA stats marked
64 // Media.Audio.InputStartupSuccessMac is then updated where true is added
65 // if input callbacks have started, and false otherwise.
66 const int kInputCallbackStartTimeoutInSeconds = 5;
67 
68 // Returns true if the format flags in |format_flags| has the "non-interleaved"
69 // flag (kAudioFormatFlagIsNonInterleaved) cleared (set to 0).
FormatIsInterleaved(UInt32 format_flags)70 static bool FormatIsInterleaved(UInt32 format_flags) {
71   return !(format_flags & kAudioFormatFlagIsNonInterleaved);
72 }
73 
74 // Converts the 32-bit non-terminated 4 byte string into an std::string.
75 // Example: code=1735354734 <=> 'goin' <=> kAudioDevicePropertyDeviceIsRunning.
FourCharFormatCodeToString(UInt32 code)76 static std::string FourCharFormatCodeToString(UInt32 code) {
77   char code_string[5];
78   // Converts a 32-bit integer from the host’s native byte order to big-endian.
79   UInt32 code_id = CFSwapInt32HostToBig(code);
80   bcopy(&code_id, code_string, 4);
81   code_string[4] = '\0';
82   return std::string(code_string);
83 }
84 
operator <<(std::ostream & os,const AudioStreamBasicDescription & format)85 static std::ostream& operator<<(std::ostream& os,
86                                 const AudioStreamBasicDescription& format) {
87   std::string format_string = FourCharFormatCodeToString(format.mFormatID);
88   os << "sample rate       : " << format.mSampleRate << std::endl
89      << "format ID         : " << format_string << std::endl
90      << "format flags      : " << format.mFormatFlags << std::endl
91      << "bytes per packet  : " << format.mBytesPerPacket << std::endl
92      << "frames per packet : " << format.mFramesPerPacket << std::endl
93      << "bytes per frame   : " << format.mBytesPerFrame << std::endl
94      << "channels per frame: " << format.mChannelsPerFrame << std::endl
95      << "bits per channel  : " << format.mBitsPerChannel << std::endl
96      << "reserved          : " << format.mReserved << std::endl
97      << "interleaved       : "
98      << (FormatIsInterleaved(format.mFormatFlags) ? "yes" : "no");
99   return os;
100 }
101 
OnGetPlayoutData(void * in_ref_con,AudioUnitRenderActionFlags * flags,const AudioTimeStamp * time_stamp,UInt32 bus_number,UInt32 num_frames,AudioBufferList * io_data)102 static OSStatus OnGetPlayoutData(void* in_ref_con,
103                                  AudioUnitRenderActionFlags* flags,
104                                  const AudioTimeStamp* time_stamp,
105                                  UInt32 bus_number,
106                                  UInt32 num_frames,
107                                  AudioBufferList* io_data) {
108   *flags |= kAudioUnitRenderAction_OutputIsSilence;
109   return noErr;
110 }
111 
GetInputDeviceStreamFormat(AudioUnit audio_unit,AudioStreamBasicDescription * format)112 static OSStatus GetInputDeviceStreamFormat(
113     AudioUnit audio_unit,
114     AudioStreamBasicDescription* format) {
115   DCHECK(audio_unit);
116   UInt32 property_size = sizeof(*format);
117   // Get the audio stream data format on the input scope of the input element
118   // since it is connected to the current input device.
119   OSStatus result =
120       AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat,
121                            kAudioUnitScope_Input, 1, format, &property_size);
122   DVLOG(1) << "Input device stream format: " << *format;
123   return result;
124 }
125 
126 // Returns the number of physical processors on the device.
NumberOfPhysicalProcessors()127 static int NumberOfPhysicalProcessors() {
128   base::mac::ScopedMachSendRight mach_host(mach_host_self());
129   host_basic_info hbi = {};
130   mach_msg_type_number_t info_count = HOST_BASIC_INFO_COUNT;
131   kern_return_t kr =
132       host_info(mach_host.get(), HOST_BASIC_INFO,
133                 reinterpret_cast<host_info_t>(&hbi), &info_count);
134 
135   int n_physical_cores = 0;
136   if (kr != KERN_SUCCESS) {
137     n_physical_cores = 1;
138     LOG(ERROR) << "Failed to determine number of physical cores, assuming 1";
139   } else {
140     n_physical_cores = hbi.physical_cpu;
141   }
142   DCHECK_EQ(HOST_BASIC_INFO_COUNT, info_count);
143   return n_physical_cores;
144 }
145 
146 // Adds extra system information to Media.AudioXXXMac UMA statistics.
147 // Only called when it has been detected that audio callbacks does not start
148 // as expected.
AddSystemInfoToUMA()149 static void AddSystemInfoToUMA() {
150   // Number of logical processors/cores on the current machine.
151   UMA_HISTOGRAM_COUNTS_1M("Media.Audio.LogicalProcessorsMac",
152                           base::SysInfo::NumberOfProcessors());
153   // Number of physical processors/cores on the current machine.
154   UMA_HISTOGRAM_COUNTS_1M("Media.Audio.PhysicalProcessorsMac",
155                           NumberOfPhysicalProcessors());
156   DVLOG(1) << "logical processors: " << base::SysInfo::NumberOfProcessors();
157   DVLOG(1) << "physical processors: " << NumberOfPhysicalProcessors();
158 }
159 
160 // Finds the first subdevice, in an aggregate device, with output streams.
FindFirstOutputSubdevice(AudioDeviceID aggregate_device_id)161 static AudioDeviceID FindFirstOutputSubdevice(
162     AudioDeviceID aggregate_device_id) {
163   const AudioObjectPropertyAddress property_address = {
164       kAudioAggregateDevicePropertyFullSubDeviceList,
165       kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
166   base::ScopedCFTypeRef<CFArrayRef> subdevices;
167   UInt32 size = sizeof(subdevices);
168   OSStatus result = AudioObjectGetPropertyData(
169       aggregate_device_id, &property_address, 0 /* inQualifierDataSize */,
170       nullptr /* inQualifierData */, &size, subdevices.InitializeInto());
171 
172   if (result != noErr) {
173     OSSTATUS_LOG(WARNING, result)
174         << "Failed to read property "
175         << kAudioAggregateDevicePropertyFullSubDeviceList << " for device "
176         << aggregate_device_id;
177     return kAudioObjectUnknown;
178   }
179 
180   AudioDeviceID output_subdevice_id = kAudioObjectUnknown;
181   DCHECK_EQ(CFGetTypeID(subdevices), CFArrayGetTypeID());
182   const CFIndex count = CFArrayGetCount(subdevices);
183   for (CFIndex i = 0; i != count; ++i) {
184     CFStringRef value =
185         base::mac::CFCast<CFStringRef>(CFArrayGetValueAtIndex(subdevices, i));
186     if (value) {
187       std::string uid = base::SysCFStringRefToUTF8(value);
188       output_subdevice_id = AudioManagerMac::GetAudioDeviceIdByUId(false, uid);
189       if (output_subdevice_id != kAudioObjectUnknown &&
190           core_audio_mac::GetNumStreams(output_subdevice_id, false) > 0) {
191         break;
192       }
193     }
194   }
195 
196   return output_subdevice_id;
197 }
198 
199 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit"
200 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html
201 // for more details and background regarding this implementation.
202 
AUAudioInputStream(AudioManagerMac * manager,const AudioParameters & input_params,AudioDeviceID audio_device_id,const AudioManager::LogCallback & log_callback,AudioManagerBase::VoiceProcessingMode voice_processing_mode)203 AUAudioInputStream::AUAudioInputStream(
204     AudioManagerMac* manager,
205     const AudioParameters& input_params,
206     AudioDeviceID audio_device_id,
207     const AudioManager::LogCallback& log_callback,
208     AudioManagerBase::VoiceProcessingMode voice_processing_mode)
209     : manager_(manager),
210       input_params_(input_params),
211       number_of_frames_provided_(0),
212       io_buffer_frame_size_(0),
213       sink_(nullptr),
214       audio_unit_(0),
215       input_device_id_(audio_device_id),
216       number_of_channels_in_frame_(0),
217       fifo_(input_params.channels(),
218             input_params.frames_per_buffer(),
219             kNumberOfBlocksBufferInFifo),
220       got_input_callback_(false),
221       input_callback_is_active_(false),
222       buffer_size_was_changed_(false),
223       audio_unit_render_has_worked_(false),
224       noise_reduction_suppressed_(false),
225       use_voice_processing_(voice_processing_mode ==
226                             AudioManagerBase::VoiceProcessingMode::kEnabled),
227       output_device_id_for_aec_(kAudioObjectUnknown),
228       last_sample_time_(0.0),
229       last_number_of_frames_(0),
230       total_lost_frames_(0),
231       largest_glitch_frames_(0),
232       glitches_detected_(0),
233       log_callback_(log_callback) {
234   DCHECK(manager_);
235   CHECK(log_callback_ != AudioManager::LogCallback());
236   if (use_voice_processing_) {
237     DCHECK(input_params.channels() == 1 || input_params.channels() == 2);
238     const bool got_default_device =
239         AudioManagerMac::GetDefaultOutputDevice(&output_device_id_for_aec_);
240     DCHECK(got_default_device);
241   }
242 
243   const SampleFormat kSampleFormat = kSampleFormatS16;
244 
245   // Set up the desired (output) format specified by the client.
246   format_.mSampleRate = input_params.sample_rate();
247   format_.mFormatID = kAudioFormatLinearPCM;
248   format_.mFormatFlags =
249       kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
250   DCHECK(FormatIsInterleaved(format_.mFormatFlags));
251   format_.mBitsPerChannel = SampleFormatToBitsPerChannel(kSampleFormat);
252   format_.mChannelsPerFrame = input_params.channels();
253   format_.mFramesPerPacket = 1;  // uncompressed audio
254   format_.mBytesPerPacket = format_.mBytesPerFrame =
255       input_params.GetBytesPerFrame(kSampleFormat);
256   format_.mReserved = 0;
257 
258   DVLOG(1) << "ctor";
259   DVLOG(1) << "device ID: 0x" << std::hex << audio_device_id;
260   DVLOG(1) << "buffer size : " << input_params.frames_per_buffer();
261   DVLOG(1) << "channels : " << input_params.channels();
262   DVLOG(1) << "desired output format: " << format_;
263 
264   // Derive size (in bytes) of the buffers that we will render to.
265   UInt32 data_byte_size =
266       input_params.frames_per_buffer() * format_.mBytesPerFrame;
267   DVLOG(1) << "size of data buffer in bytes : " << data_byte_size;
268 
269   // Allocate AudioBuffers to be used as storage for the received audio.
270   // The AudioBufferList structure works as a placeholder for the
271   // AudioBuffer structure, which holds a pointer to the actual data buffer.
272   audio_data_buffer_.reset(new uint8_t[data_byte_size]);
273   // We ask for noninterleaved audio.
274   audio_buffer_list_.mNumberBuffers = 1;
275 
276   AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers;
277   audio_buffer->mNumberChannels = input_params.channels();
278   audio_buffer->mDataByteSize = data_byte_size;
279   audio_buffer->mData = audio_data_buffer_.get();
280 }
281 
~AUAudioInputStream()282 AUAudioInputStream::~AUAudioInputStream() {
283   DVLOG(1) << "~dtor";
284   ReportAndResetStats();
285 }
286 
287 // Obtain and open the AUHAL AudioOutputUnit for recording.
Open()288 bool AUAudioInputStream::Open() {
289   DCHECK(thread_checker_.CalledOnValidThread());
290   DVLOG(1) << "Open";
291   DCHECK(!audio_unit_);
292 
293   // Verify that we have a valid device. Send appropriate error code to
294   // HandleError() to ensure that the error type is added to UMA stats.
295   if (input_device_id_ == kAudioObjectUnknown) {
296     NOTREACHED() << "Device ID is unknown";
297     HandleError(kAudioUnitErr_InvalidElement);
298     return false;
299   }
300 
301   // The requested sample-rate must match the hardware sample-rate.
302   const int sample_rate =
303       AudioManagerMac::HardwareSampleRateForDevice(input_device_id_);
304   DCHECK_EQ(sample_rate, format_.mSampleRate);
305 
306   log_callback_.Run(base::StrCat(
307       {"AU in: Open using ", use_voice_processing_ ? "VPAU" : "AUHAL"}));
308 
309   const bool success =
310       use_voice_processing_ ? OpenVoiceProcessingAU() : OpenAUHAL();
311 
312   if (!success)
313     return false;
314 
315   // The hardware latency is fixed and will not change during the call.
316   hardware_latency_ = AudioManagerMac::GetHardwareLatency(
317       audio_unit_, input_device_id_, kAudioDevicePropertyScopeInput,
318       format_.mSampleRate);
319 
320   // The master channel is 0, Left and right are channels 1 and 2.
321   // And the master channel is not counted in |number_of_channels_in_frame_|.
322   number_of_channels_in_frame_ = GetNumberOfChannelsFromStream();
323 
324   return true;
325 }
326 
OpenAUHAL()327 bool AUAudioInputStream::OpenAUHAL() {
328   // Start by obtaining an AudioOuputUnit using an AUHAL component description.
329 
330   // Description for the Audio Unit we want to use (AUHAL in this case).
331   // The kAudioUnitSubType_HALOutput audio unit interfaces to any audio device.
332   // The user specifies which audio device to track. The audio unit can do
333   // input from the device as well as output to the device. Bus 0 is used for
334   // the output side, bus 1 is used to get audio input from the device.
335   AudioComponentDescription desc = {kAudioUnitType_Output,
336                                     kAudioUnitSubType_HALOutput,
337                                     kAudioUnitManufacturer_Apple, 0, 0};
338 
339   // Find a component that meets the description in |desc|.
340   AudioComponent comp = AudioComponentFindNext(nullptr, &desc);
341   DCHECK(comp);
342   if (!comp) {
343     HandleError(kAudioUnitErr_NoConnection);
344     return false;
345   }
346 
347   // Get access to the service provided by the specified Audio Unit.
348   OSStatus result = AudioComponentInstanceNew(comp, &audio_unit_);
349   if (result) {
350     HandleError(result);
351     return false;
352   }
353 
354   // Initialize the AUHAL before making any changes or using it. The audio
355   // unit will be initialized once more as last operation in this method but
356   // that is intentional. This approach is based on a comment in the
357   // CAPlayThrough example from Apple, which states that "AUHAL needs to be
358   // initialized *before* anything is done to it".
359   // TODO(henrika): remove this extra call if we are unable to see any
360   // positive effects of it in our UMA stats.
361   result = AudioUnitInitialize(audio_unit_);
362   if (result != noErr) {
363     HandleError(result);
364     return false;
365   }
366 
367   // Enable IO on the input scope of the Audio Unit.
368   // Note that, these changes must be done *before* setting the AUHAL's
369   // current device.
370 
371   // After creating the AUHAL object, we must enable IO on the input scope
372   // of the Audio Unit to obtain the device input. Input must be explicitly
373   // enabled with the kAudioOutputUnitProperty_EnableIO property on Element 1
374   // of the AUHAL. Because the AUHAL can be used for both input and output,
375   // we must also disable IO on the output scope.
376 
377   // kAudioOutputUnitProperty_EnableIO is not a writable property of the
378   // voice processing unit (we'd get kAudioUnitErr_PropertyNotWritable returned
379   // back to us). IO is always enabled.
380 
381   // Enable input on the AUHAL.
382   {
383     const UInt32 enableIO = 1;
384     result = AudioUnitSetProperty(
385         audio_unit_, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,
386         AUElement::INPUT, &enableIO, sizeof(enableIO));
387     if (result != noErr) {
388       HandleError(result);
389       return false;
390     }
391   }
392 
393   // Disable output on the AUHAL.
394   {
395     const UInt32 disableIO = 0;
396     result = AudioUnitSetProperty(
397         audio_unit_, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,
398         AUElement::OUTPUT, &disableIO, sizeof(disableIO));
399     if (result != noErr) {
400       HandleError(result);
401       return false;
402     }
403   }
404 
405   // Next, set the audio device to be the Audio Unit's current device.
406   // Note that, devices can only be set to the AUHAL after enabling IO.
407   result =
408       AudioUnitSetProperty(audio_unit_, kAudioOutputUnitProperty_CurrentDevice,
409                            kAudioUnitScope_Global, AUElement::OUTPUT,
410                            &input_device_id_, sizeof(input_device_id_));
411 
412   if (result != noErr) {
413     HandleError(result);
414     return false;
415   }
416 
417   // Register the input procedure for the AUHAL. This procedure will be called
418   // when the AUHAL has received new data from the input device.
419   AURenderCallbackStruct callback;
420   callback.inputProc = &DataIsAvailable;
421   callback.inputProcRefCon = this;
422   result = AudioUnitSetProperty(
423       audio_unit_, kAudioOutputUnitProperty_SetInputCallback,
424       kAudioUnitScope_Global, AUElement::OUTPUT, &callback, sizeof(callback));
425 
426   if (result != noErr) {
427     HandleError(result);
428     return false;
429   }
430 
431   // Get the stream format for the selected input device and ensure that the
432   // sample rate of the selected input device matches the desired (given at
433   // construction) sample rate. We should not rely on sample rate conversion
434   // in the AUHAL, only *simple* conversions, e.g., 32-bit float to 16-bit
435   // signed integer format.
436   AudioStreamBasicDescription input_device_format = {0};
437   GetInputDeviceStreamFormat(audio_unit_, &input_device_format);
438   if (input_device_format.mSampleRate != format_.mSampleRate) {
439     LOG(ERROR) << "Input device's sample rate does not match the client's "
440                   "sample rate; input_device_format="
441                << input_device_format;
442     result = kAudioUnitErr_FormatNotSupported;
443     HandleError(result);
444     return false;
445   }
446 
447   // Modify the IO buffer size if not already set correctly for the selected
448   // device. The status of other active audio input and output streams is
449   // involved in the final setting.
450   // TODO(henrika): we could make io_buffer_frame_size a member and add it to
451   // the UMA stats tied to the Media.Audio.InputStartupSuccessMac record.
452   size_t io_buffer_frame_size = 0;
453   if (!manager_->MaybeChangeBufferSize(
454           input_device_id_, audio_unit_, 1, input_params_.frames_per_buffer(),
455           &buffer_size_was_changed_, &io_buffer_frame_size)) {
456     result = kAudioUnitErr_FormatNotSupported;
457     HandleError(result);
458     return false;
459   }
460 
461   // Store current I/O buffer frame size for UMA stats stored in combination
462   // with failing input callbacks.
463   DCHECK(!io_buffer_frame_size_);
464   io_buffer_frame_size_ = io_buffer_frame_size;
465 
466   // If the requested number of frames is out of range, the closest valid buffer
467   // size will be set instead. Check the current setting and log a warning for a
468   // non perfect match. Any such mismatch will be compensated for in
469   // OnDataIsAvailable().
470   UInt32 buffer_frame_size = 0;
471   UInt32 property_size = sizeof(buffer_frame_size);
472   result = AudioUnitGetProperty(
473       audio_unit_, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
474       AUElement::OUTPUT, &buffer_frame_size, &property_size);
475   LOG_IF(WARNING, buffer_frame_size !=
476                       static_cast<UInt32>(input_params_.frames_per_buffer()))
477       << "AUHAL is using best match of IO buffer size: " << buffer_frame_size;
478 
479   // Channel mapping should be supported but add a warning just in case.
480   // TODO(henrika): perhaps add to UMA stat to track if this can happen.
481   DLOG_IF(WARNING,
482           input_device_format.mChannelsPerFrame != format_.mChannelsPerFrame)
483       << "AUHAL's audio converter must do channel conversion";
484 
485   // Set up the the desired (output) format.
486   // For obtaining input from a device, the device format is always expressed
487   // on the output scope of the AUHAL's Element 1.
488   result = AudioUnitSetProperty(audio_unit_, kAudioUnitProperty_StreamFormat,
489                                 kAudioUnitScope_Output, 1, &format_,
490                                 sizeof(format_));
491   if (result != noErr) {
492     HandleError(result);
493     return false;
494   }
495 
496   // Finally, initialize the audio unit and ensure that it is ready to render.
497   // Allocates memory according to the maximum number of audio frames
498   // it can produce in response to a single render call.
499   result = AudioUnitInitialize(audio_unit_);
500   if (result != noErr) {
501     HandleError(result);
502     return false;
503   }
504 
505   return true;
506 }
507 
OpenVoiceProcessingAU()508 bool AUAudioInputStream::OpenVoiceProcessingAU() {
509   // Start by obtaining an AudioOuputUnit using an AUHAL component description.
510 
511   // Description for the Audio Unit we want to use (AUHAL in this case).
512   // The kAudioUnitSubType_HALOutput audio unit interfaces to any audio device.
513   // The user specifies which audio device to track. The audio unit can do
514   // input from the device as well as output to the device. Bus 0 is used for
515   // the output side, bus 1 is used to get audio input from the device.
516   AudioComponentDescription desc = {kAudioUnitType_Output,
517                                     kAudioUnitSubType_VoiceProcessingIO,
518                                     kAudioUnitManufacturer_Apple, 0, 0};
519 
520   // Find a component that meets the description in |desc|.
521   AudioComponent comp = AudioComponentFindNext(nullptr, &desc);
522   DCHECK(comp);
523   if (!comp) {
524     HandleError(kAudioUnitErr_NoConnection);
525     return false;
526   }
527 
528   // Get access to the service provided by the specified Audio Unit.
529   OSStatus result = AudioComponentInstanceNew(comp, &audio_unit_);
530   if (result) {
531     HandleError(result);
532     return false;
533   }
534 
535   // Next, set the audio device to be the Audio Unit's input device.
536   result =
537       AudioUnitSetProperty(audio_unit_, kAudioOutputUnitProperty_CurrentDevice,
538                            kAudioUnitScope_Global, AUElement::INPUT,
539                            &input_device_id_, sizeof(input_device_id_));
540 
541   if (result != noErr) {
542     HandleError(result);
543     return false;
544   }
545 
546   // Followed by the audio device to be the Audio Unit's output device.
547   result = AudioUnitSetProperty(
548       audio_unit_, kAudioOutputUnitProperty_CurrentDevice,
549       kAudioUnitScope_Global, AUElement::OUTPUT, &output_device_id_for_aec_,
550       sizeof(output_device_id_for_aec_));
551 
552   if (result != noErr) {
553     HandleError(result);
554     return false;
555   }
556 
557   // Register the input procedure for the AUHAL. This procedure will be called
558   // when the AUHAL has received new data from the input device.
559   AURenderCallbackStruct callback;
560   callback.inputProc = &DataIsAvailable;
561   callback.inputProcRefCon = this;
562 
563   result = AudioUnitSetProperty(
564       audio_unit_, kAudioOutputUnitProperty_SetInputCallback,
565       kAudioUnitScope_Global, AUElement::INPUT, &callback, sizeof(callback));
566   if (result != noErr) {
567     HandleError(result);
568     return false;
569   }
570 
571   callback.inputProc = OnGetPlayoutData;
572   callback.inputProcRefCon = this;
573   result = AudioUnitSetProperty(
574       audio_unit_, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
575       AUElement::OUTPUT, &callback, sizeof(callback));
576   if (result != noErr) {
577     HandleError(result);
578     return false;
579   }
580 
581   // Get the stream format for the selected input device and ensure that the
582   // sample rate of the selected input device matches the desired (given at
583   // construction) sample rate. We should not rely on sample rate conversion
584   // in the AUHAL, only *simple* conversions, e.g., 32-bit float to 16-bit
585   // signed integer format.
586   AudioStreamBasicDescription input_device_format = {0};
587   GetInputDeviceStreamFormat(audio_unit_, &input_device_format);
588   if (input_device_format.mSampleRate != format_.mSampleRate) {
589     LOG(ERROR)
590         << "Input device's sample rate does not match the client's sample rate";
591     result = kAudioUnitErr_FormatNotSupported;
592     HandleError(result);
593     return false;
594   }
595 
596   // Modify the IO buffer size if not already set correctly for the selected
597   // device. The status of other active audio input and output streams is
598   // involved in the final setting.
599   // TODO(henrika): we could make io_buffer_frame_size a member and add it to
600   // the UMA stats tied to the Media.Audio.InputStartupSuccessMac record.
601   size_t io_buffer_frame_size = 0;
602   if (!manager_->MaybeChangeBufferSize(
603           input_device_id_, audio_unit_, 1, input_params_.frames_per_buffer(),
604           &buffer_size_was_changed_, &io_buffer_frame_size)) {
605     result = kAudioUnitErr_FormatNotSupported;
606     HandleError(result);
607     return false;
608   }
609 
610   // Store current I/O buffer frame size for UMA stats stored in combination
611   // with failing input callbacks.
612   DCHECK(!io_buffer_frame_size_);
613   io_buffer_frame_size_ = io_buffer_frame_size;
614 
615   // If the requested number of frames is out of range, the closest valid buffer
616   // size will be set instead. Check the current setting and log a warning for a
617   // non perfect match. Any such mismatch will be compensated for in
618   // OnDataIsAvailable().
619   UInt32 buffer_frame_size = 0;
620   UInt32 property_size = sizeof(buffer_frame_size);
621   result = AudioUnitGetProperty(
622       audio_unit_, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
623       AUElement::OUTPUT, &buffer_frame_size, &property_size);
624   LOG_IF(WARNING, buffer_frame_size !=
625                       static_cast<UInt32>(input_params_.frames_per_buffer()))
626       << "AUHAL is using best match of IO buffer size: " << buffer_frame_size;
627 
628   // The built-in device claims to be stereo. VPAU claims 5 channels (for me)
629   // but refuses to work in stereo. Just accept stero for now, use mono
630   // internally and upmix.
631   AudioStreamBasicDescription mono_format = format_;
632   if (format_.mChannelsPerFrame == 2) {
633     mono_format.mChannelsPerFrame = 1;
634     mono_format.mBytesPerPacket = mono_format.mBitsPerChannel / 8;
635     mono_format.mBytesPerFrame = mono_format.mBytesPerPacket;
636   }
637 
638   // Set up the the desired (output) format.
639   // For obtaining input from a device, the device format is always expressed
640   // on the output scope of the AUHAL's Element 1.
641   result = AudioUnitSetProperty(audio_unit_, kAudioUnitProperty_StreamFormat,
642                                 kAudioUnitScope_Output, AUElement::INPUT,
643                                 &mono_format, sizeof(mono_format));
644   if (result != noErr) {
645     HandleError(result);
646     return false;
647   }
648 
649   result = AudioUnitSetProperty(audio_unit_, kAudioUnitProperty_StreamFormat,
650                                 kAudioUnitScope_Input, AUElement::OUTPUT,
651                                 &mono_format, sizeof(mono_format));
652   if (result != noErr) {
653     HandleError(result);
654     return false;
655   }
656 
657   // Finally, initialize the audio unit and ensure that it is ready to render.
658   // Allocates memory according to the maximum number of audio frames
659   // it can produce in response to a single render call.
660   result = AudioUnitInitialize(audio_unit_);
661   if (result != noErr) {
662     HandleError(result);
663     return false;
664   }
665 
666   UndoDucking(output_device_id_for_aec_);
667 
668   return true;
669 }
670 
Start(AudioInputCallback * callback)671 void AUAudioInputStream::Start(AudioInputCallback* callback) {
672   DCHECK(thread_checker_.CalledOnValidThread());
673   DVLOG(1) << "Start";
674   DCHECK(callback);
675   DCHECK(!sink_);
676   DLOG_IF(ERROR, !audio_unit_) << "Open() has not been called successfully";
677   if (IsRunning())
678     return;
679 
680   // Check if we should defer Start() for http://crbug.com/160920.
681   if (manager_->ShouldDeferStreamStart()) {
682     LOG(WARNING) << "Start of input audio is deferred";
683     // Use a cancellable closure so that if Stop() is called before Start()
684     // actually runs, we can cancel the pending start.
685     deferred_start_cb_.Reset(base::BindOnce(&AUAudioInputStream::Start,
686                                             base::Unretained(this), callback));
687     manager_->GetTaskRunner()->PostDelayedTask(
688         FROM_HERE, deferred_start_cb_.callback(),
689         base::TimeDelta::FromSeconds(
690             AudioManagerMac::kStartDelayInSecsForPowerEvents));
691     return;
692   }
693 
694   sink_ = callback;
695   last_success_time_ = base::TimeTicks::Now();
696   audio_unit_render_has_worked_ = false;
697 
698   // Don't disable built-in noise suppression when using VPAU.
699   if (!use_voice_processing_ &&
700       !(input_params_.effects() & AudioParameters::NOISE_SUPPRESSION) &&
701       manager_->DeviceSupportsAmbientNoiseReduction(input_device_id_)) {
702     noise_reduction_suppressed_ =
703         manager_->SuppressNoiseReduction(input_device_id_);
704   }
705   StartAgc();
706   OSStatus result = AudioOutputUnitStart(audio_unit_);
707   OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
708       << "Failed to start acquiring data";
709   if (result != noErr) {
710     Stop();
711     return;
712   }
713   DCHECK(IsRunning()) << "Audio unit started OK but is not yet running";
714 
715   // For UMA stat purposes, start a one-shot timer which detects when input
716   // callbacks starts indicating if input audio recording starts as intended.
717   // CheckInputStartupSuccess() will check if |input_callback_is_active_| is
718   // true when the timer expires.
719   input_callback_timer_.reset(new base::OneShotTimer());
720   input_callback_timer_->Start(
721       FROM_HERE,
722       base::TimeDelta::FromSeconds(kInputCallbackStartTimeoutInSeconds), this,
723       &AUAudioInputStream::CheckInputStartupSuccess);
724   DCHECK(input_callback_timer_->IsRunning());
725 }
726 
Stop()727 void AUAudioInputStream::Stop() {
728   DCHECK(thread_checker_.CalledOnValidThread());
729   deferred_start_cb_.Cancel();
730   DVLOG(1) << "Stop";
731   StopAgc();
732   if (noise_reduction_suppressed_) {
733     manager_->UnsuppressNoiseReduction(input_device_id_);
734     noise_reduction_suppressed_ = false;
735   }
736   if (input_callback_timer_ != nullptr) {
737     input_callback_timer_->Stop();
738     input_callback_timer_.reset();
739   }
740 
741   if (audio_unit_ != nullptr) {
742     // Stop the I/O audio unit.
743     OSStatus result = AudioOutputUnitStop(audio_unit_);
744     DCHECK_EQ(result, noErr);
745     // Add a DCHECK here just in case. AFAIK, the call to AudioOutputUnitStop()
746     // seems to set this state synchronously, hence it should always report
747     // false after a successful call.
748     DCHECK(!IsRunning()) << "Audio unit is stopped but still running";
749 
750     // Reset the audio unit’s render state. This function clears memory.
751     // It does not allocate or free memory resources.
752     result = AudioUnitReset(audio_unit_, kAudioUnitScope_Global, 0);
753     DCHECK_EQ(result, noErr);
754     OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
755         << "Failed to stop acquiring data";
756   }
757 
758   SetInputCallbackIsActive(false);
759   ReportAndResetStats();
760   sink_ = nullptr;
761   fifo_.Clear();
762   io_buffer_frame_size_ = 0;
763   got_input_callback_ = false;
764 }
765 
Close()766 void AUAudioInputStream::Close() {
767   DCHECK(thread_checker_.CalledOnValidThread());
768   DVLOG(1) << "Close";
769 
770   // It is valid to call Close() before calling open or Start().
771   // It is also valid to call Close() after Start() has been called.
772   if (IsRunning()) {
773     Stop();
774   }
775 
776   // Uninitialize and dispose the audio unit.
777   CloseAudioUnit();
778 
779   // Inform the audio manager that we have been closed. This will cause our
780   // destruction.
781   manager_->ReleaseInputStream(this);
782 }
783 
GetMaxVolume()784 double AUAudioInputStream::GetMaxVolume() {
785   // Verify that we have a valid device.
786   if (input_device_id_ == kAudioObjectUnknown) {
787     NOTREACHED() << "Device ID is unknown";
788     return 0.0;
789   }
790 
791   // Query if any of the master, left or right channels has volume control.
792   for (int i = 0; i <= number_of_channels_in_frame_; ++i) {
793     // If the volume is settable, the  valid volume range is [0.0, 1.0].
794     if (IsVolumeSettableOnChannel(i))
795       return 1.0;
796   }
797 
798   // Volume control is not available for the audio stream.
799   return 0.0;
800 }
801 
SetVolume(double volume)802 void AUAudioInputStream::SetVolume(double volume) {
803   DVLOG(1) << "SetVolume(volume=" << volume << ")";
804   DCHECK_GE(volume, 0.0);
805   DCHECK_LE(volume, 1.0);
806 
807   // Verify that we have a valid device.
808   if (input_device_id_ == kAudioObjectUnknown) {
809     NOTREACHED() << "Device ID is unknown";
810     return;
811   }
812 
813   Float32 volume_float32 = static_cast<Float32>(volume);
814   AudioObjectPropertyAddress property_address = {
815       kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput,
816       kAudioObjectPropertyElementMaster};
817 
818   // Try to set the volume for master volume channel.
819   if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster)) {
820     OSStatus result = AudioObjectSetPropertyData(
821         input_device_id_, &property_address, 0, nullptr, sizeof(volume_float32),
822         &volume_float32);
823     if (result != noErr) {
824       DLOG(WARNING) << "Failed to set volume to " << volume_float32;
825     }
826     return;
827   }
828 
829   // There is no master volume control, try to set volume for each channel.
830   int successful_channels = 0;
831   for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
832     property_address.mElement = static_cast<UInt32>(i);
833     if (IsVolumeSettableOnChannel(i)) {
834       OSStatus result = AudioObjectSetPropertyData(
835           input_device_id_, &property_address, 0, NULL, sizeof(volume_float32),
836           &volume_float32);
837       if (result == noErr)
838         ++successful_channels;
839     }
840   }
841 
842   DLOG_IF(WARNING, successful_channels == 0)
843       << "Failed to set volume to " << volume_float32;
844 
845   // Update the AGC volume level based on the last setting above. Note that,
846   // the volume-level resolution is not infinite and it is therefore not
847   // possible to assume that the volume provided as input parameter can be
848   // used directly. Instead, a new query to the audio hardware is required.
849   // This method does nothing if AGC is disabled.
850   UpdateAgcVolume();
851 }
852 
GetVolume()853 double AUAudioInputStream::GetVolume() {
854   // Verify that we have a valid device.
855   if (input_device_id_ == kAudioObjectUnknown) {
856     NOTREACHED() << "Device ID is unknown";
857     return 0.0;
858   }
859 
860   AudioObjectPropertyAddress property_address = {
861       kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput,
862       kAudioObjectPropertyElementMaster};
863 
864   if (AudioObjectHasProperty(input_device_id_, &property_address)) {
865     // The device supports master volume control, get the volume from the
866     // master channel.
867     Float32 volume_float32 = 0.0;
868     UInt32 size = sizeof(volume_float32);
869     OSStatus result =
870         AudioObjectGetPropertyData(input_device_id_, &property_address, 0,
871                                    nullptr, &size, &volume_float32);
872     if (result == noErr)
873       return static_cast<double>(volume_float32);
874   } else {
875     // There is no master volume control, try to get the average volume of
876     // all the channels.
877     Float32 volume_float32 = 0.0;
878     int successful_channels = 0;
879     for (int i = 1; i <= number_of_channels_in_frame_; ++i) {
880       property_address.mElement = static_cast<UInt32>(i);
881       if (AudioObjectHasProperty(input_device_id_, &property_address)) {
882         Float32 channel_volume = 0;
883         UInt32 size = sizeof(channel_volume);
884         OSStatus result =
885             AudioObjectGetPropertyData(input_device_id_, &property_address, 0,
886                                        nullptr, &size, &channel_volume);
887         if (result == noErr) {
888           volume_float32 += channel_volume;
889           ++successful_channels;
890         }
891       }
892     }
893 
894     // Get the average volume of the channels.
895     if (successful_channels != 0)
896       return static_cast<double>(volume_float32 / successful_channels);
897   }
898 
899   DLOG(WARNING) << "Failed to get volume";
900   return 0.0;
901 }
902 
IsMuted()903 bool AUAudioInputStream::IsMuted() {
904   // Verify that we have a valid device.
905   DCHECK_NE(input_device_id_, kAudioObjectUnknown) << "Device ID is unknown";
906 
907   AudioObjectPropertyAddress property_address = {
908       kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput,
909       kAudioObjectPropertyElementMaster};
910 
911   if (!AudioObjectHasProperty(input_device_id_, &property_address)) {
912     DLOG(ERROR) << "Device does not support checking master mute state";
913     return false;
914   }
915 
916   UInt32 muted = 0;
917   UInt32 size = sizeof(muted);
918   OSStatus result = AudioObjectGetPropertyData(
919       input_device_id_, &property_address, 0, nullptr, &size, &muted);
920   DLOG_IF(WARNING, result != noErr) << "Failed to get mute state";
921   return result == noErr && muted != 0;
922 }
923 
SetOutputDeviceForAec(const std::string & output_device_id)924 void AUAudioInputStream::SetOutputDeviceForAec(
925     const std::string& output_device_id) {
926   if (!use_voice_processing_)
927     return;
928 
929   AudioDeviceID audio_device_id =
930       AudioManagerMac::GetAudioDeviceIdByUId(false, output_device_id);
931   if (audio_device_id == output_device_id_for_aec_)
932     return;
933 
934   if (audio_device_id == kAudioObjectUnknown) {
935     log_callback_.Run(
936         base::StringPrintf("AU in: Unable to resolve output device id '%s'",
937                            output_device_id.c_str()));
938     return;
939   }
940 
941   // If the selected device is an aggregate device, try to use the first output
942   // device of the aggregate device instead.
943   if (core_audio_mac::GetDeviceTransportType(audio_device_id) ==
944       kAudioDeviceTransportTypeAggregate) {
945     const AudioDeviceID output_subdevice_id =
946         FindFirstOutputSubdevice(audio_device_id);
947 
948     if (output_subdevice_id == kAudioObjectUnknown) {
949       log_callback_.Run(base::StringPrintf(
950           "AU in: Unable to find an output subdevice in aggregate device '%s'",
951           output_device_id.c_str()));
952       return;
953     }
954     audio_device_id = output_subdevice_id;
955   }
956 
957   if (audio_device_id != output_device_id_for_aec_) {
958     output_device_id_for_aec_ = audio_device_id;
959     log_callback_.Run(base::StringPrintf(
960         "AU in: Output device for AEC changed to '%s' (%d)",
961         output_device_id.c_str(), output_device_id_for_aec_));
962     // Only restart the stream if it has previously been started.
963     if (audio_unit_)
964       ReinitializeVoiceProcessingAudioUnit();
965   }
966 }
967 
ReinitializeVoiceProcessingAudioUnit()968 void AUAudioInputStream::ReinitializeVoiceProcessingAudioUnit() {
969   DCHECK(use_voice_processing_);
970   DCHECK(audio_unit_);
971 
972   const bool was_running = IsRunning();
973   OSStatus result = noErr;
974 
975   if (was_running) {
976     result = AudioOutputUnitStop(audio_unit_);
977     DCHECK_EQ(result, noErr);
978   }
979 
980   CloseAudioUnit();
981 
982   // Reset things to a state similar to before the audio unit was opened.
983   // Most of these will be no-ops if the audio unit was opened but not started.
984   SetInputCallbackIsActive(false);
985   ReportAndResetStats();
986   io_buffer_frame_size_ = 0;
987   got_input_callback_ = false;
988 
989   OpenVoiceProcessingAU();
990 
991   if (was_running) {
992     result = AudioOutputUnitStart(audio_unit_);
993     if (result != noErr) {
994       OSSTATUS_DLOG(ERROR, result) << "Failed to start acquiring data";
995       Stop();
996       return;
997     }
998   }
999 
1000   log_callback_.Run(base::StringPrintf(
1001       "AU in: Successfully reinitialized AEC for output device id=%d.",
1002       output_device_id_for_aec_));
1003 }
1004 
1005 // static
DataIsAvailable(void * context,AudioUnitRenderActionFlags * flags,const AudioTimeStamp * time_stamp,UInt32 bus_number,UInt32 number_of_frames,AudioBufferList * io_data)1006 OSStatus AUAudioInputStream::DataIsAvailable(void* context,
1007                                              AudioUnitRenderActionFlags* flags,
1008                                              const AudioTimeStamp* time_stamp,
1009                                              UInt32 bus_number,
1010                                              UInt32 number_of_frames,
1011                                              AudioBufferList* io_data) {
1012   DCHECK(context);
1013   // Recorded audio is always on the input bus (=1).
1014   DCHECK_EQ(bus_number, 1u);
1015   // No data buffer should be allocated at this stage.
1016   DCHECK(!io_data);
1017   AUAudioInputStream* self = reinterpret_cast<AUAudioInputStream*>(context);
1018   // Propagate render action flags, time stamp, bus number and number
1019   // of frames requested to the AudioUnitRender() call where the actual data
1020   // is received from the input device via the output scope of the audio unit.
1021   return self->OnDataIsAvailable(flags, time_stamp, bus_number,
1022                                  number_of_frames);
1023 }
1024 
OnDataIsAvailable(AudioUnitRenderActionFlags * flags,const AudioTimeStamp * time_stamp,UInt32 bus_number,UInt32 number_of_frames)1025 OSStatus AUAudioInputStream::OnDataIsAvailable(
1026     AudioUnitRenderActionFlags* flags,
1027     const AudioTimeStamp* time_stamp,
1028     UInt32 bus_number,
1029     UInt32 number_of_frames) {
1030   TRACE_EVENT0("audio", "AUAudioInputStream::OnDataIsAvailable");
1031 
1032   // Indicate that input callbacks have started.
1033   if (!got_input_callback_) {
1034     got_input_callback_ = true;
1035     SetInputCallbackIsActive(true);
1036   }
1037 
1038   // Update the |mDataByteSize| value in the audio_buffer_list() since
1039   // |number_of_frames| can be changed on the fly.
1040   // |mDataByteSize| needs to be exactly mapping to |number_of_frames|,
1041   // otherwise it will put CoreAudio into bad state and results in
1042   // AudioUnitRender() returning -50 for the new created stream.
1043   // We have also seen kAudioUnitErr_TooManyFramesToProcess (-10874) and
1044   // kAudioUnitErr_CannotDoInCurrentContext (-10863) as error codes.
1045   // See crbug/428706 for details.
1046   UInt32 new_size = number_of_frames * format_.mBytesPerFrame;
1047   AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers;
1048   bool new_buffer_size_detected = false;
1049   if (new_size != audio_buffer->mDataByteSize) {
1050     new_buffer_size_detected = true;
1051     DVLOG(1) << "New size of number_of_frames detected: " << number_of_frames;
1052     io_buffer_frame_size_ = static_cast<size_t>(number_of_frames);
1053     if (new_size > audio_buffer->mDataByteSize) {
1054       // This can happen if the device is unplugged during recording. We
1055       // allocate enough memory here to avoid depending on how CoreAudio
1056       // handles it.
1057       // See See http://www.crbug.com/434681 for one example when we can enter
1058       // this scope.
1059       audio_data_buffer_.reset(new uint8_t[new_size]);
1060       audio_buffer->mData = audio_data_buffer_.get();
1061     }
1062 
1063     // Update the |mDataByteSize| to match |number_of_frames|.
1064     audio_buffer->mDataByteSize = new_size;
1065   }
1066 
1067   // Obtain the recorded audio samples by initiating a rendering cycle.
1068   // Since it happens on the input bus, the |&audio_buffer_list_| parameter is
1069   // a reference to the preallocated audio buffer list that the audio unit
1070   // renders into.
1071   OSStatus result;
1072   if (use_voice_processing_ && format_.mChannelsPerFrame != 1) {
1073     // Use the first part of the output buffer for mono data...
1074     AudioBufferList mono_buffer_list;
1075     mono_buffer_list.mNumberBuffers = 1;
1076     AudioBuffer* mono_buffer = mono_buffer_list.mBuffers;
1077     mono_buffer->mNumberChannels = 1;
1078     mono_buffer->mDataByteSize =
1079         audio_buffer->mDataByteSize / audio_buffer->mNumberChannels;
1080     mono_buffer->mData = audio_buffer->mData;
1081 
1082     TRACE_EVENT_BEGIN0("audio", "AudioUnitRender");
1083     result = AudioUnitRender(audio_unit_, flags, time_stamp, bus_number,
1084                              number_of_frames, &mono_buffer_list);
1085     TRACE_EVENT_END0("audio", "AudioUnitRender");
1086     // ... then upmix it by copying it out to two channels.
1087     UpmixMonoToStereoInPlace(audio_buffer, format_.mBitsPerChannel / 8);
1088   } else {
1089     TRACE_EVENT_BEGIN0("audio", "AudioUnitRender");
1090     result = AudioUnitRender(audio_unit_, flags, time_stamp, bus_number,
1091                              number_of_frames, &audio_buffer_list_);
1092     TRACE_EVENT_END0("audio", "AudioUnitRender");
1093   }
1094 
1095   if (result == noErr) {
1096     audio_unit_render_has_worked_ = true;
1097   }
1098   if (result) {
1099     TRACE_EVENT_INSTANT0("audio", "AudioUnitRender error",
1100                          TRACE_EVENT_SCOPE_THREAD);
1101     // Only upload UMA histograms for the case when AGC is enabled. The reason
1102     // is that we want to compare these stats with others in this class and
1103     // they are only stored for "AGC streams", e.g. WebRTC audio streams.
1104     const bool add_uma_histogram = GetAutomaticGainControl();
1105     if (add_uma_histogram) {
1106       base::UmaHistogramSparse("Media.AudioInputCbErrorMac", result);
1107     }
1108     OSSTATUS_LOG(ERROR, result) << "AudioUnitRender() failed ";
1109     if (result == kAudioUnitErr_TooManyFramesToProcess ||
1110         result == kAudioUnitErr_CannotDoInCurrentContext) {
1111       DCHECK(!last_success_time_.is_null());
1112       // We delay stopping the stream for kAudioUnitErr_TooManyFramesToProcess
1113       // since it has been observed that some USB headsets can cause this error
1114       // but only for a few initial frames at startup and then then the stream
1115       // returns to a stable state again. See b/19524368 for details.
1116       // Instead, we measure time since last valid audio frame and call
1117       // HandleError() only if a too long error sequence is detected. We do
1118       // this to avoid ending up in a non recoverable bad core audio state.
1119       // Also including kAudioUnitErr_CannotDoInCurrentContext since long
1120       // sequences can be produced in combination with e.g. sample-rate changes
1121       // for input devices.
1122       base::TimeDelta time_since_last_success =
1123           base::TimeTicks::Now() - last_success_time_;
1124       if ((time_since_last_success >
1125            base::TimeDelta::FromSeconds(kMaxErrorTimeoutInSeconds))) {
1126         const char* err = (result == kAudioUnitErr_TooManyFramesToProcess)
1127                               ? "kAudioUnitErr_TooManyFramesToProcess"
1128                               : "kAudioUnitErr_CannotDoInCurrentContext";
1129         LOG(ERROR) << "Too long sequence of " << err << " errors!";
1130         HandleError(result);
1131       }
1132 
1133       // Add some extra UMA stat to track down if we see this particular error
1134       // in combination with a previous change of buffer size "on the fly".
1135       if (result == kAudioUnitErr_CannotDoInCurrentContext &&
1136           add_uma_histogram) {
1137         UMA_HISTOGRAM_BOOLEAN("Media.Audio.RenderFailsWhenBufferSizeChangesMac",
1138                               new_buffer_size_detected);
1139         UMA_HISTOGRAM_BOOLEAN("Media.Audio.AudioUnitRenderHasWorkedMac",
1140                               audio_unit_render_has_worked_);
1141       }
1142     } else {
1143       // We have also seen kAudioUnitErr_NoConnection in some cases. Bailing
1144       // out for this error for now.
1145       HandleError(result);
1146     }
1147     return result;
1148   }
1149   // Update time of successful call to AudioUnitRender().
1150   last_success_time_ = base::TimeTicks::Now();
1151 
1152   // Deliver recorded data to the consumer as a callback.
1153   return Provide(number_of_frames, &audio_buffer_list_, time_stamp);
1154 }
1155 
Provide(UInt32 number_of_frames,AudioBufferList * io_data,const AudioTimeStamp * time_stamp)1156 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
1157                                      AudioBufferList* io_data,
1158                                      const AudioTimeStamp* time_stamp) {
1159   TRACE_EVENT1("audio", "AUAudioInputStream::Provide", "number_of_frames",
1160                number_of_frames);
1161   UpdateCaptureTimestamp(time_stamp);
1162   last_number_of_frames_ = number_of_frames;
1163 
1164   // TODO(grunell): We'll only care about the first buffer size change, any
1165   // further changes will be ignored. This is in line with output side stats.
1166   // It would be nice to have all changes reflected in UMA stats.
1167   if (number_of_frames !=
1168           static_cast<UInt32>(input_params_.frames_per_buffer()) &&
1169       number_of_frames_provided_ == 0)
1170     number_of_frames_provided_ = number_of_frames;
1171 
1172   base::TimeTicks capture_time = GetCaptureTime(time_stamp);
1173 
1174   // The AGC volume level is updated once every second on a separate thread.
1175   // Note that, |volume| is also updated each time SetVolume() is called
1176   // through IPC by the render-side AGC.
1177   double normalized_volume = 0.0;
1178   GetAgcVolume(&normalized_volume);
1179 
1180   AudioBuffer& buffer = io_data->mBuffers[0];
1181   uint8_t* audio_data = reinterpret_cast<uint8_t*>(buffer.mData);
1182   DCHECK(audio_data);
1183   if (!audio_data)
1184     return kAudioUnitErr_InvalidElement;
1185 
1186   // Dynamically increase capacity of the FIFO to handle larger buffers from
1187   // CoreAudio. This can happen in combination with Apple Thunderbolt Displays
1188   // when the Display Audio is used as capture source and the cable is first
1189   // remove and then inserted again.
1190   // See http://www.crbug.com/434681 for details.
1191   if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) {
1192     // Derive required increase in number of FIFO blocks. The increase is
1193     // typically one block.
1194     const int blocks =
1195         static_cast<int>((number_of_frames - fifo_.GetUnfilledFrames()) /
1196                          input_params_.frames_per_buffer()) +
1197         1;
1198     DLOG(WARNING) << "Increasing FIFO capacity by " << blocks << " blocks";
1199     TRACE_EVENT_INSTANT1("audio", "Increasing FIFO capacity",
1200                          TRACE_EVENT_SCOPE_THREAD, "increased by", blocks);
1201     fifo_.IncreaseCapacity(blocks);
1202   }
1203 
1204   // Compensate the capture time for the FIFO before pushing an new frames.
1205   capture_time -= AudioTimestampHelper::FramesToTime(fifo_.GetAvailableFrames(),
1206                                                      format_.mSampleRate);
1207 
1208   // Copy captured (and interleaved) data into FIFO.
1209   fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8);
1210 
1211   // Consume and deliver the data when the FIFO has a block of available data.
1212   while (fifo_.available_blocks()) {
1213     const AudioBus* audio_bus = fifo_.Consume();
1214     DCHECK_EQ(audio_bus->frames(),
1215               static_cast<int>(input_params_.frames_per_buffer()));
1216 
1217     sink_->OnData(audio_bus, capture_time, normalized_volume);
1218 
1219     // Move the capture time forward for each vended block.
1220     capture_time += AudioTimestampHelper::FramesToTime(audio_bus->frames(),
1221                                                        format_.mSampleRate);
1222   }
1223 
1224   return noErr;
1225 }
1226 
HardwareSampleRate()1227 int AUAudioInputStream::HardwareSampleRate() {
1228   // Determine the default input device's sample-rate.
1229   AudioDeviceID device_id = kAudioObjectUnknown;
1230   UInt32 info_size = sizeof(device_id);
1231 
1232   AudioObjectPropertyAddress default_input_device_address = {
1233       kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal,
1234       kAudioObjectPropertyElementMaster};
1235   OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
1236                                                &default_input_device_address, 0,
1237                                                0, &info_size, &device_id);
1238   if (result != noErr)
1239     return 0.0;
1240 
1241   Float64 nominal_sample_rate;
1242   info_size = sizeof(nominal_sample_rate);
1243 
1244   AudioObjectPropertyAddress nominal_sample_rate_address = {
1245       kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
1246       kAudioObjectPropertyElementMaster};
1247   result = AudioObjectGetPropertyData(device_id, &nominal_sample_rate_address,
1248                                       0, 0, &info_size, &nominal_sample_rate);
1249   if (result != noErr)
1250     return 0.0;
1251 
1252   return static_cast<int>(nominal_sample_rate);
1253 }
1254 
GetCaptureTime(const AudioTimeStamp * input_time_stamp)1255 base::TimeTicks AUAudioInputStream::GetCaptureTime(
1256     const AudioTimeStamp* input_time_stamp) {
1257   // Total latency is composed by the dynamic latency and the fixed
1258   // hardware latency.
1259   // https://lists.apple.com/archives/coreaudio-api/2017/Jul/msg00035.html
1260   return (input_time_stamp->mFlags & kAudioTimeStampHostTimeValid
1261               ? base::TimeTicks::FromMachAbsoluteTime(
1262                     input_time_stamp->mHostTime)
1263               : base::TimeTicks::Now()) -
1264          hardware_latency_;
1265 }
1266 
GetNumberOfChannelsFromStream()1267 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
1268   // Get the stream format, to be able to read the number of channels.
1269   AudioObjectPropertyAddress property_address = {
1270       kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeInput,
1271       kAudioObjectPropertyElementMaster};
1272   AudioStreamBasicDescription stream_format;
1273   UInt32 size = sizeof(stream_format);
1274   OSStatus result = AudioObjectGetPropertyData(
1275       input_device_id_, &property_address, 0, nullptr, &size, &stream_format);
1276   if (result != noErr) {
1277     DLOG(WARNING) << "Could not get stream format";
1278     return 0;
1279   }
1280 
1281   return static_cast<int>(stream_format.mChannelsPerFrame);
1282 }
1283 
IsRunning()1284 bool AUAudioInputStream::IsRunning() {
1285   DCHECK(thread_checker_.CalledOnValidThread());
1286   if (!audio_unit_)
1287     return false;
1288   UInt32 is_running = 0;
1289   UInt32 size = sizeof(is_running);
1290   OSStatus error =
1291       AudioUnitGetProperty(audio_unit_, kAudioOutputUnitProperty_IsRunning,
1292                            kAudioUnitScope_Global, 0, &is_running, &size);
1293   OSSTATUS_DLOG_IF(ERROR, error != noErr, error)
1294       << "AudioUnitGetProperty(kAudioOutputUnitProperty_IsRunning) failed";
1295   DVLOG(1) << "IsRunning: " << is_running;
1296   return (error == noErr && is_running);
1297 }
1298 
HandleError(OSStatus err)1299 void AUAudioInputStream::HandleError(OSStatus err) {
1300   // Log the latest OSStatus error message and also change the sign of the
1301   // error if no callbacks are active. I.e., the sign of the error message
1302   // carries one extra level of information.
1303   base::UmaHistogramSparse("Media.InputErrorMac",
1304                            GetInputCallbackIsActive() ? err : (err * -1));
1305   NOTREACHED() << "error " << logging::DescriptionFromOSStatus(err) << " ("
1306                << err << ")";
1307   if (sink_)
1308     sink_->OnError();
1309 }
1310 
IsVolumeSettableOnChannel(int channel)1311 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel) {
1312   Boolean is_settable = false;
1313   AudioObjectPropertyAddress property_address = {
1314       kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput,
1315       static_cast<UInt32>(channel)};
1316   OSStatus result = AudioObjectIsPropertySettable(
1317       input_device_id_, &property_address, &is_settable);
1318   return (result == noErr) ? is_settable : false;
1319 }
1320 
SetInputCallbackIsActive(bool enabled)1321 void AUAudioInputStream::SetInputCallbackIsActive(bool enabled) {
1322   base::subtle::Release_Store(&input_callback_is_active_, enabled);
1323 }
1324 
GetInputCallbackIsActive()1325 bool AUAudioInputStream::GetInputCallbackIsActive() {
1326   return (base::subtle::Acquire_Load(&input_callback_is_active_) != false);
1327 }
1328 
CheckInputStartupSuccess()1329 void AUAudioInputStream::CheckInputStartupSuccess() {
1330   DCHECK(thread_checker_.CalledOnValidThread());
1331   DCHECK(IsRunning());
1332   // Only add UMA stat related to failing input audio for streams where
1333   // the AGC has been enabled, e.g. WebRTC audio input streams.
1334   if (GetAutomaticGainControl()) {
1335     // Check if we have called Start() and input callbacks have actually
1336     // started in time as they should. If that is not the case, we have a
1337     // problem and the stream is considered dead.
1338     const bool input_callback_is_active = GetInputCallbackIsActive();
1339     UMA_HISTOGRAM_BOOLEAN("Media.Audio.InputStartupSuccessMac",
1340                           input_callback_is_active);
1341     DVLOG(1) << "input_callback_is_active: " << input_callback_is_active;
1342     if (!input_callback_is_active) {
1343       // Now when we know that startup has failed for some reason, add extra
1344       // UMA stats in an attempt to figure out the exact reason.
1345       AddHistogramsForFailedStartup();
1346     }
1347   }
1348 }
1349 
CloseAudioUnit()1350 void AUAudioInputStream::CloseAudioUnit() {
1351   DCHECK(thread_checker_.CalledOnValidThread());
1352   DVLOG(1) << "CloseAudioUnit";
1353   if (!audio_unit_)
1354     return;
1355   OSStatus result = AudioUnitUninitialize(audio_unit_);
1356   OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
1357       << "AudioUnitUninitialize() failed.";
1358   result = AudioComponentInstanceDispose(audio_unit_);
1359   OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
1360       << "AudioComponentInstanceDispose() failed.";
1361   audio_unit_ = 0;
1362 }
1363 
AddHistogramsForFailedStartup()1364 void AUAudioInputStream::AddHistogramsForFailedStartup() {
1365   DCHECK(thread_checker_.CalledOnValidThread());
1366   UMA_HISTOGRAM_BOOLEAN("Media.Audio.InputBufferSizeWasChangedMac",
1367                         buffer_size_was_changed_);
1368   // |input_params_.frames_per_buffer()| is set at construction and corresponds
1369   // to the requested (by the client) number of audio frames per I/O buffer
1370   // connected to the selected input device. Ideally, this size will be the same
1371   // as the native I/O buffer size given by |io_buffer_frame_size_|.
1372   base::UmaHistogramSparse("Media.Audio.RequestedInputBufferFrameSizeMac",
1373                            input_params_.frames_per_buffer());
1374   DVLOG(1) << "number_of_frames_: " << input_params_.frames_per_buffer();
1375   // This value indicates the number of frames in the IO buffers connected to
1376   // the selected input device. It has been set by the audio manger in Open()
1377   // and can be the same as |input_params_.frames_per_buffer()|, which is the
1378   // desired buffer size. These two values might differ if other streams are
1379   // using the same device and any of these streams have asked for a smaller
1380   // buffer size.
1381   base::UmaHistogramSparse("Media.Audio.ActualInputBufferFrameSizeMac",
1382                            io_buffer_frame_size_);
1383   DVLOG(1) << "io_buffer_frame_size_: " << io_buffer_frame_size_;
1384   // Add information about things like number of logical processors etc.
1385   AddSystemInfoToUMA();
1386 }
1387 
UpdateCaptureTimestamp(const AudioTimeStamp * timestamp)1388 void AUAudioInputStream::UpdateCaptureTimestamp(
1389     const AudioTimeStamp* timestamp) {
1390   if ((timestamp->mFlags & kAudioTimeStampSampleTimeValid) == 0)
1391     return;
1392 
1393   if (last_sample_time_) {
1394     DCHECK_NE(0U, last_number_of_frames_);
1395     UInt32 diff =
1396         static_cast<UInt32>(timestamp->mSampleTime - last_sample_time_);
1397     if (diff != last_number_of_frames_) {
1398       DCHECK_GT(diff, last_number_of_frames_);
1399       // We were given samples post what we expected. Update the glitch count
1400       // etc. and keep a record of the largest glitch.
1401       auto lost_frames = diff - last_number_of_frames_;
1402       total_lost_frames_ += lost_frames;
1403       if (lost_frames > largest_glitch_frames_)
1404         largest_glitch_frames_ = lost_frames;
1405       ++glitches_detected_;
1406     }
1407   }
1408 
1409   // Store the last sample time for use next time we get called back.
1410   last_sample_time_ = timestamp->mSampleTime;
1411 }
1412 
ReportAndResetStats()1413 void AUAudioInputStream::ReportAndResetStats() {
1414   if (last_sample_time_ == 0)
1415     return;  // No stats gathered to report.
1416 
1417   // A value of 0 indicates that we got the buffer size we asked for.
1418   UMA_HISTOGRAM_COUNTS_10000("Media.Audio.Capture.FramesProvided",
1419                              number_of_frames_provided_);
1420   // Even if there aren't any glitches, we want to record it to get a feel for
1421   // how often we get no glitches vs the alternative.
1422   UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Capture.Glitches", glitches_detected_);
1423 
1424   auto lost_frames_ms = (total_lost_frames_ * 1000) / format_.mSampleRate;
1425   std::string log_message = base::StringPrintf(
1426       "AU in: Total glitches=%d. Total frames lost=%d (%.0lf ms).",
1427       glitches_detected_, total_lost_frames_, lost_frames_ms);
1428   log_callback_.Run(log_message);
1429 
1430   if (glitches_detected_ != 0) {
1431     UMA_HISTOGRAM_LONG_TIMES("Media.Audio.Capture.LostFramesInMs",
1432                              base::TimeDelta::FromMilliseconds(lost_frames_ms));
1433     auto largest_glitch_ms =
1434         (largest_glitch_frames_ * 1000) / format_.mSampleRate;
1435     UMA_HISTOGRAM_CUSTOM_TIMES(
1436         "Media.Audio.Capture.LargestGlitchMs",
1437         base::TimeDelta::FromMilliseconds(largest_glitch_ms),
1438         base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
1439         50);
1440     DLOG(WARNING) << log_message;
1441   }
1442 
1443   number_of_frames_provided_ = 0;
1444   glitches_detected_ = 0;
1445   last_sample_time_ = 0;
1446   last_number_of_frames_ = 0;
1447   total_lost_frames_ = 0;
1448   largest_glitch_frames_ = 0;
1449 }
1450 
1451 // TODO(ossu): Ideally, we'd just use the mono stream directly. However, since
1452 // mono or stereo (may) depend on if we want to run the echo canceller, and
1453 // since we can't provide two sets of AudioParameters for a device, this is the
1454 // best we can do right now.
1455 //
1456 // The algorithm works by copying a sample at offset N to 2*N and 2*N + 1, e.g.:
1457 //  ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
1458 // | a1 | a2 | a3 | b1 | b2 | b3 | c1 | c2 | c3 | -- | -- | -- | -- | -- | ...
1459 //  ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
1460 //  into
1461 //  ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
1462 // | a1 | a2 | a3 | a1 | a2 | a3 | b1 | b2 | b3 | b1 | b2 | b3 | c1 | c2 | ...
1463 //  ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
1464 //
1465 // To support various different sample sizes, this is done byte-by-byte. Only
1466 // the first half of the buffer will be used as input. It is expected to contain
1467 // mono audio. The second half is output only. Since the data is expanding, the
1468 // algorithm starts copying from the last sample. Otherwise it would overwrite
1469 // data not already copied.
UpmixMonoToStereoInPlace(AudioBuffer * audio_buffer,int bytes_per_sample)1470 void AUAudioInputStream::UpmixMonoToStereoInPlace(AudioBuffer* audio_buffer,
1471                                                   int bytes_per_sample) {
1472   constexpr int channels = 2;
1473   DCHECK_EQ(audio_buffer->mNumberChannels, static_cast<UInt32>(channels));
1474   const int total_bytes = audio_buffer->mDataByteSize;
1475   const int frames = total_bytes / bytes_per_sample / channels;
1476   char* byte_ptr = reinterpret_cast<char*>(audio_buffer->mData);
1477   for (int i = frames - 1; i >= 0; --i) {
1478     int in_offset = (bytes_per_sample * i);
1479     int out_offset = (channels * bytes_per_sample * i);
1480     for (int b = 0; b < bytes_per_sample; ++b) {
1481       const char byte = byte_ptr[in_offset + b];
1482       byte_ptr[out_offset + b] = byte;
1483       byte_ptr[out_offset + bytes_per_sample + b] = byte;
1484     }
1485   }
1486 }
1487 
1488 }  // namespace media
1489