getUserMedia({audio}) right after audioTrack.stop() fails with AbortError
Categories
(Core :: WebRTC: Audio/Video, defect, P3)
Tracking
()
Tracking | Status | |
---|---|---|
firefox68 | --- | fixed |
People
(Reporter: shaker.haibo, Assigned: jib)
References
Details
Attachments
(1 file)
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Steps to reproduce:
(1) using navigator.mediaDevices.getUserMedia({audio: true}) to get the audio stream. Add the stream to a WebRTC peer connection.
(2) After a while, we want to switch the microphone. Enumerate the devices and get another available microphone device id.
(3) Stop the previous old stream.
oldStream.getAudioTracks().forEach(function (track) {
track.enabled = false;
track.stop();
});
(4) Capture the new audio stream by getUserMedia() with specific device
Actual results:
The getUserMedia promise rejects with "Abort Error"
The Firefox internal logs show "GetUserMediaStreamRunnable::Run: starting failure callback following InitializeAsync()"
Expected results:
The getUserMedia promise resolves and returns a valid stream
B.T.W, it works well on older Firefox 60
Updated•6 years ago
|
Comment 1•6 years ago
|
||
Thanks for the report!
I have a hunch where this is failing, so I'd like to confirm.
Does the abort error come with a message with more information (on the js object)? Does the Web Console (in Developer Tools) show anything related?
I don't understand why it would be failing like this though, given that the second microphone otherwise works normally. Do you have a simplified testcase page I can reproduce this on myself?
navigator.mediaDevices.getUserMedia({
audio: _audioConstraints
}).then(function (stream) {
}, function (error) {
// Catch the error here.
});
The error is:
MediaStreamError
constraint: ""
message: "Starting audio failed"
name: "AbortError"
stack: ""
About the demo page, I have no such page now. I will post one if available.
Comment 3•6 years ago
|
||
This is probably the old "a single input device per document" limitation. We need to try to understand why stopping the track is not cleaning things up fast enough. Andreas, an idea about this?
Updated•6 years ago
|
Comment 4•6 years ago
|
||
Ah, I managed to reproduce this eventually. There are missing bits in comment 0 needed to reproduce this.
Steps to reproduce:
1 Ensure you have two audio input devices on your system (this tested on Mac)
2 Go to https://jsfiddle.net/pehrsons/7hurneaz/
3 Click on "Ask for Devices"
4 Accept the permission prompt, and be sure to check the "Remember this decision" checkbox
Expected:
No errors
Actual:
AbortError shown on page, console shows it has the message
"Starting audio failed", i.e., from [1], thus [2], like padenot speculated in.
[1] https://searchfox.org/mozilla-central/rev/75294521381b331f821aad3d6b60636844080ee2/dom/media/MediaManager.cpp#4144
[2] https://searchfox.org/mozilla-central/rev/75294521381b331f821aad3d6b60636844080ee2/dom/media/webrtc/MediaEngineWebRTCAudio.cpp#556-558
Comment 5•6 years ago
|
||
Waiting a bit after the audioTrack.stop() seems to work, like in https://jsfiddle.net/pehrsons/xeojsw0p/
[1] shows it depends on MSGImpl::InputDeviceID()
which we call from the MediaManager thread. However this member is set on the graph thread at [2]. There's a race here that is not trivial to solve unless we move the MediaEngineWebRTCMicrophoneSource::Start() error to be an async MediaStreamTrack::OnEnded instead. Perhaps we need that as the fallback in MediaStreamGraph, and a way of tracking which input device is used for the document in MediaManager so we don't get into the situation that triggers that "ended" event later.
Or remove the limitation of one input device per doc, but how much work is that?
Either way we should fix the race here first.
I won't have time to work on this anytime soon. Paul or jib, perhaps either of you could take a look at what's acceptable here?
[1] https://searchfox.org/mozilla-central/rev/75294521381b331f821aad3d6b60636844080ee2/dom/media/webrtc/MediaEngineWebRTCAudio.cpp#554
[2] https://searchfox.org/mozilla-central/rev/75294521381b331f821aad3d6b60636844080ee2/dom/media/MediaStreamGraph.cpp#812
Assignee | ||
Comment 6•6 years ago
•
|
||
If this is only an issue with audio—which seems to be the case—then I vote we hack it at the primary call site for Start()
in InitializeAsync. The other place we call it, for mute/unmute shouldn't need changing.
Basically: pick a specific error code, and check for it here and if it matches, wait 200 ms and try one more time before giving up.
If we do that, we should use a timer—maybe make a nice media::Wait(200)
function that returns a MozPromise? And not jank.
Comment 7•6 years ago
|
||
jib, you seem to have the solution, can you write the patch?
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 8•6 years ago
|
||
Comment 10•6 years ago
|
||
bugherder |
Updated•6 years ago
|
Description
•