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

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

Issue 2689483006: Switch browser side audio capture path to use base time primitives. (Closed)
Patch Set: Bloop Created 3 years, 10 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_low_latency_input_mac.h" 5 #include "media/audio/mac/audio_low_latency_input_mac.h"
6 #include <CoreServices/CoreServices.h> 6 #include <CoreServices/CoreServices.h>
7 #include <mach/mach.h> 7 #include <mach/mach.h>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/mac/mac_logging.h" 12 #include "base/mac/mac_logging.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/sparse_histogram.h" 14 #include "base/metrics/sparse_histogram.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "base/sys_info.h" 16 #include "base/sys_info.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "base/trace_event/trace_event.h" 18 #include "base/trace_event/trace_event.h"
19 #include "media/audio/mac/audio_manager_mac.h" 19 #include "media/audio/mac/audio_manager_mac.h"
20 #include "media/base/audio_bus.h" 20 #include "media/base/audio_bus.h"
21 #include "media/base/audio_timestamp_helper.h"
21 #include "media/base/data_buffer.h" 22 #include "media/base/data_buffer.h"
22 23
23 namespace media { 24 namespace media {
24 25
25 // Number of blocks of buffers used in the |fifo_|. 26 // Number of blocks of buffers used in the |fifo_|.
26 const int kNumberOfBlocksBufferInFifo = 2; 27 const int kNumberOfBlocksBufferInFifo = 2;
27 28
28 // Max length of sequence of TooManyFramesToProcessError errors. 29 // Max length of sequence of TooManyFramesToProcessError errors.
29 // The stream will be stopped as soon as this time limit is passed. 30 // The stream will be stopped as soon as this time limit is passed.
30 const int kMaxErrorTimeoutInSeconds = 1; 31 const int kMaxErrorTimeoutInSeconds = 1;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 const AudioParameters& input_params, 244 const AudioParameters& input_params,
244 AudioDeviceID audio_device_id, 245 AudioDeviceID audio_device_id,
245 const AudioManager::LogCallback& log_callback) 246 const AudioManager::LogCallback& log_callback)
246 : manager_(manager), 247 : manager_(manager),
247 number_of_frames_(input_params.frames_per_buffer()), 248 number_of_frames_(input_params.frames_per_buffer()),
248 number_of_frames_provided_(0), 249 number_of_frames_provided_(0),
249 io_buffer_frame_size_(0), 250 io_buffer_frame_size_(0),
250 sink_(nullptr), 251 sink_(nullptr),
251 audio_unit_(0), 252 audio_unit_(0),
252 input_device_id_(audio_device_id), 253 input_device_id_(audio_device_id),
253 hardware_latency_frames_(0),
254 number_of_channels_in_frame_(0), 254 number_of_channels_in_frame_(0),
255 fifo_(input_params.channels(), 255 fifo_(input_params.channels(),
256 number_of_frames_, 256 number_of_frames_,
257 kNumberOfBlocksBufferInFifo), 257 kNumberOfBlocksBufferInFifo),
258 input_callback_is_active_(false), 258 input_callback_is_active_(false),
259 start_was_deferred_(false), 259 start_was_deferred_(false),
260 buffer_size_was_changed_(false), 260 buffer_size_was_changed_(false),
261 audio_unit_render_has_worked_(false), 261 audio_unit_render_has_worked_(false),
262 device_listener_is_active_(false), 262 device_listener_is_active_(false),
263 last_sample_time_(0.0), 263 last_sample_time_(0.0),
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 // Finally, initialize the audio unit and ensure that it is ready to render. 510 // Finally, initialize the audio unit and ensure that it is ready to render.
511 // Allocates memory according to the maximum number of audio frames 511 // Allocates memory according to the maximum number of audio frames
512 // it can produce in response to a single render call. 512 // it can produce in response to a single render call.
513 result = AudioUnitInitialize(audio_unit_); 513 result = AudioUnitInitialize(audio_unit_);
514 if (result != noErr) { 514 if (result != noErr) {
515 HandleError(result); 515 HandleError(result);
516 return false; 516 return false;
517 } 517 }
518 518
519 // The hardware latency is fixed and will not change during the call. 519 // The hardware latency is fixed and will not change during the call.
520 hardware_latency_frames_ = GetHardwareLatency(); 520 hardware_latency_ = GetHardwareLatency();
521 521
522 // The master channel is 0, Left and right are channels 1 and 2. 522 // The master channel is 0, Left and right are channels 1 and 2.
523 // And the master channel is not counted in |number_of_channels_in_frame_|. 523 // And the master channel is not counted in |number_of_channels_in_frame_|.
524 number_of_channels_in_frame_ = GetNumberOfChannelsFromStream(); 524 number_of_channels_in_frame_ = GetNumberOfChannelsFromStream();
525 525
526 return true; 526 return true;
527 } 527 }
528 528
529 void AUAudioInputStream::Start(AudioInputCallback* callback) { 529 void AUAudioInputStream::Start(AudioInputCallback* callback) {
530 DCHECK(thread_checker_.CalledOnValidThread()); 530 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 UpdateCaptureTimestamp(time_stamp); 953 UpdateCaptureTimestamp(time_stamp);
954 last_number_of_frames_ = number_of_frames; 954 last_number_of_frames_ = number_of_frames;
955 955
956 // TODO(grunell): We'll only care about the first buffer size change, any 956 // TODO(grunell): We'll only care about the first buffer size change, any
957 // further changes will be ignored. This is in line with output side stats. 957 // further changes will be ignored. This is in line with output side stats.
958 // It would be nice to have all changes reflected in UMA stats. 958 // It would be nice to have all changes reflected in UMA stats.
959 if (number_of_frames != number_of_frames_ && number_of_frames_provided_ == 0) 959 if (number_of_frames != number_of_frames_ && number_of_frames_provided_ == 0)
960 number_of_frames_provided_ = number_of_frames; 960 number_of_frames_provided_ = number_of_frames;
961 961
962 // Update the capture latency. 962 // Update the capture latency.
963 double capture_latency_frames = GetCaptureLatency(time_stamp); 963 base::TimeDelta delay = GetCaptureLatency(time_stamp);
964 base::TimeTicks delay_timestamp = base::TimeTicks::Now();
964 965
965 // The AGC volume level is updated once every second on a separate thread. 966 // The AGC volume level is updated once every second on a separate thread.
966 // Note that, |volume| is also updated each time SetVolume() is called 967 // Note that, |volume| is also updated each time SetVolume() is called
967 // through IPC by the render-side AGC. 968 // through IPC by the render-side AGC.
968 double normalized_volume = 0.0; 969 double normalized_volume = 0.0;
969 GetAgcVolume(&normalized_volume); 970 GetAgcVolume(&normalized_volume);
970 971
971 AudioBuffer& buffer = io_data->mBuffers[0]; 972 AudioBuffer& buffer = io_data->mBuffers[0];
972 uint8_t* audio_data = reinterpret_cast<uint8_t*>(buffer.mData); 973 uint8_t* audio_data = reinterpret_cast<uint8_t*>(buffer.mData);
973 uint32_t capture_delay_bytes = static_cast<uint32_t>(
974 (capture_latency_frames + 0.5) * format_.mBytesPerFrame);
975 DCHECK(audio_data); 974 DCHECK(audio_data);
976 if (!audio_data) 975 if (!audio_data)
977 return kAudioUnitErr_InvalidElement; 976 return kAudioUnitErr_InvalidElement;
978 977
979 // Dynamically increase capacity of the FIFO to handle larger buffers from 978 // Dynamically increase capacity of the FIFO to handle larger buffers from
980 // CoreAudio. This can happen in combination with Apple Thunderbolt Displays 979 // CoreAudio. This can happen in combination with Apple Thunderbolt Displays
981 // when the Display Audio is used as capture source and the cable is first 980 // when the Display Audio is used as capture source and the cable is first
982 // remove and then inserted again. 981 // remove and then inserted again.
983 // See http://www.crbug.com/434681 for details. 982 // See http://www.crbug.com/434681 for details.
984 if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) { 983 if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) {
(...skipping 10 matching lines...) Expand all
995 994
996 // Copy captured (and interleaved) data into FIFO. 995 // Copy captured (and interleaved) data into FIFO.
997 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); 996 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8);
998 997
999 // Consume and deliver the data when the FIFO has a block of available data. 998 // Consume and deliver the data when the FIFO has a block of available data.
1000 while (fifo_.available_blocks()) { 999 while (fifo_.available_blocks()) {
1001 const AudioBus* audio_bus = fifo_.Consume(); 1000 const AudioBus* audio_bus = fifo_.Consume();
1002 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); 1001 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_));
1003 1002
1004 // Compensate the audio delay caused by the FIFO. 1003 // Compensate the audio delay caused by the FIFO.
1005 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame; 1004 delay += AudioTimestampHelper::FramesToTime(fifo_.GetAvailableFrames(),
1006 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume); 1005 format_.mSampleRate);
1006 sink_->OnData(this, audio_bus, capture_latency, delay_timestamp,
miu 2017/02/12 04:21:36 Should |capture_latency| be |delay| here? Otherwis
1007 normalized_volume);
1007 } 1008 }
1008 1009
1009 return noErr; 1010 return noErr;
1010 } 1011 }
1011 1012
1012 void AUAudioInputStream::DevicePropertyChangedOnMainThread( 1013 void AUAudioInputStream::DevicePropertyChangedOnMainThread(
1013 const std::vector<UInt32>& properties) { 1014 const std::vector<UInt32>& properties) {
1014 DCHECK(thread_checker_.CalledOnValidThread()); 1015 DCHECK(thread_checker_.CalledOnValidThread());
1015 DCHECK(device_listener_is_active_); 1016 DCHECK(device_listener_is_active_);
1016 // Use property as key to a map and increase its value. We are not 1017 // Use property as key to a map and increase its value. We are not
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, 1107 kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
1107 kAudioObjectPropertyElementMaster}; 1108 kAudioObjectPropertyElementMaster};
1108 result = AudioObjectGetPropertyData(device_id, &nominal_sample_rate_address, 1109 result = AudioObjectGetPropertyData(device_id, &nominal_sample_rate_address,
1109 0, 0, &info_size, &nominal_sample_rate); 1110 0, 0, &info_size, &nominal_sample_rate);
1110 if (result != noErr) 1111 if (result != noErr)
1111 return 0.0; 1112 return 0.0;
1112 1113
1113 return static_cast<int>(nominal_sample_rate); 1114 return static_cast<int>(nominal_sample_rate);
1114 } 1115 }
1115 1116
1116 double AUAudioInputStream::GetHardwareLatency() { 1117 base::TimeDelta AUAudioInputStream::GetHardwareLatency() {
1117 if (!audio_unit_ || input_device_id_ == kAudioObjectUnknown) { 1118 if (!audio_unit_ || input_device_id_ == kAudioObjectUnknown) {
1118 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown"; 1119 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown";
1119 return 0.0; 1120 return base::TimeDelta();
1120 } 1121 }
1121 1122
1122 // Get audio unit latency. 1123 // Get audio unit latency.
1123 Float64 audio_unit_latency_sec = 0.0; 1124 Float64 audio_unit_latency_sec = 0.0;
1124 UInt32 size = sizeof(audio_unit_latency_sec); 1125 UInt32 size = sizeof(audio_unit_latency_sec);
1125 OSStatus result = AudioUnitGetProperty( 1126 OSStatus result = AudioUnitGetProperty(
1126 audio_unit_, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, 1127 audio_unit_, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0,
1127 &audio_unit_latency_sec, &size); 1128 &audio_unit_latency_sec, &size);
1128 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) 1129 OSSTATUS_DLOG_IF(WARNING, result != noErr, result)
1129 << "Could not get audio unit latency"; 1130 << "Could not get audio unit latency";
1130 1131
1131 // Get input audio device latency. 1132 // Get input audio device latency.
1132 AudioObjectPropertyAddress property_address = { 1133 AudioObjectPropertyAddress property_address = {
1133 kAudioDevicePropertyLatency, kAudioDevicePropertyScopeInput, 1134 kAudioDevicePropertyLatency, kAudioDevicePropertyScopeInput,
1134 kAudioObjectPropertyElementMaster}; 1135 kAudioObjectPropertyElementMaster};
1135 UInt32 device_latency_frames = 0; 1136 UInt32 device_latency_frames = 0;
1136 size = sizeof(device_latency_frames); 1137 size = sizeof(device_latency_frames);
1137 result = AudioObjectGetPropertyData(input_device_id_, &property_address, 0, 1138 result = AudioObjectGetPropertyData(input_device_id_, &property_address, 0,
1138 nullptr, &size, &device_latency_frames); 1139 nullptr, &size, &device_latency_frames);
1139 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency."; 1140 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency.";
1140 1141
1141 return static_cast<double>((audio_unit_latency_sec * format_.mSampleRate) + 1142 return base::TimeDelta::FromSecondsD(audio_unit_latency_sec) +
1142 device_latency_frames); 1143 AudioTimestampHelper::FramesToTime(device_latency_frames,
1144 format_.mSampleRate);
1143 } 1145 }
1144 1146
1145 double AUAudioInputStream::GetCaptureLatency( 1147 base::TimeDelta AUAudioInputStream::GetCaptureLatency(
1146 const AudioTimeStamp* input_time_stamp) { 1148 const AudioTimeStamp* input_time_stamp) {
1147 // Get the delay between between the actual recording instant and the time 1149 // Get the delay between between the actual recording instant and the time
1148 // when the data packet is provided as a callback. 1150 // when the data packet is provided as a callback.
1149 UInt64 capture_time_ns = 1151 UInt64 capture_time_ns =
1150 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime); 1152 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime);
1151 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); 1153 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
1152 double delay_frames = static_cast<double>(1e-9 * (now_ns - capture_time_ns) *
1153 format_.mSampleRate);
1154 1154
1155 // Total latency is composed by the dynamic latency and the fixed 1155 // Total latency is composed by the dynamic latency and the fixed
1156 // hardware latency. 1156 // hardware latency.
1157 return (delay_frames + hardware_latency_frames_); 1157 return hardware_latency_ + base::TimeDelta::FromMicroseconds(
1158 (now_ns - capture_time_ns) /
1159 base::Time::kNanosecondsPerMicrosecond);
1158 } 1160 }
1159 1161
1160 int AUAudioInputStream::GetNumberOfChannelsFromStream() { 1162 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
1161 // Get the stream format, to be able to read the number of channels. 1163 // Get the stream format, to be able to read the number of channels.
1162 AudioObjectPropertyAddress property_address = { 1164 AudioObjectPropertyAddress property_address = {
1163 kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeInput, 1165 kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeInput,
1164 kAudioObjectPropertyElementMaster}; 1166 kAudioObjectPropertyElementMaster};
1165 AudioStreamBasicDescription stream_format; 1167 AudioStreamBasicDescription stream_format;
1166 UInt32 size = sizeof(stream_format); 1168 UInt32 size = sizeof(stream_format);
1167 OSStatus result = AudioObjectGetPropertyData( 1169 OSStatus result = AudioObjectGetPropertyData(
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 1683
1682 number_of_frames_provided_ = 0; 1684 number_of_frames_provided_ = 0;
1683 glitches_detected_ = 0; 1685 glitches_detected_ = 0;
1684 last_sample_time_ = 0; 1686 last_sample_time_ = 0;
1685 last_number_of_frames_ = 0; 1687 last_number_of_frames_ = 0;
1686 total_lost_frames_ = 0; 1688 total_lost_frames_ = 0;
1687 largest_glitch_frames_ = 0; 1689 largest_glitch_frames_ = 0;
1688 } 1690 }
1689 1691
1690 } // namespace media 1692 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698