Bug 907817 - Actually set the latency when using the audiounit cubeb backend. r=kinetik
authorPaul Adenot <paul@paul.cx>
Thu, 17 Oct 2013 15:44:51 +0200
changeset 165891 6c1e6cff2e434366e8b9db02f3826363aae2c81d
parent 165890 616980966644f34c3e96a2b44517ca8f553364ff
child 165892 af8f1f9b11bee23cd188b423d588331683b1d2e3
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs907817
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 907817 - Actually set the latency when using the audiounit cubeb backend. r=kinetik
media/libcubeb/src/cubeb_audiounit.c
--- a/media/libcubeb/src/cubeb_audiounit.c
+++ b/media/libcubeb/src/cubeb_audiounit.c
@@ -203,16 +203,29 @@ audiounit_stream_init(cubeb * context, c
 #else
   AudioComponentDescription desc;
   AudioComponent comp;
 #endif
   cubeb_stream * stm;
   AURenderCallbackStruct input;
   unsigned int buffer_size;
   OSStatus r;
+  UInt32 size;
+  AudioObjectPropertyAddress output_device_address = {
+    kAudioHardwarePropertyDefaultOutputDevice,
+    kAudioObjectPropertyScopeGlobal,
+    kAudioObjectPropertyElementMaster
+  };
+  AudioObjectPropertyAddress output_device_buffer_size_range = {
+    kAudioDevicePropertyBufferFrameSizeRange,
+    kAudioObjectPropertyScopeOutput,
+    kAudioObjectPropertyElementMaster
+  };
+  AudioDeviceID output_device_id;
+
 
   assert(context);
   *stream = NULL;
 
   memset(&ss, 0, sizeof(ss));
   ss.mFormatFlags = 0;
 
   switch (stream_params.format) {
@@ -291,29 +304,69 @@ audiounit_stream_init(cubeb * context, c
   input.inputProcRefCon = stm;
   r = AudioUnitSetProperty(stm->unit, kAudioUnitProperty_SetRenderCallback,
                            kAudioUnitScope_Global, 0, &input, sizeof(input));
   if (r != 0) {
     audiounit_stream_destroy(stm);
     return CUBEB_ERROR;
   }
 
+  buffer_size = latency / 1000.0 * ss.mSampleRate;
+
+  size = sizeof(output_device_id);
+  /* Get the default output device id. */
+  r = AudioObjectGetPropertyData(kAudioObjectSystemObject,
+                                 &output_device_address,
+                                 0,
+                                 0,
+                                 &size,
+                                 &output_device_id);
+
+  if (r != 0) {
+    audiounit_stream_destroy(stm);
+    return CUBEB_ERROR;
+  }
+
+  /* Get the buffer size range this device supports and clamp the supplied
+   * latency to an acceptable value */
+  AudioValueRange buffer_size_range;
+  size = sizeof(buffer_size_range);
+
+  r = AudioObjectGetPropertyData(output_device_id,
+                                 &output_device_buffer_size_range,
+                                 0,
+                                 NULL,
+                                 &size,
+                                 &buffer_size_range);
+  if (r != 0) {
+    audiounit_stream_destroy(stm);
+    return CUBEB_ERROR;
+  }
+  if (buffer_size < (unsigned int) buffer_size_range.mMinimum) {
+    buffer_size = (unsigned int) buffer_size_range.mMinimum;
+  } else if (buffer_size > (unsigned int) buffer_size_range.mMaximum) {
+    buffer_size = (unsigned int) buffer_size_range.mMaximum;
+  }
+
+  /* Set the maximum number of frame that the render callback will ask for,
+   * effectively setting the latency of the stream. This is process-wide. */
+  r = AudioUnitSetProperty(stm->unit, kAudioDevicePropertyBufferFrameSize,
+                           kAudioUnitScope_Output, 0, &buffer_size, sizeof(buffer_size));
+  if (r != 0) {
+    audiounit_stream_destroy(stm);
+    return CUBEB_ERROR;
+  }
+
   r = AudioUnitSetProperty(stm->unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
                            0, &ss, sizeof(ss));
   if (r != 0) {
     audiounit_stream_destroy(stm);
     return CUBEB_ERROR;
   }
 
-  buffer_size = ss.mSampleRate / 1000.0 * latency * ss.mBytesPerFrame / NBUFS;
-  if (buffer_size % ss.mBytesPerFrame != 0) {
-    buffer_size += ss.mBytesPerFrame - (buffer_size % ss.mBytesPerFrame);
-  }
-  assert(buffer_size % ss.mBytesPerFrame == 0);
-
   r = AudioUnitInitialize(stm->unit);
   if (r != 0) {
     audiounit_stream_destroy(stm);
     return CUBEB_ERROR;
   }
 
   *stream = stm;
 
@@ -430,17 +483,17 @@ audiounit_stream_get_latency(cubeb_strea
                                    0,
                                    NULL,
                                    &size,
                                    &device_latency_frames);
     if (r != noErr) {
       pthread_mutex_unlock(&stm->mutex);
       return CUBEB_ERROR;
     }
-    
+
     size = sizeof(device_safety_offset);
     r = AudioObjectGetPropertyData(output_device_id,
                                    &safety_offset_address,
                                    0,
                                    NULL,
                                    &size,
                                    &device_safety_offset);
     if (r != noErr) {