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

Unified Diff: media/audio/mac/audio_low_latency_input_mac.cc

Issue 8234009: Adding input and output delay estimation for mac. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: media/audio/mac/audio_low_latency_input_mac.cc
===================================================================
--- media/audio/mac/audio_low_latency_input_mac.cc (revision 104447)
+++ media/audio/mac/audio_low_latency_input_mac.cc (working copy)
@@ -31,7 +31,10 @@
: manager_(manager),
sink_(NULL),
audio_unit_(0),
- started_(false) {
+ input_device_id_(kAudioDeviceUnknown),
+ started_(false),
+ hardware_latency_ms_(0),
+ capture_latency_ms_(0) {
DCHECK(manager_);
// Set up the desired (output) format specified by the client.
@@ -136,13 +139,12 @@
// Set the current device of the AudioOuputUnit to default input device.
- AudioDeviceID input_device;
- UInt32 size = sizeof(input_device);
+ UInt32 size = sizeof(input_device_id_);
henrika (OOO until Aug 14) 2011/10/12 12:10:11 I would use a local here and only assign if we are
no longer working on chromium 2011/10/12 15:28:47 Done.
// First, obtain the current input device selected by the user.
result = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
&size,
- &input_device);
+ &input_device_id_);
if (result) {
HandleError(result);
return false;
@@ -154,8 +156,8 @@
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
- &input_device,
- sizeof(input_device));
+ &input_device_id_,
+ sizeof(input_device_id_));
if (result) {
HandleError(result);
return false;
@@ -212,6 +214,10 @@
HandleError(result);
return false;
}
+
+ // Update the capture device hardware latency.
henrika (OOO until Aug 14) 2011/10/12 12:10:11 Can be a static method instead.
no longer working on chromium 2011/10/12 15:28:47 Can't make it since the function needs some member
+ UpdateHardwareLatency();
+
return true;
}
@@ -289,19 +295,25 @@
// Deliver recorded data to the consumer as a callback.
return audio_input->Provide(number_of_frames,
- audio_input->audio_buffer_list());
+ audio_input->audio_buffer_list(),
+ time_stamp);
}
OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
- AudioBufferList* io_data) {
+ AudioBufferList* io_data,
+ const AudioTimeStamp* time_stamp) {
+ // Update the capture latency.
+ UpdateCaptureLatency(time_stamp);
henrika (OOO until Aug 14) 2011/10/12 12:10:11 Have you checked if we need to call it each callba
no longer working on chromium 2011/10/12 15:28:47 The value should be quite stable in the normal cas
+
AudioBuffer& buffer = io_data->mBuffers[0];
uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
+ uint32 capture_delay_bytes = (1.0e-3 * capture_latency_ms_ *
henrika (OOO until Aug 14) 2011/10/12 12:10:11 I would divide by 1000, and clean up casting here.
no longer working on chromium 2011/10/12 15:28:47 Done.
+ format_.mSampleRate * format_.mBytesPerFrame);
DCHECK(audio_data);
if (!audio_data)
return kAudioUnitErr_InvalidElement;
- // TODO(henrika): improve delay estimation. Using buffer size for now.
- sink_->OnData(this, audio_data, buffer.mDataByteSize, buffer.mDataByteSize);
+ sink_->OnData(this, audio_data, buffer.mDataByteSize, capture_delay_bytes);
return noErr;
}
@@ -347,6 +359,73 @@
return nominal_sample_rate;
}
+void AUAudioInputStream::UpdateHardwareLatency() {
+ // Get audio unit latency.
+ Float64 audio_unit_latency_s = 0;
henrika (OOO until Aug 14) 2011/10/12 12:10:11 sec and 0.0.
no longer working on chromium 2011/10/12 15:28:47 Done.
+ UInt32 size = sizeof(audio_unit_latency_s);
+ OSStatus result = AudioUnitGetProperty(
henrika (OOO until Aug 14) 2011/10/12 12:10:11 Use same style as in rest of the code.
no longer working on chromium 2011/10/12 15:28:47 Done.
+ audio_unit_, kAudioUnitProperty_Latency, kAudioUnitScope_Global,
+ 0, &audio_unit_latency_s, &size);
+ if (result) {
+ DLOG(WARNING) << "GetHardwareLatency: Could not get audio unit latency.";
+ audio_unit_latency_s = 0;
henrika (OOO until Aug 14) 2011/10/12 12:10:11 not needed
no longer working on chromium 2011/10/12 15:28:47 Done.
+ }
+
+ // Get audio device latency.
+ UInt32 device_latency_frames = 0;
+ size = sizeof(device_latency_frames);
+ result = AudioDeviceGetProperty(input_device_id_, 0, true,
henrika (OOO until Aug 14) 2011/10/12 12:10:11 ditto
no longer working on chromium 2011/10/12 15:28:47 Done.
+ kAudioDevicePropertyLatency, &size,
+ &device_latency_frames);
+ if (result) {
+ DLOG(WARNING) << "GetHardwareLatency: Could not get device latency.";
+ device_latency_frames = 0;
henrika (OOO until Aug 14) 2011/10/12 12:10:11 ditto
no longer working on chromium 2011/10/12 15:28:47 Done.
+ }
+
+ // Get the stream latency.
+ UInt32 stream_latency_frames = 0;
+ size = 0;
+ result = AudioDeviceGetPropertyInfo(input_device_id_, 0, true,
henrika (OOO until Aug 14) 2011/10/12 12:10:11 ditto
no longer working on chromium 2011/10/12 15:28:47 Done.
+ kAudioDevicePropertyStreams, &size, NULL);
+ if (!result) {
+ scoped_ptr_malloc<AudioStreamID>
+ streams(reinterpret_cast<AudioStreamID*>(malloc(size)));
+ AudioStreamID* stream_ids = streams.get();
+ result = AudioDeviceGetProperty(
henrika (OOO until Aug 14) 2011/10/12 12:10:11 ditto
no longer working on chromium 2011/10/12 15:28:47 Done.
+ input_device_id_, 0, true,
+ kAudioDevicePropertyStreams, &size, stream_ids);
+ if (result) {
+ DLOG(WARNING) << "UpdateHardwareLatency: Could not get stream id.";
+ return;
henrika (OOO until Aug 14) 2011/10/12 12:10:11 Wrong!
no longer working on chromium 2011/10/12 15:28:47 Done.
+ }
+
+ result = AudioStreamGetProperty(
+ stream_ids[0], 0, kAudioStreamPropertyLatency,
henrika (OOO until Aug 14) 2011/10/12 12:10:11 ditto
no longer working on chromium 2011/10/12 15:28:47 Done.
+ &size, &stream_latency_frames);
+ if (result) {
+ DLOG(WARNING) << "UpdateHardwareLatency: Could not get stream latency.";
+ stream_latency_frames = 0;
+ }
+ } else {
+ DLOG(WARNING) << "UpdateHardwareLatency: Could not get stream id.";
+ }
+
+ hardware_latency_ms_ = static_cast<uint32>(1.0e3 * audio_unit_latency_s +
henrika (OOO until Aug 14) 2011/10/12 12:10:11 Are you sure?
no longer working on chromium 2011/10/12 15:28:47 Done.
+ (1.0e3 * (device_latency_frames + stream_latency_frames)
+ / format_.mSampleRate) + 0.5);
+}
+
+void AUAudioInputStream::UpdateCaptureLatency(
+ const AudioTimeStamp* input_time_stamp) {
+ // Get the delay between now and when the data was hitting the hardware.
henrika (OOO until Aug 14) 2011/10/12 12:10:11 aooch ;-)
no longer working on chromium 2011/10/12 15:28:47 Done.
+ UInt64 input_time_ns = AudioConvertHostTimeToNanos(
+ input_time_stamp->mHostTime);
+ UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
+ uint32 delay_ms = static_cast<uint32>(1e-6 * (now_ns - input_time_ns) + 0.5);
henrika (OOO until Aug 14) 2011/10/12 12:10:11 Are you sure?
no longer working on chromium 2011/10/12 15:28:47 I would like to keep it, since it is a more readab
+
+ capture_latency_ms_ = delay_ms + hardware_latency_ms_;
henrika (OOO until Aug 14) 2011/10/12 12:10:11 I would add a DCHECK here just in case (santity?)
no longer working on chromium 2011/10/12 15:28:47 I need to think a bit more here. For other platfor
+}
+
void AUAudioInputStream::HandleError(OSStatus err) {
NOTREACHED() << "error code: " << err;
if (sink_)

Powered by Google App Engine
This is Rietveld 408576698