diff --git a/media/libcubeb/src/cubeb_audiounit.cpp b/media/libcubeb/src/cubeb_audiounit.cpp
--- a/media/libcubeb/src/cubeb_audiounit.cpp
+++ b/media/libcubeb/src/cubeb_audiounit.cpp
@@ -594,20 +594,20 @@ audiounit_get_input_device_id(AudioDevic
 
   return CUBEB_OK;
 }
 
 static int audiounit_stream_get_volume(cubeb_stream * stm, float * volume);
 static int audiounit_stream_set_volume(cubeb_stream * stm, float volume);
 
 static int
-audiounit_reinit_stream(cubeb_stream * stm, bool is_started)
+audiounit_reinit_stream(cubeb_stream * stm)
 {
   auto_lock context_lock(stm->context->mutex);
-  if (is_started) {
+  if (!stm->shutdown) {
     audiounit_stream_stop_internal(stm);
   }
 
   {
     auto_lock lock(stm->mutex);
     float volume = 0.0;
     int vol_rv = audiounit_stream_get_volume(stm, &volume);
 
@@ -622,32 +622,30 @@ audiounit_reinit_stream(cubeb_stream * s
       audiounit_stream_set_volume(stm, volume);
     }
 
     // Reset input frames to force new stream pre-buffer
     // silence if needed, check `is_extra_input_needed()`
     stm->frames_read = 0;
 
     // If the stream was running, start it again.
-    if (is_started) {
+    if (!stm->shutdown) {
       audiounit_stream_start_internal(stm);
     }
   }
   return CUBEB_OK;
 }
 
 static OSStatus
 audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_count,
                                      const AudioObjectPropertyAddress * addresses,
                                      void * user)
 {
   cubeb_stream * stm = (cubeb_stream*) user;
   stm->switching_device = true;
-  // Note if the stream was running or not
-  bool was_running = !stm->shutdown;
 
   LOG("(%p) Audio device changed, %d events.", stm, address_count);
   for (UInt32 i = 0; i < address_count; i++) {
     switch(addresses[i].mSelector) {
       case kAudioHardwarePropertyDefaultOutputDevice: {
           LOG("Event[%d] - mSelector == kAudioHardwarePropertyDefaultOutputDevice", i);
           // Allow restart to choose the new default
           stm->output_device = nullptr;
@@ -666,19 +664,20 @@ audiounit_property_listener_callback(Aud
           if (stm->is_default_input) {
             LOG("It's the default input device, ignore the event");
             return noErr;
           }
           // Allow restart to choose the new default. Event register only for input.
           stm->input_device = nullptr;
         }
         break;
-      case kAudioDevicePropertyDataSource:
-        LOG("Event[%d] - mSelector == kAudioHardwarePropertyDataSource", i);
-        break;
+      case kAudioDevicePropertyDataSource: {
+          LOG("Event[%d] - mSelector == kAudioHardwarePropertyDataSource", i);
+          return noErr;
+        }
     }
   }
 
   for (UInt32 i = 0; i < address_count; i++) {
     switch(addresses[i].mSelector) {
     case kAudioHardwarePropertyDefaultOutputDevice:
     case kAudioHardwarePropertyDefaultInputDevice:
     case kAudioDevicePropertyDeviceIsAlive:
@@ -691,17 +690,17 @@ audiounit_property_listener_callback(Aud
         break;
       }
     }
   }
 
   // Use a new thread, through the queue, to avoid deadlock when calling
   // Get/SetProperties method from inside notify callback
   dispatch_async(stm->context->serial_queue, ^() {
-    if (audiounit_reinit_stream(stm, was_running) != CUBEB_OK) {
+    if (audiounit_reinit_stream(stm) != CUBEB_OK) {
       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
       LOG("(%p) Could not reopen the stream after switching.", stm);
     }
     stm->switching_device = false;
   });
 
   return noErr;
 }
@@ -752,27 +751,16 @@ audiounit_install_device_changed_callbac
     }
 
     r = audiounit_add_listener(stm, output_dev_id, kAudioDevicePropertyDataSource,
         kAudioDevicePropertyScopeOutput, &audiounit_property_listener_callback);
     if (r != noErr) {
       PRINT_ERROR_CODE("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDataSource", r);
       return CUBEB_ERROR;
     }
-
-    /* This event will notify us when the default audio device changes,
-     * for example when the user plugs in a USB headset and the system chooses it
-     * automatically as the default, or when another device is chosen in the
-     * dropdown list. */
-    r = audiounit_add_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice,
-        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
-    if (r != noErr) {
-      PRINT_ERROR_CODE("AudioObjectAddPropertyListener/output/kAudioHardwarePropertyDefaultOutputDevice", r);
-      return CUBEB_ERROR;
-    }
   }
 
   if (stm->input_unit) {
     /* This event will notify us when the data source on the input device changes. */
     AudioDeviceID input_dev_id;
     r = audiounit_get_input_device_id(&input_dev_id);
     if (r != noErr) {
       return CUBEB_ERROR;
@@ -780,78 +768,112 @@ audiounit_install_device_changed_callbac
 
     r = audiounit_add_listener(stm, input_dev_id, kAudioDevicePropertyDataSource,
         kAudioDevicePropertyScopeInput, &audiounit_property_listener_callback);
     if (r != noErr) {
       PRINT_ERROR_CODE("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDataSource", r);
       return CUBEB_ERROR;
     }
 
-    /* This event will notify us when the default input device changes. */
-    r = audiounit_add_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultInputDevice,
-        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
-    if (r != noErr) {
-      PRINT_ERROR_CODE("AudioObjectAddPropertyListener/input/kAudioHardwarePropertyDefaultInputDevice", r);
-      return CUBEB_ERROR;
-    }
-
     /* Event to notify when the input is going away. */
     AudioDeviceID dev = stm->input_device ? reinterpret_cast<intptr_t>(stm->input_device) :
                                             audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
     r = audiounit_add_listener(stm, dev, kAudioDevicePropertyDeviceIsAlive,
         kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
     if (r != noErr) {
       PRINT_ERROR_CODE("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDeviceIsAlive", r);
       return CUBEB_ERROR;
     }
   }
 
   return CUBEB_OK;
 }
 
 static int
+audiounit_install_system_changed_callback(cubeb_stream * stm)
+{
+  OSStatus r;
+
+  if (stm->output_unit) {
+    /* This event will notify us when the default audio device changes,
+     * for example when the user plugs in a USB headset and the system chooses it
+     * automatically as the default, or when another device is chosen in the
+     * dropdown list. */
+    r = audiounit_add_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice,
+                               kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      LOG("AudioObjectAddPropertyListener/output/kAudioHardwarePropertyDefaultOutputDevice rv=%d", r);
+      return CUBEB_ERROR;
+    }
+  }
+
+  if (stm->input_unit) {
+    /* This event will notify us when the default input device changes. */
+    r = audiounit_add_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultInputDevice,
+                               kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      LOG("AudioObjectAddPropertyListener/input/kAudioHardwarePropertyDefaultInputDevice rv=%d", r);
+      return CUBEB_ERROR;
+    }
+  }
+
+  return CUBEB_OK;
+}
+
+static int
 audiounit_uninstall_device_changed_callback(cubeb_stream * stm)
 {
   OSStatus r;
 
   if (stm->output_unit) {
     AudioDeviceID output_dev_id;
     r = audiounit_get_output_device_id(&output_dev_id);
     if (r != noErr) {
       return CUBEB_ERROR;
     }
 
     r = audiounit_remove_listener(stm, output_dev_id, kAudioDevicePropertyDataSource,
         kAudioDevicePropertyScopeOutput, &audiounit_property_listener_callback);
     if (r != noErr) {
       return CUBEB_ERROR;
     }
-
-    r = audiounit_remove_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice,
-        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
-    if (r != noErr) {
-      return CUBEB_ERROR;
-    }
   }
 
   if (stm->input_unit) {
     AudioDeviceID input_dev_id;
     r = audiounit_get_input_device_id(&input_dev_id);
     if (r != noErr) {
       return CUBEB_ERROR;
     }
 
     r = audiounit_remove_listener(stm, input_dev_id, kAudioDevicePropertyDataSource,
         kAudioDevicePropertyScopeInput, &audiounit_property_listener_callback);
     if (r != noErr) {
       return CUBEB_ERROR;
     }
-
+  }
+  return CUBEB_OK;
+}
+
+static int
+audiounit_uninstall_system_changed_callback(cubeb_stream * stm)
+{
+  OSStatus r;
+
+  if (stm->output_unit) {
+    r = audiounit_remove_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice,
+                                  kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
+  }
+
+  if (stm->input_unit) {
     r = audiounit_remove_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultInputDevice,
-        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+                                  kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
     if (r != noErr) {
       return CUBEB_ERROR;
     }
   }
   return CUBEB_OK;
 }
 
 /* Get the acceptable buffer size (in frames) that this device can work with. */
@@ -1764,16 +1786,22 @@ audiounit_setup_stream(cubeb_stream * st
 
   if (stm->input_unit && stm->output_unit) {
     // According to the I/O hardware rate it is expected a specific pattern of callbacks
     // for example is input is 44100 and output is 48000 we expected no more than 2
     // out callback in a row.
     stm->expected_output_callbacks_in_a_row = ceilf(stm->output_hw_rate / stm->input_hw_rate);
   }
 
+  r = audiounit_install_device_changed_callback(stm);
+  if (r != CUBEB_OK) {
+    LOG("(%p) Could not install the device change callback.", stm);
+    return r;
+  }
+
   return CUBEB_OK;
 }
 
 static int
 audiounit_stream_init(cubeb * context,
                       cubeb_stream ** stream,
                       char const * /* stream_name */,
                       cubeb_devid input_device,
@@ -1838,31 +1866,37 @@ audiounit_stream_init(cubeb * context,
   }
 
   if (r != CUBEB_OK) {
     LOG("(%p) Could not setup the audiounit stream.", stm);
     audiounit_stream_destroy(stm);
     return r;
   }
 
-  r = audiounit_install_device_changed_callback(stm);
+  r = audiounit_install_system_changed_callback(stm);
   if (r != CUBEB_OK) {
     LOG("(%p) Could not install the device change callback.", stm);
     return r;
   }
 
   *stream = stm;
   LOG("Cubeb stream (%p) init successful.", stm);
   return CUBEB_OK;
 }
 
 static void
 audiounit_close_stream(cubeb_stream *stm)
 {
   stm->mutex.assert_current_thread_owns();
+
+  int r = audiounit_uninstall_device_changed_callback(stm);
+  if (r != CUBEB_OK) {
+    LOG("(%p) Could not uninstall the device changed callback", stm);
+  }
+
   if (stm->input_unit) {
     AudioUnitUninitialize(stm->input_unit);
     AudioComponentInstanceDispose(stm->input_unit);
   }
 
   audiounit_destroy_input_linear_buffer(stm);
 
   if (stm->output_unit) {
@@ -1873,31 +1907,29 @@ audiounit_close_stream(cubeb_stream *stm
   cubeb_resampler_destroy(stm->resampler);
 }
 
 static void
 audiounit_stream_destroy(cubeb_stream * stm)
 {
   stm->shutdown = true;
 
+  int r = audiounit_uninstall_system_changed_callback(stm);
+  if (r != CUBEB_OK) {
+    LOG("(%p) Could not uninstall the device changed callback", stm);
+  }
+
   auto_lock context_lock(stm->context->mutex);
   audiounit_stream_stop_internal(stm);
 
   {
     auto_lock lock(stm->mutex);
     audiounit_close_stream(stm);
   }
 
-#if !TARGET_OS_IPHONE
-  int r = audiounit_uninstall_device_changed_callback(stm);
-  if (r != CUBEB_OK) {
-    LOG("(%p) Could not uninstall the device changed callback", stm);
-  }
-#endif
-
   assert(stm->context->active_streams >= 1);
   stm->context->active_streams -= 1;
 
   LOG("Cubeb stream (%p) destroyed successful.", stm);
 
   stm->~cubeb_stream();
   free(stm);
 }
@@ -1914,20 +1946,20 @@ audiounit_stream_start_internal(cubeb_st
     r = AudioOutputUnitStart(stm->output_unit);
     assert(r == 0);
   }
 }
 
 static int
 audiounit_stream_start(cubeb_stream * stm)
 {
+  auto_lock context_lock(stm->context->mutex);
   stm->shutdown = false;
   stm->draining = false;
 
-  auto_lock context_lock(stm->context->mutex);
   audiounit_stream_start_internal(stm);
 
   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
 
   LOG("Cubeb stream (%p) started successfully.", stm);
   return CUBEB_OK;
 }
 
@@ -1943,19 +1975,19 @@ audiounit_stream_stop_internal(cubeb_str
     r = AudioOutputUnitStop(stm->output_unit);
     assert(r == 0);
   }
 }
 
 static int
 audiounit_stream_stop(cubeb_stream * stm)
 {
+  auto_lock context_lock(stm->context->mutex);
   stm->shutdown = true;
 
-  auto_lock context_lock(stm->context->mutex);
   audiounit_stream_stop_internal(stm);
 
   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
 
   LOG("Cubeb stream (%p) stopped successfully.", stm);
   return CUBEB_OK;
 }