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

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: 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"
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 const AudioParameters& input_params, 243 const AudioParameters& input_params,
244 AudioDeviceID audio_device_id, 244 AudioDeviceID audio_device_id,
245 const AudioManager::LogCallback& log_callback) 245 const AudioManager::LogCallback& log_callback)
246 : manager_(manager), 246 : manager_(manager),
247 number_of_frames_(input_params.frames_per_buffer()), 247 number_of_frames_(input_params.frames_per_buffer()),
248 number_of_frames_provided_(0), 248 number_of_frames_provided_(0),
249 io_buffer_frame_size_(0), 249 io_buffer_frame_size_(0),
250 sink_(nullptr), 250 sink_(nullptr),
251 audio_unit_(0), 251 audio_unit_(0),
252 input_device_id_(audio_device_id), 252 input_device_id_(audio_device_id),
253 hardware_latency_frames_(0),
254 number_of_channels_in_frame_(0), 253 number_of_channels_in_frame_(0),
255 fifo_(input_params.channels(), 254 fifo_(input_params.channels(),
256 number_of_frames_, 255 number_of_frames_,
257 kNumberOfBlocksBufferInFifo), 256 kNumberOfBlocksBufferInFifo),
258 input_callback_is_active_(false), 257 input_callback_is_active_(false),
259 start_was_deferred_(false), 258 start_was_deferred_(false),
260 buffer_size_was_changed_(false), 259 buffer_size_was_changed_(false),
261 audio_unit_render_has_worked_(false), 260 audio_unit_render_has_worked_(false),
262 device_listener_is_active_(false), 261 device_listener_is_active_(false),
263 last_sample_time_(0.0), 262 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. 509 // Finally, initialize the audio unit and ensure that it is ready to render.
511 // Allocates memory according to the maximum number of audio frames 510 // Allocates memory according to the maximum number of audio frames
512 // it can produce in response to a single render call. 511 // it can produce in response to a single render call.
513 result = AudioUnitInitialize(audio_unit_); 512 result = AudioUnitInitialize(audio_unit_);
514 if (result != noErr) { 513 if (result != noErr) {
515 HandleError(result); 514 HandleError(result);
516 return false; 515 return false;
517 } 516 }
518 517
519 // The hardware latency is fixed and will not change during the call. 518 // The hardware latency is fixed and will not change during the call.
520 hardware_latency_frames_ = GetHardwareLatency(); 519 hardware_latency_ = GetHardwareLatency();
521 520
522 // The master channel is 0, Left and right are channels 1 and 2. 521 // 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_|. 522 // And the master channel is not counted in |number_of_channels_in_frame_|.
524 number_of_channels_in_frame_ = GetNumberOfChannelsFromStream(); 523 number_of_channels_in_frame_ = GetNumberOfChannelsFromStream();
525 524
526 return true; 525 return true;
527 } 526 }
528 527
529 void AUAudioInputStream::Start(AudioInputCallback* callback) { 528 void AUAudioInputStream::Start(AudioInputCallback* callback) {
530 DCHECK(thread_checker_.CalledOnValidThread()); 529 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 UpdateCaptureTimestamp(time_stamp); 952 UpdateCaptureTimestamp(time_stamp);
954 last_number_of_frames_ = number_of_frames; 953 last_number_of_frames_ = number_of_frames;
955 954
956 // TODO(grunell): We'll only care about the first buffer size change, any 955 // 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. 956 // 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. 957 // 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) 958 if (number_of_frames != number_of_frames_ && number_of_frames_provided_ == 0)
960 number_of_frames_provided_ = number_of_frames; 959 number_of_frames_provided_ = number_of_frames;
961 960
962 // Update the capture latency. 961 // Update the capture latency.
963 double capture_latency_frames = GetCaptureLatency(time_stamp); 962 base::TimeDelta capture_latency = GetCaptureLatency(time_stamp);
963 base::TimeDelta delay_timestamp = base::TimeTicks::Now();
964 964
965 // The AGC volume level is updated once every second on a separate thread. 965 // 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 966 // Note that, |volume| is also updated each time SetVolume() is called
967 // through IPC by the render-side AGC. 967 // through IPC by the render-side AGC.
968 double normalized_volume = 0.0; 968 double normalized_volume = 0.0;
969 GetAgcVolume(&normalized_volume); 969 GetAgcVolume(&normalized_volume);
970 970
971 AudioBuffer& buffer = io_data->mBuffers[0]; 971 AudioBuffer& buffer = io_data->mBuffers[0];
972 uint8_t* audio_data = reinterpret_cast<uint8_t*>(buffer.mData); 972 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); 973 DCHECK(audio_data);
976 if (!audio_data) 974 if (!audio_data)
977 return kAudioUnitErr_InvalidElement; 975 return kAudioUnitErr_InvalidElement;
978 976
979 // Dynamically increase capacity of the FIFO to handle larger buffers from 977 // Dynamically increase capacity of the FIFO to handle larger buffers from
980 // CoreAudio. This can happen in combination with Apple Thunderbolt Displays 978 // 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 979 // when the Display Audio is used as capture source and the cable is first
982 // remove and then inserted again. 980 // remove and then inserted again.
983 // See http://www.crbug.com/434681 for details. 981 // See http://www.crbug.com/434681 for details.
984 if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) { 982 if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) {
985 // Derive required increase in number of FIFO blocks. The increase is 983 // Derive required increase in number of FIFO blocks. The increase is
986 // typically one block. 984 // typically one block.
987 const int blocks = 985 const int blocks =
988 static_cast<int>((number_of_frames - fifo_.GetUnfilledFrames()) / 986 static_cast<int>((number_of_frames - fifo_.GetUnfilledFrames()) /
989 number_of_frames_) + 1; 987 number_of_frames_) + 1;
990 DLOG(WARNING) << "Increasing FIFO capacity by " << blocks << " blocks"; 988 DLOG(WARNING) << "Increasing FIFO capacity by " << blocks << " blocks";
991 TRACE_EVENT_INSTANT1("audio", "Increasing FIFO capacity", 989 TRACE_EVENT_INSTANT1("audio", "Increasing FIFO capacity",
992 TRACE_EVENT_SCOPE_THREAD, "increased by", blocks); 990 TRACE_EVENT_SCOPE_THREAD, "increased by", blocks);
993 fifo_.IncreaseCapacity(blocks); 991 fifo_.IncreaseCapacity(blocks);
994 } 992 }
995 993
996 // Copy captured (and interleaved) data into FIFO. 994 // Copy captured (and interleaved) data into FIFO.
997 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); 995 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8);
o1ka 2017/02/10 13:28:50 Shouldn't we push latency and timestamp info the F
998 996
999 // Consume and deliver the data when the FIFO has a block of available data. 997 // Consume and deliver the data when the FIFO has a block of available data.
1000 while (fifo_.available_blocks()) { 998 while (fifo_.available_blocks()) {
1001 const AudioBus* audio_bus = fifo_.Consume(); 999 const AudioBus* audio_bus = fifo_.Consume();
1002 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); 1000 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_));
1003 1001
1004 // Compensate the audio delay caused by the FIFO. 1002 // Compensate the audio delay caused by the FIFO.
1005 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame; 1003 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame;
o1ka 2017/02/10 13:28:50 Hmm.. does it really compile? :)
DaleCurtis 2017/02/11 01:43:13 Like I said, not done yet :)
1006 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume); 1004 sink_->OnData(this, audio_bus, capture_latency, delay_timestamp,
o1ka 2017/02/10 13:28:50 Shouldn't we adjust latency and timestamp values t
1005 normalized_volume);
1007 } 1006 }
1008 1007
1009 return noErr; 1008 return noErr;
1010 } 1009 }
1011 1010
1012 void AUAudioInputStream::DevicePropertyChangedOnMainThread( 1011 void AUAudioInputStream::DevicePropertyChangedOnMainThread(
1013 const std::vector<UInt32>& properties) { 1012 const std::vector<UInt32>& properties) {
1014 DCHECK(thread_checker_.CalledOnValidThread()); 1013 DCHECK(thread_checker_.CalledOnValidThread());
1015 DCHECK(device_listener_is_active_); 1014 DCHECK(device_listener_is_active_);
1016 // Use property as key to a map and increase its value. We are not 1015 // 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, 1105 kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
1107 kAudioObjectPropertyElementMaster}; 1106 kAudioObjectPropertyElementMaster};
1108 result = AudioObjectGetPropertyData(device_id, &nominal_sample_rate_address, 1107 result = AudioObjectGetPropertyData(device_id, &nominal_sample_rate_address,
1109 0, 0, &info_size, &nominal_sample_rate); 1108 0, 0, &info_size, &nominal_sample_rate);
1110 if (result != noErr) 1109 if (result != noErr)
1111 return 0.0; 1110 return 0.0;
1112 1111
1113 return static_cast<int>(nominal_sample_rate); 1112 return static_cast<int>(nominal_sample_rate);
1114 } 1113 }
1115 1114
1116 double AUAudioInputStream::GetHardwareLatency() { 1115 base::TimeDelta AUAudioInputStream::GetHardwareLatency() {
1117 if (!audio_unit_ || input_device_id_ == kAudioObjectUnknown) { 1116 if (!audio_unit_ || input_device_id_ == kAudioObjectUnknown) {
1118 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown"; 1117 DLOG(WARNING) << "Audio unit object is NULL or device ID is unknown";
1119 return 0.0; 1118 return base::TimeDelta();
1120 } 1119 }
1121 1120
1122 // Get audio unit latency. 1121 // Get audio unit latency.
1123 Float64 audio_unit_latency_sec = 0.0; 1122 Float64 audio_unit_latency_sec = 0.0;
1124 UInt32 size = sizeof(audio_unit_latency_sec); 1123 UInt32 size = sizeof(audio_unit_latency_sec);
1125 OSStatus result = AudioUnitGetProperty( 1124 OSStatus result = AudioUnitGetProperty(
1126 audio_unit_, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, 1125 audio_unit_, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0,
1127 &audio_unit_latency_sec, &size); 1126 &audio_unit_latency_sec, &size);
1128 OSSTATUS_DLOG_IF(WARNING, result != noErr, result) 1127 OSSTATUS_DLOG_IF(WARNING, result != noErr, result)
1129 << "Could not get audio unit latency"; 1128 << "Could not get audio unit latency";
1130 1129
1131 // Get input audio device latency. 1130 // Get input audio device latency.
1132 AudioObjectPropertyAddress property_address = { 1131 AudioObjectPropertyAddress property_address = {
1133 kAudioDevicePropertyLatency, kAudioDevicePropertyScopeInput, 1132 kAudioDevicePropertyLatency, kAudioDevicePropertyScopeInput,
1134 kAudioObjectPropertyElementMaster}; 1133 kAudioObjectPropertyElementMaster};
1135 UInt32 device_latency_frames = 0; 1134 UInt32 device_latency_frames = 0;
1136 size = sizeof(device_latency_frames); 1135 size = sizeof(device_latency_frames);
1137 result = AudioObjectGetPropertyData(input_device_id_, &property_address, 0, 1136 result = AudioObjectGetPropertyData(input_device_id_, &property_address, 0,
1138 nullptr, &size, &device_latency_frames); 1137 nullptr, &size, &device_latency_frames);
1139 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency."; 1138 DLOG_IF(WARNING, result != noErr) << "Could not get audio device latency.";
1140 1139
1141 return static_cast<double>((audio_unit_latency_sec * format_.mSampleRate) + 1140 return base::TimeDelta::FromSecondsD(
1142 device_latency_frames); 1141 audio_unit_latency_sec +
1142 device_latency_frames / static_cast<double>(format_.mSampleRate));
1143 } 1143 }
1144 1144
1145 double AUAudioInputStream::GetCaptureLatency( 1145 base::TimeDelta AUAudioInputStream::GetCaptureLatency(
1146 const AudioTimeStamp* input_time_stamp) { 1146 const AudioTimeStamp* input_time_stamp) {
1147 // Get the delay between between the actual recording instant and the time 1147 // Get the delay between between the actual recording instant and the time
1148 // when the data packet is provided as a callback. 1148 // when the data packet is provided as a callback.
1149 UInt64 capture_time_ns = 1149 UInt64 capture_time_ns =
1150 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime); 1150 AudioConvertHostTimeToNanos(input_time_stamp->mHostTime);
1151 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); 1151 UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
1152 double delay_frames = static_cast<double>(1e-9 * (now_ns - capture_time_ns) *
1153 format_.mSampleRate);
1154 1152
1155 // Total latency is composed by the dynamic latency and the fixed 1153 // Total latency is composed by the dynamic latency and the fixed
1156 // hardware latency. 1154 // hardware latency.
1157 return (delay_frames + hardware_latency_frames_); 1155 return hardware_latency_ +
1156 base::TimeDelta::FromMicroseconds((now_ns - capture_time_ns) /
1157 kNanosecondsPerMicrosecond);
1158 } 1158 }
1159 1159
1160 int AUAudioInputStream::GetNumberOfChannelsFromStream() { 1160 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
1161 // Get the stream format, to be able to read the number of channels. 1161 // Get the stream format, to be able to read the number of channels.
1162 AudioObjectPropertyAddress property_address = { 1162 AudioObjectPropertyAddress property_address = {
1163 kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeInput, 1163 kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeInput,
1164 kAudioObjectPropertyElementMaster}; 1164 kAudioObjectPropertyElementMaster};
1165 AudioStreamBasicDescription stream_format; 1165 AudioStreamBasicDescription stream_format;
1166 UInt32 size = sizeof(stream_format); 1166 UInt32 size = sizeof(stream_format);
1167 OSStatus result = AudioObjectGetPropertyData( 1167 OSStatus result = AudioObjectGetPropertyData(
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 1681
1682 number_of_frames_provided_ = 0; 1682 number_of_frames_provided_ = 0;
1683 glitches_detected_ = 0; 1683 glitches_detected_ = 0;
1684 last_sample_time_ = 0; 1684 last_sample_time_ = 0;
1685 last_number_of_frames_ = 0; 1685 last_number_of_frames_ = 0;
1686 total_lost_frames_ = 0; 1686 total_lost_frames_ = 0;
1687 largest_glitch_frames_ = 0; 1687 largest_glitch_frames_ = 0;
1688 } 1688 }
1689 1689
1690 } // namespace media 1690 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698