Skip to content

[Enhancement] iOS Audio engine input / output availability - #102

Merged
santhoshvai merged 1 commit into
mainfrom
develop
Jul 27, 2026
Merged

[Enhancement] iOS Audio engine input / output availability #102
santhoshvai merged 1 commit into
mainfrom
develop

Conversation

@santhoshvai

@santhoshvai santhoshvai commented Jul 27, 2026

Copy link
Copy Markdown
Member

WebRTC Changelog 145.11.0 — Audio Engine Availability (develop → main)

Release 145.11.0 is a patch release on top of 145.10.0. It contains no WebRTC baseline bump — the upstream webrtc.googlesource.com/src revision is unchanged from the previous release. The only change is a Stream fork addition to the iOS/macOS AudioEngineDevice, giving hosts an explicit way to gate when the audio engine is allowed to start and stop.

Compare: main...develop
Range: ee2a4bef1711813e3d764850 (1 commit, first-parent)


Summary

AudioEngineDevice previously started the input and output engines purely as a function of its own enabled/running state. That works when WebRTC owns the audio lifecycle, but breaks in host-driven flows — most notably CallKit, where the system decides when AVAudioSession becomes active and starting AVAudioEngine too early (or too late) results in no audio, a dropped route, or a hard engine failure.

This release adds an availability gate: two independent flags (inputAvailable / outputAvailable) that act as a veto on top of all existing engine-state logic. Both default to true, so existing behavior is unchanged unless an integrator opts in by setting availability to false. Once set, the engine will not enable or run the corresponding direction regardless of what the rest of the state machine wants — letting the host hold the engine back until the platform says it is safe to start, then release it.

The change is ported from the upstream webrtc-sdk/webrtc fork (PR #196) and adapted for Stream, with the ObjC entry points guarded to match the rest of the audio-engine surface.


Categories

Counts as reported by scripts/generate_changelog.py for origin/main..origin/develop:

Category Count
Upstream WebRTC merge 0
Features 0
Fixes 0
Platform / build 0
Tests / internal 0
Other changes 0
Breaking change review (public headers / packaged API) 1
Total commits in range 1

The single commit is not auto-classified into a feature/fix bucket; it is flagged for breaking change review because it touches packaged public headers. See Notes for Reviewers — the API change is purely additive.


Stream Integration Highlights

  • New engine availability gate (iOS / macOS). AudioEngineDevice::EngineState gains input_available and output_available (both defaulting to true). Every enabled/running query — IsInputEnabled, IsInputRunning, IsOutputEnabled, IsOutputRunning — now ANDs its result with the matching availability flag, so a single flag suppresses start/stop for that direction across the whole state machine rather than at individual call sites.

  • Native control surface. AudioEngineDevice::SetEngineAvailability(bool input, bool output) and AudioEngineDevice::EngineAvailability(bool*, bool*) are added, both asserting they run on the device thread. Setting availability goes through the existing ModifyEngineState transform, so a change is applied and reconciled the same way as any other engine-state transition — no separate code path.

  • Public ObjC API (additive). RTCAudioDeviceModule exposes:

    • - (NSInteger)setEngineAvailability:(RTCAudioEngineAvailability)availability;
    • @property(nonatomic, readonly) RTCAudioEngineAvailability engineAvailability;

    backed by a new lightweight struct RTCAudioEngineAvailability { bool isInputAvailable; bool isOutputAvailable; }. Both hop to the worker thread via BlockingCall, and both are guarded on WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE, native-module readiness, worker-thread readiness, and isAudioEngineModule — matching the guard pattern already used by the other audio-engine-only members. Guard failures return -1 (setter) or (NO, NO) (getter) instead of touching a null module.

  • Simplified aggregate state predicates. IsAllEnabled() / IsAllRunning() are rewritten as plain IsInputEnabled() && IsOutputEnabled() and IsInputRunning() && IsOutputRunning(), replacing the previous branch on IsOutputInputLinked(). This removes duplicated linkage logic and ensures the new availability gate is honored by the aggregate predicates too.

  • Debug logging. DebugEngineState now prints InputAvailable / OutputAvailable, so availability is visible in engine-state dumps when diagnosing "engine didn't start" reports.

  • Header tidy-up. Trailing whitespace removed from the RTCAudioProcessingState struct declaration. No functional effect.

Primary use case: with CallKit, set availability to false while the call is being set up, then flip it to true from provider:didActivateAudioSession: so the engine starts only once the system session is active — and back to false on deactivation.


Fixes

None in this release.

Platform / build

No build, toolchain, GN, or dependency changes. DEPS and the upstream baseline are untouched, so this release rebuilds against the same WebRTC revision as 145.10.0.


Notes for Reviewers

  • Public API surface changed — additive only. sdk/objc/api/peerconnection/RTCAudioDeviceModule.h gains one struct, one method, and one readonly property. Nothing was renamed, removed, or re-typed, so existing consumers compile and behave unchanged. RTCAudioEngineAvailability is new and needs to be visible in the packaged framework headers — worth confirming it is exported alongside the other RTC_OBJC_TYPE audio-engine structs when the xcframework is built.
  • Default is backwards-compatible. input_available and output_available initialize to true in EngineState, and nothing in this change writes them except the new setter. A build that never calls setEngineAvailability: is behaviorally identical to 145.10.0.
  • IsAllEnabled is equivalent; IsAllRunning is subtly stricter. For IsAllEnabled, the new expression reduces to the old one in both the linked and unlinked cases. For IsAllRunning, the old form compared the raw input_running field, whereas IsInputRunning() also applies the MuteMode::RestartEngine && input_muted guard. Net effect: a muted-via-engine-restart device is no longer reported as "all running". This looks correct and intended, but it is the one place where behavior changes without anyone opting in — worth a focused check against mute/unmute flows using MuteMode::RestartEngine.
  • Availability is a veto, not a request. Setting outputAvailable = false suppresses output even when output is enabled and linked to input. Because IsOutputInputLinked() makes output follow input, gating input alone will also stop output in voice-processing mode. Integrators generally want to set both flags together.
  • Getter returns (NO, NO) on guard failure. engineAvailability cannot distinguish "input and output are both unavailable" from "the audio engine module isn't ready / this isn't an engine module". Callers should not treat a (NO, NO) read as authoritative before the ADM is initialized.
  • Threading. Native methods are annotated RTC_DCHECK_RUN_ON(thread_) and reached only via _workerThread->BlockingCall. setEngineAvailability: and engineAvailability are therefore synchronous and blocking — do not call them from an audio-render or other latency-sensitive callback.
  • Scope is Apple platforms only. Four files changed (+102 / −17): modules/audio_device/audio_engine_device.{h,mm} and sdk/objc/api/peerconnection/RTCAudioDeviceModule.{h,mm}. No Android, Java/JNI, frame-cryptor, pc/, or api/ changes — Android artifacts for this release carry no source changes.
  • Provenance. Ported from webrtc-sdk/webrtc PR #196, co-authored by Hiroshi Horie, with Stream-side review fixes (the guard hardening on setEngineAvailability: / engineAvailability).
  • No automated coverage added. There are no unit tests for the availability gate; validation should be manual on a device — a normal call to confirm the default path is unchanged, and a CallKit-driven call to confirm the gate defers engine start until the system session activates.

Publish

  • Version: 145.11.0
  • Alpha: off (stable release — pre-releases use the workflow's alpha flag rather than a version suffix)
  • Merge: developmain

Summary by CodeRabbit

  • New Features
    • Added controls to set and query audio engine input and output availability.
    • Added Objective-C APIs for managing and reading audio engine availability.
    • Audio engine state now distinguishes input and output availability.
  • Behavior Changes
    • Disabled or unavailable input/output paths are no longer reported as enabled or running.
    • Availability is included in audio engine state diagnostics.

* Audio engine input / output availability (#196)

Adds a flag to override engine start/stop behavior, useful in scenarios
such as CallKit, where the timing for starting AVAudioSession and
AVAudioEngine is restricted.

* review comments fix

* fix: guard setEngineAvailability: / engineAvailability, matching other methods

---------

Co-authored-by: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b15fb9f1-f00a-4b16-a236-36f6b88ebe46

📥 Commits

Reviewing files that changed from the base of the PR and between ee2a4be and 813e3d7.

📒 Files selected for processing (4)
  • modules/audio_device/audio_engine_device.h
  • modules/audio_device/audio_engine_device.mm
  • sdk/objc/api/peerconnection/RTCAudioDeviceModule.h
  • sdk/objc/api/peerconnection/RTCAudioDeviceModule.mm

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Walkthrough

AudioEngineDevice now tracks input and output availability independently, gates engine state calculations accordingly, and exposes native and Objective-C APIs for updating and querying availability.

Changes

Audio engine availability

Layer / File(s) Summary
Availability state and gating
modules/audio_device/audio_engine_device.h
EngineState stores input/output availability, includes them in equality checks, and gates enabled/running state calculations.
Native availability API
modules/audio_device/audio_engine_device.h, modules/audio_device/audio_engine_device.mm
Native setter and getter methods update or return availability, with null-pointer validation and debug-state logging.
Objective-C availability bridge
sdk/objc/api/peerconnection/RTCAudioDeviceModule.*
Adds the availability type, setter, and getter, forwarding calls through the worker thread when internal audio support is enabled and returning unavailable sentinels otherwise.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RTCAudioDeviceModule
  participant WorkerThread
  participant AudioEngineDevice
  Client->>RTCAudioDeviceModule: setEngineAvailability
  RTCAudioDeviceModule->>WorkerThread: BlockingCall
  WorkerThread->>AudioEngineDevice: SetEngineAvailability
  Client->>RTCAudioDeviceModule: engineAvailability
  RTCAudioDeviceModule->>WorkerThread: BlockingCall
  WorkerThread->>AudioEngineDevice: EngineAvailability
  AudioEngineDevice-->>RTCAudioDeviceModule: Availability values
  RTCAudioDeviceModule-->>Client: RTCAudioEngineAvailability
Loading

Possibly related PRs

Suggested reviewers: ipavlidakis

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@santhoshvai
santhoshvai merged commit 20df2b7 into main Jul 27, 2026
7 of 8 checks passed
@santhoshvai
santhoshvai deleted the develop branch July 27, 2026 16:44
@santhoshvai
santhoshvai restored the develop branch July 27, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant