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

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

Issue 8234009: Adding input and output delay estimation for mac. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: increase the delay precision 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_output_mac.cc
===================================================================
--- media/audio/mac/audio_low_latency_output_mac.cc (revision 104447)
+++ media/audio/mac/audio_low_latency_output_mac.cc (working copy)
@@ -47,7 +47,10 @@
: manager_(manager),
source_(NULL),
output_unit_(0),
- volume_(1) {
+ output_device_id_(kAudioDeviceUnknown),
+ volume_(1),
+ hardware_latency_frames_(0),
+ playout_latency_frames_(0) {
// We must have a manager.
DCHECK(manager_);
// A frame is one sample across all channels. In interleaved audio the per
@@ -72,6 +75,16 @@
}
bool AUAudioOutputStream::Open() {
+ // Obtain the current input device selected by the user.
+ UInt32 size = sizeof(output_device_id_);
+ OSStatus result = AudioHardwareGetProperty(
+ kAudioHardwarePropertyDefaultOutputDevice,
+ &size,
+ &output_device_id_);
+ DCHECK_EQ(result, 0);
+ if (result)
+ return false;
+
// Open and initialize the DefaultOutputUnit.
Component comp;
ComponentDescription desc;
@@ -84,7 +97,7 @@
comp = FindNextComponent(0, &desc);
DCHECK(comp);
- OSStatus result = OpenAComponent(comp, &output_unit_);
+ result = OpenAComponent(comp, &output_unit_);
DCHECK_EQ(result, 0);
if (result)
return false;
@@ -95,6 +108,9 @@
if (result)
return false;
+ // Gets the playout device hardware latency and stores the value.
+ StoreHardwareLatency();
scherkus (not reviewing) 2011/10/19 16:35:15 ditto
no longer working on chromium 2011/10/19 18:19:05 Done.
+
return Configure();
}
@@ -185,11 +201,18 @@
// Note to future hackers of this function: Do not add locks here because this
// is running on a real-time thread (for low-latency).
OSStatus AUAudioOutputStream::Render(UInt32 number_of_frames,
- AudioBufferList* io_data) {
+ AudioBufferList* io_data,
+ const AudioTimeStamp* output_time_stamp) {
+ // Update the playout latency.
+ UpdatePlayoutLatency(output_time_stamp);
scherkus (not reviewing) 2011/10/19 16:35:15 ditto
no longer working on chromium 2011/10/19 18:19:05 Done.
+
AudioBuffer& buffer = io_data->mBuffers[0];
uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
+ uint32 hardware_pending_bytes = static_cast<uint32>
+ (playout_latency_frames_ * format_.mBytesPerFrame + 0.5);
uint32 filled = source_->OnMoreData(
- this, audio_data, buffer.mDataByteSize, AudioBuffersState(0, 0));
+ this, audio_data, buffer.mDataByteSize,
+ AudioBuffersState(0, hardware_pending_bytes));
// Handle channel order for 5.1 audio.
if (format_.mChannelsPerFrame == 6) {
@@ -208,7 +231,7 @@
// DefaultOutputUnit callback
OSStatus AUAudioOutputStream::InputProc(void* user_data,
AudioUnitRenderActionFlags*,
- const AudioTimeStamp*,
+ const AudioTimeStamp* output_time_stamp,
UInt32,
UInt32 number_of_frames,
AudioBufferList* io_data) {
@@ -218,7 +241,7 @@
if (!audio_output)
return -1;
- return audio_output->Render(number_of_frames, io_data);
+ return audio_output->Render(number_of_frames, io_data, output_time_stamp);
}
double AUAudioOutputStream::HardwareSampleRate() {
@@ -261,3 +284,74 @@
return nominal_sample_rate;
}
+
+void AUAudioOutputStream::StoreHardwareLatency() {
+ // Get audio unit latency.
+ Float64 audio_unit_latency_sec = 0.0;
+ UInt32 size = sizeof(audio_unit_latency_sec);
+ OSStatus result = AudioUnitGetProperty(output_unit_,
+ kAudioUnitProperty_Latency,
+ kAudioUnitScope_Global,
+ 0,
+ &audio_unit_latency_sec,
+ &size);
+ if (result)
+ DLOG(WARNING) << "StoreHardwareLatency: Could not get audio unit latency.";
+
+ // Get audio device latency.
+ UInt32 device_latency_frames = 0;
+ size = sizeof(device_latency_frames);
+ result = AudioDeviceGetProperty(output_device_id_,
+ 0,
+ false,
+ kAudioDevicePropertyLatency,
+ &size,
+ &device_latency_frames);
+ if (result)
+ DLOG(WARNING) << "StoreHardwareLatency: Could not get device latency.";
+
+ // Get the stream latency.
+ UInt32 stream_latency_frames = 0;
+ result = AudioDeviceGetPropertyInfo(output_device_id_,
+ 0,
+ false,
+ kAudioDevicePropertyStreams,
+ &size,
+ NULL);
+ if (!result) {
+ scoped_ptr_malloc<AudioStreamID>
+ streams(reinterpret_cast<AudioStreamID*>(malloc(size)));
+ AudioStreamID* stream_ids = streams.get();
+ result = AudioDeviceGetProperty(output_device_id_,
+ 0,
+ false,
+ kAudioDevicePropertyStreams,
+ &size,
+ stream_ids);
+ if (!result)
+ result = AudioStreamGetProperty(stream_ids[0],
+ 0,
+ kAudioStreamPropertyLatency,
+ &size,
+ &stream_latency_frames);
+ }
+ // Log the warning if it fails to get stream latency.
+ if (result)
+ DLOG(WARNING) << "StoreHardwareLatency: Could not get stream latency.";
+
+ // Store the hardware latency value in freams.
+ hardware_latency_frames_ = static_cast<double>(audio_unit_latency_sec *
+ format_.mSampleRate + device_latency_frames + stream_latency_frames);
+}
+
+void AUAudioOutputStream::UpdatePlayoutLatency(
+ const AudioTimeStamp* output_time_stamp) {
+ // Get the delay between now and when the data is going to reach the hardware.
+ UInt64 output_time_ns = AudioConvertHostTimeToNanos(
+ output_time_stamp->mHostTime);
+ UInt64 now_ns = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
+ double delay_frames = static_cast<double>
+ (1e-9 * (output_time_ns - now_ns) * format_.mSampleRate);
+
+ playout_latency_frames_ = delay_frames + hardware_latency_frames_;
+}

Powered by Google App Engine
This is Rietveld 408576698