NEW271227
AudioContext attached nodes can be collected
https://bugs.webkit.org/show_bug.cgi?id=271227
Summary AudioContext attached nodes can be collected
youenn fablet
Reported 2024-03-19 02:52:02 PDT
AudioContext attached nodes can be collected, which can have an impact on audio rendering/now playing info. For instance in current LayoutTests/media/now-playing-webaudio.html: <!doctype html> <html> <head> <meta charset="utf-8"> <title>Testing basic video exchange from offerer to receiver</title> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> </head> <body> <script> function waitFor(delay) { return new Promise(resolve => setTimeout(resolve, delay)); } async function waitForCriteria(test, criteria) { let counter = 0; while (!criteria() && ++counter < 100) await waitFor(50); } promise_test(async test => { if (!window.internals) return; navigator.audioSession.type = "playback"; let context = new AudioContext(); await waitFor(100); assert_false(!!internals.nowPlayingState.uniqueIdentifier); let oscillator = null; let gainNode = context.createGain(); oscillator = context.createOscillator(); oscillator.type = 'square'; oscillator.frequency.setValueAtTime(440, context.currentTime); oscillator.connect(gainNode); gainNode.gain.value = 0.1 internals.withUserGesture(() => { context.resume(); }); await waitFor(100); assert_false(!!internals.nowPlayingState.uniqueIdentifier); gainNode.connect(context.destination); await waitForCriteria(test, () => { return !!internals.nowPlayingState.uniqueIdentifier; }); assert_true(!!internals.nowPlayingState.uniqueIdentifier, "active now playing"); context.suspend(); await waitForCriteria(test, () => { return !internals.nowPlayingState.uniqueIdentifier; }); assert_false(!!internals.nowPlayingState.uniqueIdentifier, "inactive now playing"); context.resume(); await waitForCriteria(test, () => { return !!internals.nowPlayingState.uniqueIdentifier; }); assert_true(!!internals.nowPlayingState.uniqueIdentifier, "active now playing again"); }, "AudioContext as the now playing info source"); promise_test(async test => { if (!window.internals) return; const identifier = internals.nowPlayingState.uniqueIdentifier; let mediaElement = document.createElement("audio"); document.body.appendChild(mediaElement); await waitFor(100); assert_equals(internals.nowPlayingState.uniqueIdentifier, identifier, "AudioContext identifier"); await waitFor(100); assert_equals(internals.nowPlayingState.uniqueIdentifier, identifier, "AudioContext identifier 2"); mediaElement.src = "content/test.wav"; await waitForCriteria(test, () => { return internals.nowPlayingState.uniqueIdentifier !== identifier; }); assert_not_equals(internals.nowPlayingState.uniqueIdentifier, identifier, "HTMLMediaElement identifier"); const mediaElementIdentifier = internals.nowPlayingState.uniqueIdentifier document.body.removeChild(mediaElement); await waitForCriteria(test, () => { return internals.nowPlayingState.uniqueIdentifier !== mediaElementIdentifier; }); assert_equals(internals.nowPlayingState.uniqueIdentifier, identifier, "AudioContext identifier 3"); }, "HTMLMediaElement will become the now playing info source over playing AudioContext"); </script> </body> </html>
Attachments
Radar WebKit Bug Importer
Comment 1 2024-03-19 02:52:22 PDT
youenn fablet
Comment 2 2025-01-31 08:49:24 PST
Looking a bit more, calling start() fixes the issue. I am not sure whether it makes a difference to have a node that disappears or keeping a node that is not started. When plugging a MediaStream destination node, this has the internal effect of audioSamplesAvailable being no longer called (but maybe this should be handled by MediaStream destination node itself).
Note You need to log in before you can comment on or make changes to this bug.