Android 11 Hanging Chrome Fix: Call `stop()` on LiveStream <video> element before stopping video stream
See original GitHub issueDescription
On Android 11 we started experiencing a behavior where calling quaggaInstance.stop()
causes the video element to freeze Chrome rendering. Touch events are still active (tapping around on the app causes the URL to change when accidentally clicking links), but nothing on the view changes. Even elements under the video element are frozen. Testing on Android 10 did not seem to exhibit the issue. If I had to guess, there’s a memory leak that happens when stopping underlying MediaChannel references without first pausing the parent <video>
element itself.
Device Test Specifics
- Android 11
- Pixel 2 (Chrome 86.0.4240.99) and Pixel 4 (Chrome 86.0.4240.99)
Reproduction Steps
- Initialize and start Quagga
- Trigger a quaggaInstance.stop()
- Notice that Android 11 devices running Chrome seem to hang
Solution Steps We’ve found a workaround for now, thanks to this comment in the Quagga code base: https://github.com/ericblade/quagga2/blob/8226a048ad526845ff6b102be1a10f2ca57fbcce/src/input/camera_access.ts#L101
Through some experimentation, we came up with the following solution:
public stopScanner() {
const htmlVideoElements: NodeListOf<HTMLVideoElement> = document.getElementsByName('video') as NodeListOf<HTMLVideoElement>
for (let i = 0; i < htmlVideoElements.length; ++i) {
const targetElement = htmlVideoElements[i]
if (targetElement && targetElement.pause) {
targetElement.pause()
}
}
setTimeout(() => {
Quagga.stop()
}, 0)
}
We also did the reverse in a startScanner()
method, calling play()
on all <video>
elements, setting a timeout, and calling Quagga.start()
. So far it’s fixed the issue for us.
The setTimeout seems to be necessary to give the target elements a chance to pause the underlying camera hardware before attempting to stop the MediaChannels. Otherwise my test devices exhibit a race condition behavior where the solution only sometimes works.
If I get the spare chance I’ll open a PR for you all, but wanted to file this as an issue first in case anyone else is running into this problem.
Issue Analytics
- State:
- Created 3 years ago
- Comments:18 (8 by maintainers)
Top GitHub Comments
For what it’s worth, this does seem to be either an Android 11 issue, or more specifically the Pixels. I have a PWA that not only uses this barcode scanner library, but also has normal camera functions. 3 of my users are on Pixels (this is an internal business app), and all have similar issues with Chrome freezing when the video playback is stopped. In both my camera section, and the barcode scanner.
It aggravated me so much I bought a Pixel 4a just to test this. Absolutely no errors in the console.
Following @anonmos suggestion about pausing the video elements before issuing a stop fixed this for me. In both the barcode scanner, and my other camera functions. Just to be on the safe side, I used a 10ms wait on the setTimeout, but that probably isn’t necessary.
One other tidbit of information. When my Pixel 4a arrived, I immediately tested my app, without doing any OS updates. No freezing or lockups. Once I took the latest update, the freezing was consistent. Unfortunately, I didn’t take note of the OS version at unboxing.
@hariaw very thorough. I don’t see anything you’ve missed. Looks like you’ve got it covered.
Thanks for submitting. Still working on a time slot to get the patch in on quagga.