Bug 1624485 - Update cubeb-coreaudio to 20daa86. r=padenot
authorChun-Min Chang <chun.m.chang@gmail.com>
Thu, 26 Mar 2020 18:45:47 +0000
changeset 520632 03c0aa19b1b703e48b466734b60b83e26d4dd935
parent 520631 827124686e243c6e7d51a309a84b6eb7974747f7
child 520633 9b0691360c54670250d56409e5e767a2fcf0c16e
push id37254
push usernerli@mozilla.com
push dateFri, 27 Mar 2020 04:48:07 +0000
treeherdermozilla-central@2d758b42bd73 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1624485
milestone76.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 1624485 - Update cubeb-coreaudio to 20daa86. r=padenot Pick commits - 20daa86: Revise git hooks (#68) - 81d0024: Revise `destroy_cubeb_device_info` (#67) - 1cc8a31: Add a hook to check that commits are formatted and linted correctly (#66) - aa80b3f: Try using the model id as group id. (#64) - ab31978: Bail if `cargo clippy` or `cargo fmt` fails (#65) - 3860bb3: Fix comments in #57 (#63) - ef5f58b: Run `cargo fmt` and make scripts executable (#62) - a4c83db: Fix two bugs and add logs (#57) Differential Revision: https://phabricator.services.mozilla.com/D68402
.cargo/config.in
Cargo.lock
third_party/rust/cubeb-coreaudio/.cargo-checksum.json
third_party/rust/cubeb-coreaudio/.githooks/pre-push
third_party/rust/cubeb-coreaudio/.travis.yml
third_party/rust/cubeb-coreaudio/README.md
third_party/rust/cubeb-coreaudio/install_git_hook.sh
third_party/rust/cubeb-coreaudio/install_rustfmt_clippy.sh
third_party/rust/cubeb-coreaudio/run_device_tests.sh
third_party/rust/cubeb-coreaudio/run_sanitizers.sh
third_party/rust/cubeb-coreaudio/run_tests.sh
third_party/rust/cubeb-coreaudio/src/backend/device_property.rs
third_party/rust/cubeb-coreaudio/src/backend/mod.rs
third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs
toolkit/library/rust/shared/Cargo.toml
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -70,17 +70,17 @@ rev = "d510da5999a744c563b0acd18056069d1
 [source."https://github.com/PLSysSec/lucet_sandbox_compiler"]
 git = "https://github.com/PLSysSec/lucet_sandbox_compiler"
 replace-with = "vendored-sources"
 rev = "5e870faf6f95d79d11efc813e56370ad124bbed5"
 
 [source."https://github.com/ChunMinChang/cubeb-coreaudio-rs"]
 git = "https://github.com/ChunMinChang/cubeb-coreaudio-rs"
 replace-with = "vendored-sources"
-rev = "799518a033a0c780cfdb82a4eaabfd9681cb7f3b"
+rev = "20daa86ae2829351d08c829f1ebad2755c583abf"
 
 [source.crates-io]
 replace-with = "vendored-sources"
 
 # Take advantage of the fact that cargo will treat lines starting with #
 # as comments to add preprocessing directives. This file can thus by copied
 # as-is to $topsrcdir/.cargo/config with no preprocessing to be used there
 # (for e.g. independent tasks building rust code), or be preprocessed by
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -684,17 +684,17 @@ source = "registry+https://github.com/ru
 checksum = "e81f1c165c33ffab90a03077ac3b03462b34d5947145dfa48102e063d581502c"
 dependencies = [
  "bindgen",
 ]
 
 [[package]]
 name = "coreaudio-sys-utils"
 version = "0.1.0"
-source = "git+https://github.com/ChunMinChang/cubeb-coreaudio-rs?rev=799518a033a0c780cfdb82a4eaabfd9681cb7f3b#799518a033a0c780cfdb82a4eaabfd9681cb7f3b"
+source = "git+https://github.com/ChunMinChang/cubeb-coreaudio-rs?rev=20daa86ae2829351d08c829f1ebad2755c583abf#20daa86ae2829351d08c829f1ebad2755c583abf"
 dependencies = [
  "core-foundation-sys",
  "coreaudio-sys",
 ]
 
 [[package]]
 name = "cose"
 version = "0.1.4"
@@ -921,17 +921,17 @@ checksum = "bfd9b2ea1cb6afed9419b0d18fc4
 dependencies = [
  "bitflags",
  "cubeb-sys",
 ]
 
 [[package]]
 name = "cubeb-coreaudio"
 version = "0.1.0"
-source = "git+https://github.com/ChunMinChang/cubeb-coreaudio-rs?rev=799518a033a0c780cfdb82a4eaabfd9681cb7f3b#799518a033a0c780cfdb82a4eaabfd9681cb7f3b"
+source = "git+https://github.com/ChunMinChang/cubeb-coreaudio-rs?rev=20daa86ae2829351d08c829f1ebad2755c583abf#20daa86ae2829351d08c829f1ebad2755c583abf"
 dependencies = [
  "atomic",
  "audio-mixer",
  "bitflags",
  "coreaudio-sys-utils",
  "cubeb-backend",
  "float-cmp",
  "lazy_static",
--- a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json
+++ b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".travis.yml":"878d9519da0844cd3de2999f81fce966452f0fb65150605c25a1abf3523360ab","Cargo.toml":"bcb3ec3785c3cbe799bb41c07176afdd0028328be79932a4e44bc97a364e8c69","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0d5a4c39e737aeeccfd5a54914e8927631ad86e3da8c24f62594f2f89a3302bf","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"e66d32da5439818eee30fc5e7ed9ab9990723ffafe684870efe82dac11be07ef","run_sanitizers.sh":"54970203e86eed00245de3d9b53584d5d8868be983f90b27c603b310ba5554e5","run_tests.sh":"257ac9b30e0ff3775d713668a9704f15ad4ed2334aca7d8c544d079cde197e8a","src/backend/aggregate_device.rs":"ae21129aa6b3c7bd3376751b6a94d1ebe6c9f7afcd1db3107fb4d703d04da6b3","src/backend/auto_array.rs":"5f35545baba2b005e13a2225bd1cbdd94ffc2097554d61479929bfc5442a6dd6","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/device_property.rs":"324a7c9672daa49ee2221a56d140e1c8298719dab66f204b19d10f3632f96602","src/backend/mixer.rs":"0c237bd5ca63b028c4b22ddc5bc026d7e21c0fa9b4e337f00b6131ed0a0806a5","src/backend/mod.rs":"e6ed4937f9ca52626a0ab6728631a88c9ae1369fd1ff61a377dfa64c3d406fb3","src/backend/resampler.rs":"fd1281d28a4db1659d2f75e43b8457651745e1b6eb5a53a77f04d752135f6dc7","src/backend/tests/aggregate_device.rs":"107f5c637844cd5ae43d2b42cec4ef3369bb702751586078c0a9d50f039161cd","src/backend/tests/api.rs":"58cbf67e3f4588f5e644ebcdc24942fcd6299c26f42a7e27fb4b6b9d8e5245f8","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"8261f561f69dabd374ac47d69aa484812b65070a9e9581dfb2605e8404eaad6d","src/backend/tests/device_property.rs":"b1a9ae79aa5b9a3f180040d0ef0954b134680d586882d2062c5e017b555bff57","src/backend/tests/interfaces.rs":"14943e84a79976a7ef52882edeb9330350705d5190db6647f98b4ffa851a8396","src/backend/tests/manual.rs":"dc707836dab31f83d4b325afbc4dc4c8104ac8036e87f59ade3309ee83fe2d3f","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"f9e1883660d6146b6e5075806561f5f689810e25c5e7764dfd28c9b939821a49","src/backend/tests/tone.rs":"16150438317ce501986734167b5fb97bfec567228acbcd8f3b4c4484c22f29e0","src/backend/tests/utils.rs":"1bb99ef71d3c18545bca49767e7b6bfffbe11896246994f41be7ed372772fd48","src/backend/utils.rs":"5ce1b753af0ffb654b6b2038d649aea88eebd27390a607a6d5988a9e40a4a717","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"29545b4d9c516396f82bd392797e2713d4602036eaba0f151b384af764f8515f"},"package":null}
\ No newline at end of file
+{"files":{".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"da1b815382649512784ff98e648cc06a7727b7e3fce1a04ba448af3db9e42c23",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"bcb3ec3785c3cbe799bb41c07176afdd0028328be79932a4e44bc97a364e8c69","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"b791d43cbea873bc199e3b4c26e776b0068e6dd1f8307140cc1f5b63611dedd9","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"e66d32da5439818eee30fc5e7ed9ab9990723ffafe684870efe82dac11be07ef","run_sanitizers.sh":"ccb6ec9e4f25118220fb4c661c2bea711307e280bba201ee8ed2e4ac8554cde8","run_tests.sh":"da1fae5a4508e5a8b2d9797200958af54d79262fc688b87ab112d91c6d495c7d","src/backend/aggregate_device.rs":"ae21129aa6b3c7bd3376751b6a94d1ebe6c9f7afcd1db3107fb4d703d04da6b3","src/backend/auto_array.rs":"5f35545baba2b005e13a2225bd1cbdd94ffc2097554d61479929bfc5442a6dd6","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/device_property.rs":"b37ddc4ad853b3e9f2dc48272bb3b898e38ee0e9af006871260e62edcf1b4be6","src/backend/mixer.rs":"0c237bd5ca63b028c4b22ddc5bc026d7e21c0fa9b4e337f00b6131ed0a0806a5","src/backend/mod.rs":"275766270c377724ec62891a3ba660a02709a6d8805b01af8a782a5d5ffa170b","src/backend/resampler.rs":"fd1281d28a4db1659d2f75e43b8457651745e1b6eb5a53a77f04d752135f6dc7","src/backend/tests/aggregate_device.rs":"107f5c637844cd5ae43d2b42cec4ef3369bb702751586078c0a9d50f039161cd","src/backend/tests/api.rs":"746d086836d95f0729e7a40b93a1a29f30954787b1de1192477c478d73e2d852","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"8261f561f69dabd374ac47d69aa484812b65070a9e9581dfb2605e8404eaad6d","src/backend/tests/device_property.rs":"b1a9ae79aa5b9a3f180040d0ef0954b134680d586882d2062c5e017b555bff57","src/backend/tests/interfaces.rs":"14943e84a79976a7ef52882edeb9330350705d5190db6647f98b4ffa851a8396","src/backend/tests/manual.rs":"dc707836dab31f83d4b325afbc4dc4c8104ac8036e87f59ade3309ee83fe2d3f","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"f9e1883660d6146b6e5075806561f5f689810e25c5e7764dfd28c9b939821a49","src/backend/tests/tone.rs":"16150438317ce501986734167b5fb97bfec567228acbcd8f3b4c4484c22f29e0","src/backend/tests/utils.rs":"1bb99ef71d3c18545bca49767e7b6bfffbe11896246994f41be7ed372772fd48","src/backend/utils.rs":"5ce1b753af0ffb654b6b2038d649aea88eebd27390a607a6d5988a9e40a4a717","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"29545b4d9c516396f82bd392797e2713d4602036eaba0f151b384af764f8515f"},"package":null}
\ No newline at end of file
new file mode 100755
--- /dev/null
+++ b/third_party/rust/cubeb-coreaudio/.githooks/pre-push
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+# An example hook script to verify what is about to be pushed.  Called by "git
+# push" after it has checked the remote status, but before anything has been
+# pushed.  If this script exits with a non-zero status nothing will be pushed.
+#
+# This hook is called with the following parameters:
+#
+# $1 -- Name of the remote to which the push is being done
+# $2 -- URL to which the push is being done
+#
+# If pushing without using a named remote those arguments will be equal.
+#
+# Information about the commits which are being pushed is supplied as lines to
+# the standard input in the form:
+#
+#   <local ref> <local sha1> <remote ref> <remote sha1>
+
+remote="$1"
+url="$2"
+
+cargo fmt -- --check || (echo "Please run 'cargo fmt'"; false);
+
+cargo clippy -- -D warnings || (echo "Please run 'cargo clippy'"; false);
+
--- a/third_party/rust/cubeb-coreaudio/.travis.yml
+++ b/third_party/rust/cubeb-coreaudio/.travis.yml
@@ -2,20 +2,21 @@ language: rust
 rust:
   - stable
   - beta
   - nightly
 os:
   - osx
 env:
   - RUST_BACKTRACE=1
+install:
+  - sh install_rustfmt_clippy.sh
 before_script:
   - rustc --version
   - cargo --version
-  - sh install_rustfmt_clippy.sh
 script:
   - cargo build --verbose
   - sh run_tests.sh
   - sh run_sanitizers.sh
 jobs:
   allow_failures:
     - rust: nightly
   fast_finish: true
--- a/third_party/rust/cubeb-coreaudio/README.md
+++ b/third_party/rust/cubeb-coreaudio/README.md
@@ -30,16 +30,22 @@ They may operate the same device at the 
 or indirectly fire some system events that are listened by some tests.
 
 The tests that may affect others are marked `#[ignore]`.
 They will be run by `cargo test ... -- --ignored ...`
 after finishing normal tests.
 Most of the tests are executed in `run_tests.sh`.
 Only those tests commented with *FIXIT* are left.
 
+### Git Hooks
+
+You can install _git hooks_ by running `install_git_hook.sh`.
+Then _pre-push_ script will be run and do the `cargo fmt` and `cargo clippy` check
+before the commits are pushed to remote.
+
 ### Run Sanitizers
 
 Run _AddressSanitizer (ASan), LeakSanitizer (LSan), MemorySanitizer (MSan), ThreadSanitizer (TSan)_
 by `sh run_sanitizers.sh`.
 
 The above command will run all the test suits in *run_tests.sh* by all the available _sanitizers_.
 However, it takes a long time for finshing the tests.
 
new file mode 100755
--- /dev/null
+++ b/third_party/rust/cubeb-coreaudio/install_git_hook.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+git config core.hooksPath .githooks
old mode 100644
new mode 100755
old mode 100644
new mode 100755
old mode 100644
new mode 100755
--- a/third_party/rust/cubeb-coreaudio/run_sanitizers.sh
+++ b/third_party/rust/cubeb-coreaudio/run_sanitizers.sh
@@ -1,17 +1,17 @@
 # The option `Z` is only accepted on the nightly compiler
 # so changing to nightly toolchain by `rustup default nightly` is required.
 
 # See: https://github.com/rust-lang/rust/issues/39699 for more sanitizer support.
 
 toolchain=$(rustup default)
 echo "\nUse Rust toolchain: $toolchain"
 
-if [[ $toolchain != nightly-* ]]; then
+if [[ $toolchain != nightly* ]]; then
    echo "The sanitizer is only available on Rust Nightly only. Skip."
    exit
 fi
 
 sanitizers=("address" "leak" "memory" "thread")
 for san in "${sanitizers[@]}"
 do
     San="$(tr '[:lower:]' '[:upper:]' <<< ${san:0:1})${san:1}"
old mode 100644
new mode 100755
--- a/third_party/rust/cubeb-coreaudio/run_tests.sh
+++ b/third_party/rust/cubeb-coreaudio/run_tests.sh
@@ -1,43 +1,65 @@
 echo "\n\nTest suite for cubeb-coreaudio\n========================================"
 
 if [[ -z "${RUST_BACKTRACE}" ]]; then
   # Display backtrace for debugging
   export RUST_BACKTRACE=1
 fi
 echo "RUST_BACKTRACE is set to ${RUST_BACKTRACE}\n"
 
+format_check() {
+  cargo fmt --all -- --check
+  local result=$?
+  if [[ $result -ne 0 ]]; then
+    echo "Please format the code with 'cargo fmt' (version $(cargo fmt -- --version))"
+  fi
+  return $result
+}
+
+lints_check() {
+  if [[ -n "$1" ]]; then
+    cargo clippy -p $1 -- -D warnings
+  else
+    cargo clippy -- -D warnings
+  fi
+  local result=$?
+  if [[ $result -ne 0 ]]; then
+    echo "Please fix errors with 'cargo clippy' (version $(cargo clippy -- --version))"
+  fi
+  return $result
+}
+
 # Run tests in the sub crate
 # Run the tests by `cargo * -p <SUB_CRATE>` if it's possible. By doing so, the duplicate compiling
 # between this crate and the <SUB_CRATE> can be saved. The compiling for <SUB_CRATE> can be reused
 # when running `cargo *` with this crate.
 # -------------------------------------------------------------------------------------------------
 SUB_CRATE="coreaudio-sys-utils"
 
 # Format check
 # `cargo fmt -p *` is only usable in workspaces, so a workaround is to enter to the sub crate
 # and then exit from it.
 cd $SUB_CRATE
-cargo fmt --all -- --check
+format_check || exit $?
 cd ..
 
 # Lints check
-cargo clippy -p $SUB_CRATE -- -D warnings
+(lints_check $SUB_CRATE) || exit $?
 
 # Regular Tests
 cargo test -p $SUB_CRATE
 
 # Run tests in the main crate
 # -------------------------------------------------------------------------------------------------
 # Format check
-cargo fmt --all -- --check
+format_check || exit $?
 
 # Lints check
-cargo clippy -- -D warnings
+lints_check || exit $?
 
 # Regular Tests
 cargo test --verbose
 cargo test test_configure_output -- --ignored
 cargo test test_aggregate -- --ignored --test-threads=1
 
 # Parallel Tests
 cargo test test_parallel -- --ignored --nocapture --test-threads=1
--- a/third_party/rust/cubeb-coreaudio/src/backend/device_property.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/device_property.rs
@@ -16,16 +16,33 @@ pub fn get_device_uid(
     let err = audio_object_get_property_data(id, &address, &mut size, &mut uid);
     if err == NO_ERR {
         Ok(StringRef::new(uid as _))
     } else {
         Err(err)
     }
 }
 
+pub fn get_device_model_uid(
+    id: AudioDeviceID,
+    devtype: DeviceType,
+) -> std::result::Result<StringRef, OSStatus> {
+    assert_ne!(id, kAudioObjectUnknown);
+
+    let address = get_property_address(Property::ModelUID, devtype);
+    let mut size = mem::size_of::<CFStringRef>();
+    let mut uid: CFStringRef = ptr::null();
+    let err = audio_object_get_property_data(id, &address, &mut size, &mut uid);
+    if err == NO_ERR {
+        Ok(StringRef::new(uid as _))
+    } else {
+        Err(err)
+    }
+}
+
 pub fn get_device_source(
     id: AudioDeviceID,
     devtype: DeviceType,
 ) -> std::result::Result<u32, OSStatus> {
     assert_ne!(id, kAudioObjectUnknown);
 
     let address = get_property_address(Property::DeviceSource, devtype);
     let mut size = mem::size_of::<u32>();
@@ -271,16 +288,17 @@ pub enum Property {
     DeviceSampleRate,
     DeviceSampleRates,
     DeviceSource,
     DeviceSourceName,
     DeviceStreamConfiguration,
     DeviceStreamFormat,
     DeviceStreams,
     DeviceUID,
+    ModelUID,
     HardwareDefaultInputDevice,
     HardwareDefaultOutputDevice,
     HardwareDevices,
     StreamLatency,
 }
 
 impl From<Property> for AudioObjectPropertySelector {
     fn from(p: Property) -> Self {
@@ -293,16 +311,17 @@ impl From<Property> for AudioObjectPrope
             Property::DeviceSampleRate => kAudioDevicePropertyNominalSampleRate,
             Property::DeviceSampleRates => kAudioDevicePropertyAvailableNominalSampleRates,
             Property::DeviceSource => kAudioDevicePropertyDataSource,
             Property::DeviceSourceName => kAudioDevicePropertyDataSourceNameForIDCFString,
             Property::DeviceStreamConfiguration => kAudioDevicePropertyStreamConfiguration,
             Property::DeviceStreamFormat => kAudioDevicePropertyStreamFormat,
             Property::DeviceStreams => kAudioDevicePropertyStreams,
             Property::DeviceUID => kAudioDevicePropertyDeviceUID,
+            Property::ModelUID => kAudioDevicePropertyModelUID,
             Property::HardwareDefaultInputDevice => kAudioHardwarePropertyDefaultInputDevice,
             Property::HardwareDefaultOutputDevice => kAudioHardwarePropertyDefaultOutputDevice,
             Property::HardwareDevices => kAudioHardwarePropertyDevices,
             Property::StreamLatency => kAudioStreamPropertyLatency,
         }
     }
 }
 
--- a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
@@ -37,17 +37,17 @@ use cubeb_backend::{
 };
 use mach::mach_time::{mach_absolute_time, mach_timebase_info};
 use std::cmp;
 use std::ffi::{CStr, CString};
 use std::mem;
 use std::os::raw::c_void;
 use std::ptr;
 use std::slice;
-use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, AtomicU64, Ordering};
+use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicUsize, Ordering};
 use std::sync::{Arc, Condvar, Mutex};
 use std::time::Duration;
 
 const NO_ERR: OSStatus = 0;
 
 const AU_OUT_BUS: AudioUnitElement = 0;
 const AU_IN_BUS: AudioUnitElement = 1;
 
@@ -199,25 +199,28 @@ fn create_device_info(id: AudioDeviceID,
             DeviceType::INPUT => device_flags::DEV_INPUT,
             DeviceType::OUTPUT => device_flags::DEV_OUTPUT,
             _ => panic!("Only accept input or output type"),
         },
     };
 
     let default_device_id = audiounit_get_default_device_id(devtype);
     if default_device_id == kAudioObjectUnknown {
+        cubeb_log!("Could not find default audio device for {:?}", devtype);
         return Err(Error::error());
     }
 
     if id == kAudioObjectUnknown {
         info.id = default_device_id;
+        cubeb_log!("Creating a default device info.");
         info.flags |= device_flags::DEV_SELECTED_DEFAULT;
     }
 
     if info.id == default_device_id {
+        cubeb_log!("Requesting default system device.");
         info.flags |= device_flags::DEV_SYSTEM_DEFAULT;
     }
 
     Ok(info)
 }
 
 fn create_stream_description(stream_params: &StreamParams) -> Result<AudioStreamBasicDescription> {
     assert!(stream_params.rate() > 0);
@@ -322,23 +325,27 @@ fn get_volume(unit: AudioUnit) -> Result
     if r == NO_ERR {
         Ok(volume)
     } else {
         cubeb_log!("AudioUnitGetParameter/kHALOutputParam_Volume rv={}", r);
         Err(Error::error())
     }
 }
 
-fn minimum_resampling_input_frames(input_rate: f64, output_rate: f64, output_frames: i64) -> i64 {
+fn minimum_resampling_input_frames(
+    input_rate: f64,
+    output_rate: f64,
+    output_frames: usize,
+) -> usize {
     assert!(!approx_eq!(f64, input_rate, 0_f64));
     assert!(!approx_eq!(f64, output_rate, 0_f64));
     if approx_eq!(f64, input_rate, output_rate) {
         return output_frames;
     }
-    (input_rate * output_frames as f64 / output_rate).ceil() as i64
+    (input_rate * output_frames as f64 / output_rate).ceil() as usize
 }
 
 fn audiounit_make_silent(io_data: &mut AudioBuffer) {
     assert!(!io_data.mData.is_null());
     let bytes = unsafe {
         let ptr = io_data.mData as *mut u8;
         let len = io_data.mDataByteSize as usize;
         slice::from_raw_parts_mut(ptr, len)
@@ -442,17 +449,17 @@ extern "C" fn audiounit_input_callback(
                 .as_mut()
                 .unwrap()
                 .push(input_buffer_list.mBuffers[0].mData, elements);
             ErrorHandle::Return(status)
         };
 
         // Advance input frame counter.
         stm.frames_read
-            .fetch_add(i64::from(input_frames), atomic::Ordering::SeqCst);
+            .fetch_add(input_frames as usize, atomic::Ordering::SeqCst);
 
         cubeb_logv!(
             "({:p}) input: buffers {}, size {}, channels {}, rendered frames {}, total frames {}.",
             stm.core_stream_data.stm_ptr,
             input_buffer_list.mNumberBuffers,
             input_buffer_list.mBuffers[0].mDataByteSize,
             input_buffer_list.mBuffers[0].mNumberChannels,
             input_frames,
@@ -634,56 +641,78 @@ extern "C" fn audiounit_output_callback(
             Some(mixer) => {
                 // If remixing needs to occur, we can't directly work in our final
                 // destination buffer as data may be overwritten or too small to start with.
                 mixer.update_buffer_size(output_frames as usize);
                 mixer.get_buffer_mut_ptr() as *mut c_void
             }
         };
 
+        let prev_frames_written = stm.frames_written.load(Ordering::SeqCst);
+
         stm.frames_written
-            .fetch_add(i64::from(output_frames), Ordering::SeqCst);
+            .fetch_add(output_frames as usize, Ordering::SeqCst);
 
         // Also get the input buffer if the stream is duplex
         let (input_buffer, mut input_frames) = if !stm.core_stream_data.input_unit.is_null() {
             assert!(stm.core_stream_data.input_linear_buffer.is_some());
             assert_ne!(stm.core_stream_data.input_desc.mChannelsPerFrame, 0);
+            let input_channels = stm.core_stream_data.input_desc.mChannelsPerFrame as usize;
             // If the output callback came first and this is a duplex stream, we need to
             // fill in some additional silence in the resampler.
             // Otherwise, if we had more than expected callbacks in a row, or we're
             // currently switching, we add some silence as well to compensate for the
             // fact that we're lacking some input data.
-            let frames_written = stm.frames_written.load(Ordering::SeqCst);
             let input_frames_needed = minimum_resampling_input_frames(
                 stm.core_stream_data.input_hw_rate,
                 f64::from(stm.core_stream_data.output_stream_params.rate()),
-                frames_written,
+                output_frames as usize,
             );
-            let missing_frames = input_frames_needed - stm.frames_read.load(Ordering::SeqCst);
-            let elements = (missing_frames
-                * i64::from(stm.core_stream_data.input_desc.mChannelsPerFrame))
-                as usize;
-            if missing_frames > 0 {
+            let buffered_input_frames = stm
+                .core_stream_data
+                .input_linear_buffer
+                .as_ref()
+                .unwrap()
+                .elements()
+                / input_channels;
+            // Else if the input has buffered a lot already because the output started late, we
+            // need to trim the input buffer
+            if prev_frames_written == 0 && buffered_input_frames > input_frames_needed as usize {
+                let samples_to_pop =
+                    (buffered_input_frames - input_frames_needed as usize) * input_channels;
                 stm.core_stream_data
                     .input_linear_buffer
                     .as_mut()
                     .unwrap()
-                    .push_zeros(elements);
-                stm.frames_read.store(input_frames_needed, Ordering::SeqCst);
+                    .pop(samples_to_pop);
+                stm.frames_read
+                    .fetch_sub((samples_to_pop / input_channels) as usize, Ordering::SeqCst);
+            }
+
+            if input_frames_needed > buffered_input_frames {
+                let silent_frames_to_push = input_frames_needed - buffered_input_frames;
+                let silent_samples_to_push = silent_frames_to_push * input_channels;
+                stm.core_stream_data
+                    .input_linear_buffer
+                    .as_mut()
+                    .unwrap()
+                    .push_zeros(silent_samples_to_push);
+                stm.frames_read
+                    .fetch_add(input_frames_needed, Ordering::SeqCst);
                 cubeb_log!(
-                    "({:p}) {} pushed {} frames of input silence.",
+                    "({:p}) Missing Frames: {} pushed {} frames of input silence.",
                     stm.core_stream_data.stm_ptr,
                     if stm.frames_read.load(Ordering::SeqCst) == 0 {
-                        "Input hasn't started,"
+                        "input hasn't started,"
                     } else if stm.switching_device.load(Ordering::SeqCst) {
-                        "Device switching,"
+                        "device switching,"
                     } else {
-                        "Drop out,"
+                        "drop out,"
                     },
-                    missing_frames
+                    silent_frames_to_push
                 );
             }
             let input_frames = stm
                 .core_stream_data
                 .input_linear_buffer
                 .as_ref()
                 .unwrap()
                 .elements()
@@ -1472,28 +1501,42 @@ fn create_cubeb_device_info(
         "cubeb_devid can't represent devid"
     );
     dev_info.devid = devid as ffi::cubeb_devid;
 
     match get_device_uid(devid, devtype) {
         Ok(uid) => {
             let c_string = uid.into_cstring();
             dev_info.device_id = c_string.into_raw();
-            dev_info.group_id = dev_info.device_id;
         }
         Err(e) => {
             cubeb_log!(
                 "Cannot get the uid for device {} in {:?} scope. Error: {}",
                 devid,
                 devtype,
                 e
             );
         }
     }
 
+    match get_device_model_uid(devid, devtype) {
+        Ok(uid) => {
+            let c_string = uid.into_cstring();
+            dev_info.group_id = c_string.into_raw();
+        }
+        Err(e) => {
+            cubeb_log!(
+                "Cannot get the model uid for device {} in {:?} scope. Error: {}",
+                devid,
+                devtype,
+                e
+            );
+        }
+    }
+
     let label = match get_device_label(devid, devtype) {
         Ok(label) => label.into_cstring(),
         Err(e) => {
             cubeb_log!(
                 "Cannot get the label for device {} in {:?} scope. Error: {}",
                 devid,
                 devtype,
                 e
@@ -1593,31 +1636,35 @@ fn is_aggregate_device(device_info: &ffi
             device_info.friendly_name,
             private_name.as_ptr(),
             libc::strlen(private_name.as_ptr()),
         ) == 0
     }
 }
 
 fn destroy_cubeb_device_info(device: &mut ffi::cubeb_device_info) {
-    // This should be mapped to the memory allocation in create_cubeb_device_info.
+    // This should be mapped to the memory allocation in `create_cubeb_device_info`.
+    // The `device_id`, `group_id`, `vendor_name` can be null pointer if the queries
+    // failed, while `friendly_name` will be assigned to a default empty "" string.
     // Set the pointers to null in case it points to some released memory.
     unsafe {
         if !device.device_id.is_null() {
-            // group_id is a mirror to device_id, so we could skip it.
-            assert!(!device.group_id.is_null());
-            assert_eq!(device.device_id, device.group_id);
             let _ = CString::from_raw(device.device_id as *mut _);
             device.device_id = ptr::null();
+        }
+
+        if !device.group_id.is_null() {
+            let _ = CString::from_raw(device.group_id as *mut _);
             device.group_id = ptr::null();
         }
-        if !device.friendly_name.is_null() {
-            let _ = CString::from_raw(device.friendly_name as *mut _);
-            device.friendly_name = ptr::null();
-        }
+
+        assert!(!device.friendly_name.is_null());
+        let _ = CString::from_raw(device.friendly_name as *mut _);
+        device.friendly_name = ptr::null();
+
         if !device.vendor_name.is_null() {
             let _ = CString::from_raw(device.vendor_name as *mut _);
             device.vendor_name = ptr::null();
         }
     }
 }
 
 fn audiounit_get_devices() -> Vec<AudioObjectID> {
@@ -3081,19 +3128,19 @@ struct AudioUnitStream<'ctx> {
     data_callback: ffi::cubeb_data_callback,
     state_callback: ffi::cubeb_state_callback,
     device_changed_callback: Mutex<ffi::cubeb_device_changed_callback>,
     // Frame counters
     frames_played: AtomicU64,
     frames_queued: u64,
     // How many frames got read from the input since the stream started (includes
     // padded silence)
-    frames_read: AtomicI64,
+    frames_read: AtomicUsize,
     // How many frames got written to the output device since the stream started
-    frames_written: AtomicI64,
+    frames_written: AtomicUsize,
     shutdown: AtomicBool,
     draining: AtomicBool,
     reinit_pending: AtomicBool,
     destroy_pending: AtomicBool,
     // Latency requested by the user.
     latency_frames: u32,
     current_latency_frames: AtomicU32,
     total_output_latency_frames: AtomicU32,
@@ -3114,18 +3161,18 @@ impl<'ctx> AudioUnitStream<'ctx> {
             context,
             user_ptr,
             queue: Queue::new(DISPATCH_QUEUE_LABEL),
             data_callback,
             state_callback,
             device_changed_callback: Mutex::new(None),
             frames_played: AtomicU64::new(0),
             frames_queued: 0,
-            frames_read: AtomicI64::new(0),
-            frames_written: AtomicI64::new(0),
+            frames_read: AtomicUsize::new(0),
+            frames_written: AtomicUsize::new(0),
             shutdown: AtomicBool::new(true),
             draining: AtomicBool::new(false),
             reinit_pending: AtomicBool::new(false),
             destroy_pending: AtomicBool::new(false),
             latency_frames,
             current_latency_frames: AtomicU32::new(0),
             total_output_latency_frames: AtomicU32::new(0),
             switching_device: AtomicBool::new(false),
--- a/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs
@@ -112,17 +112,17 @@ fn test_make_silent() {
 // ------------------------------------
 #[test]
 fn test_minimum_resampling_input_frames() {
     let input_rate = 48000_f64;
     let output_rate = 44100_f64;
 
     let frames = 100;
     let times = input_rate / output_rate;
-    let expected = (frames as f64 * times).ceil() as i64;
+    let expected = (frames as f64 * times).ceil() as usize;
 
     assert_eq!(
         minimum_resampling_input_frames(input_rate, output_rate, frames),
         expected
     );
 }
 
 #[test]
@@ -1335,16 +1335,17 @@ fn test_get_device_presentation_latency(
             );
         } else {
             println!("No device for {:?}.", scope);
         }
     }
 }
 
 // create_cubeb_device_info
+// destroy_cubeb_device_info
 // ------------------------------------
 #[test]
 fn test_create_cubeb_device_info() {
     use std::collections::VecDeque;
 
     test_create_device_from_hwdev_in_scope(Scope::Input);
     test_create_device_from_hwdev_in_scope(Scope::Output);
 
@@ -1389,17 +1390,18 @@ fn test_create_cubeb_device_info() {
     }
 
     fn check_device_info_by_device(info: &ffi::cubeb_device_info, id: AudioObjectID, scope: Scope) {
         assert!(!info.devid.is_null());
         assert!(mem::size_of_val(&info.devid) >= mem::size_of::<AudioObjectID>());
         assert_eq!(info.devid as AudioObjectID, id);
         assert!(!info.device_id.is_null());
         assert!(!info.friendly_name.is_null());
-        assert_eq!(info.group_id, info.device_id);
+        assert!(!info.group_id.is_null());
+
         // TODO: Hit a kAudioHardwareUnknownPropertyError for AirPods
         // assert!(!info.vendor_name.is_null());
 
         // FIXIT: The device is defined to input-only or output-only, but some device is in-out!
         assert_eq!(info.device_type, DeviceType::from(scope.clone()).bits());
         assert_eq!(info.state, ffi::CUBEB_DEVICE_STATE_ENABLED);
         // TODO: The preference is set when the device is default input/output device if the device
         //       info is created from input/output scope. Should the preference be set if the
@@ -1446,16 +1448,35 @@ fn test_create_device_info_with_unknown_
             assert!(create_cubeb_device_info(device, DeviceType::UNKNOWN).is_err());
         } else {
             panic!("Panic by default: No device for {:?}.", scope);
         }
     }
 }
 
 #[test]
+#[should_panic]
+fn test_device_destroy_empty_device() {
+    let mut device = ffi::cubeb_device_info::default();
+
+    assert!(device.device_id.is_null());
+    assert!(device.group_id.is_null());
+    assert!(device.friendly_name.is_null());
+    assert!(device.vendor_name.is_null());
+
+    // `friendly_name` must be set.
+    destroy_cubeb_device_info(&mut device);
+
+    assert!(device.device_id.is_null());
+    assert!(device.group_id.is_null());
+    assert!(device.friendly_name.is_null());
+    assert!(device.vendor_name.is_null());
+}
+
+#[test]
 fn test_create_device_from_hwdev_with_inout_type() {
     test_create_device_from_hwdev_with_inout_type_by_scope(Scope::Input);
     test_create_device_from_hwdev_with_inout_type_by_scope(Scope::Output);
 
     fn test_create_device_from_hwdev_with_inout_type_by_scope(scope: Scope) {
         if let Some(device) = test_get_default_device(scope.clone()) {
             // Get a kAudioHardwareUnknownPropertyError in get_channel_count actually.
             assert!(
@@ -1479,66 +1500,16 @@ fn test_is_aggregate_device() {
     info.friendly_name = aggregate_name_cstring.as_ptr();
     assert!(is_aggregate_device(&info));
 
     let non_aggregate_name_cstring = CString::new("Hello World!").unwrap();
     info.friendly_name = non_aggregate_name_cstring.as_ptr();
     assert!(!is_aggregate_device(&info));
 }
 
-// destroy_cubeb_device_info
-// ------------------------------------
-#[test]
-fn test_device_destroy() {
-    let mut device = ffi::cubeb_device_info::default();
-
-    let device_id = CString::new("test: device id").unwrap();
-    let friendly_name = CString::new("test: friendly name").unwrap();
-    let vendor_name = CString::new("test: vendor name").unwrap();
-
-    device.device_id = device_id.into_raw();
-    // The group_id is a mirror to device_id in our implementation, so we could skip it.
-    device.group_id = device.device_id;
-    device.friendly_name = friendly_name.into_raw();
-    device.vendor_name = vendor_name.into_raw();
-
-    destroy_cubeb_device_info(&mut device);
-
-    assert!(device.device_id.is_null());
-    assert!(device.group_id.is_null());
-    assert!(device.friendly_name.is_null());
-    assert!(device.vendor_name.is_null());
-}
-
-#[test]
-#[should_panic]
-fn test_device_destroy_with_different_device_id_and_group_id() {
-    let mut device = ffi::cubeb_device_info::default();
-    device.device_id = 0xdeaddead as *const _;
-    device.group_id = 0xdeadbeef as *const _;
-    destroy_cubeb_device_info(&mut device);
-}
-
-#[test]
-fn test_device_destroy_empty_device() {
-    let mut device = ffi::cubeb_device_info::default();
-
-    assert!(device.device_id.is_null());
-    assert!(device.group_id.is_null());
-    assert!(device.friendly_name.is_null());
-    assert!(device.vendor_name.is_null());
-
-    destroy_cubeb_device_info(&mut device);
-
-    assert!(device.device_id.is_null());
-    assert!(device.group_id.is_null());
-    assert!(device.friendly_name.is_null());
-    assert!(device.vendor_name.is_null());
-}
-
 // get_devices_of_type
 // ------------------------------------
 #[test]
 fn test_get_devices_of_type() {
     use std::collections::HashSet;
 
     let all_devices = audiounit_get_devices_of_type(DeviceType::INPUT | DeviceType::OUTPUT);
     let input_devices = audiounit_get_devices_of_type(DeviceType::INPUT);
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -14,17 +14,17 @@ nserror = { path = "../../../../xpcom/ru
 nsstring = { path = "../../../../xpcom/rust/nsstring" }
 netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
 xpcom = { path = "../../../../xpcom/rust/xpcom" }
 prefs_parser = { path = "../../../../modules/libpref/parser" }
 static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
 profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
 mozurl = { path = "../../../../netwerk/base/mozurl" }
 webrender_bindings = { path = "../../../../gfx/webrender_bindings", optional = true }
-cubeb-coreaudio = { git = "https://github.com/ChunMinChang/cubeb-coreaudio-rs", rev = "799518a033a0c780cfdb82a4eaabfd9681cb7f3b", optional = true }
+cubeb-coreaudio = { git = "https://github.com/ChunMinChang/cubeb-coreaudio-rs", rev = "20daa86ae2829351d08c829f1ebad2755c583abf", optional = true }
 cubeb-pulse = { git = "https://github.com/djg/cubeb-pulse-rs", rev="8069f8f4189982e0b38fa6dc8993dd4fab41f728", optional = true, features=["pulse-dlopen"] }
 cubeb-sys = { version = "0.6", optional = true, features=["gecko-in-tree"] }
 encoding_glue = { path = "../../../../intl/encoding_glue" }
 audioipc-client = { path = "../../../../media/audioipc/client", optional = true }
 audioipc-server = { path = "../../../../media/audioipc/server", optional = true }
 authenticator = "0.2.10"
 gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
 rsdparsa_capi = { path = "../../../../media/webrtc/signaling/src/sdp/rsdparsa_capi" }