Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support background filter for ios 16+ #2484

Merged
merged 2 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add the audio output gain and frequency to the meeting readiness checker's configuration. The readiness checker uses this value to set the "Play Tone" gain and frequency.
- Add support for background filter starting from iOS 16 for major browsers Safari, Chrome, and Firefox (except on iPad).

### Removed

Expand Down
2 changes: 1 addition & 1 deletion demos/browser/app/meetingV2/meetingV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ export class DemoMeetingApp
}

(document.getElementById('sdk-version') as HTMLSpanElement).innerText =
'amazon-chime-sdk-js@' + Versioning.sdkVersion;
'amazon-chime-sdk-js@' + Versioning.sdkVersion;
this.initEventListeners();
this.initParameters();
this.setMediaRegion();
Expand Down
4,762 changes: 2,383 additions & 2,379 deletions docs/assets/js/search.js

Large diffs are not rendered by default.

77 changes: 49 additions & 28 deletions docs/classes/defaultbrowserbehavior.html

Large diffs are not rendered by default.

41 changes: 39 additions & 2 deletions docs/modules/backgroundfilter_video_processor.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,45 @@ <h2>Can I use a background filter in my application?</h2>
<a href="#browser-compatibility" id="browser-compatibility" style="color: inherit; text-decoration: none;">
<h3>Browser compatibility</h3>
</a>
<p>A background filter in the Amazon Chime SDK for JavaScript works in Firefox, Chrome, and Chromium-based browsers (including Electron) on desktop, Android, and Safari 14.1 and later on macOS.</p>
<p>There is a known issue with <code>VideoFrameProcessor</code> in Safari 15: see <a href="https://github.com/aws/amazon-chime-sdk-js/issues/1059">github issue 1059</a></p>
<p>The APIs for video processing in Amazon Chime SDK for JavaScript work in Firefox, Chrome, Chromium-based browsers
(including Electron) on desktop, Android and iOS operating systems. A full compatibility table is below.</p>
<table>
<thead>
<tr>
<th>Browser</th>
<th>Minimum supported version</th>
</tr>
</thead>
<tbody><tr>
<td>Firefox</td>
<td>76</td>
</tr>
<tr>
<td>Chromium-based browsers and environments, including Edge and Electron</td>
<td>78</td>
</tr>
<tr>
<td>Android Chrome</td>
<td>78</td>
</tr>
<tr>
<td>Safari on MacOS</td>
<td>13.0</td>
</tr>
<tr>
<td>iOS Safari</td>
<td>16</td>
</tr>
<tr>
<td>iOS Chrome</td>
<td>16</td>
</tr>
<tr>
<td>iOS Firefox (Except on iPad)</td>
<td>16</td>
</tr>
</tbody></table>
<p>Note that there is a known issue with <code>VideoFrameProcessor</code> in Safari 15: see <a href="https://github.com/aws/amazon-chime-sdk-js/issues/1059">github issue 1059</a>. This has been fixed with Safari 16.</p>
<p>A background filter can be CPU-intensive and the web runtime affects performance. As such, not all mobile devices or lower-spec laptop or desktop computers will be sufficiently powerful, or will be able to use a background filter while also supporting multiple video streams and rich application functionality.</p>
<p>See the sections “<a href="#checking-for-support-before-offering-a-background-filter">Checking for support before offering a background filter</a>” for more details about checking for support.</p>
<a href="#simd-support" id="simd-support" style="color: inherit; text-decoration: none;">
Expand Down
12 changes: 7 additions & 5 deletions docs/modules/videoprocessor.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ <h2>Introduction</h2>
<a href="#browser-compatibility" id="browser-compatibility" style="color: inherit; text-decoration: none;">
<h3>Browser compatibility</h3>
</a>
<p>The APIs for video processing in Amazon Chime SDK for JavaScript work in Firefox, Chrome, Chromium-based browsers (including Electron) on desktop, and Android operating systems. A full compatibility table is below. Currently, the APIs for video processing do not support Safari/Chrome/Firefox on iOS devices due to <a href="https://bugs.webkit.org/show_bug.cgi?id=181663">Webkit Bug 181663</a>.</p>
<p>The APIs for video processing in Amazon Chime SDK for JavaScript work in Firefox, Chrome, Chromium-based browsers
(including Electron) on desktop, Android and iOS operating systems. A full compatibility table is below.</p>
<table>
<thead>
<tr>
Expand All @@ -113,17 +114,18 @@ <h3>Browser compatibility</h3>
</tr>
<tr>
<td>iOS Safari</td>
<td>Not supported</td>
<td>16</td>
</tr>
<tr>
<td>iOS Chrome</td>
<td>Not supported</td>
<td>16</td>
</tr>
<tr>
<td>iOS Firefox</td>
<td>Not supported</td>
<td>iOS Firefox (Except on iPad)</td>
<td>16</td>
</tr>
</tbody></table>
<p>Note that there is a known issue with <code>VideoFrameProcessor</code> in Safari 15: see <a href="https://github.com/aws/amazon-chime-sdk-js/issues/1059">github issue 1059</a>. This has been fixed with Safari 16.</p>
<a href="#video-processing-apis" id="video-processing-apis" style="color: inherit; text-decoration: none;">
<h2>Video Processing APIs</h2>
</a>
Expand Down
11 changes: 7 additions & 4 deletions guides/10_Video_Processor.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ A typical workflow would be:

### Browser compatibility

The APIs for video processing in Amazon Chime SDK for JavaScript work in Firefox, Chrome, Chromium-based browsers (including Electron) on desktop, and Android operating systems. A full compatibility table is below. Currently, the APIs for video processing do not support Safari/Chrome/Firefox on iOS devices due to [Webkit Bug 181663](https://bugs.webkit.org/show_bug.cgi?id=181663).
The APIs for video processing in Amazon Chime SDK for JavaScript work in Firefox, Chrome, Chromium-based browsers
(including Electron) on desktop, Android and iOS operating systems. A full compatibility table is below.

|Browser |Minimum supported version
|--- |---
|Firefox |76
|Chromium-based browsers and environments, including Edge and Electron |78
|Android Chrome |78
|Safari on MacOS |13.0
|iOS Safari |Not supported
|iOS Chrome |Not supported
|iOS Firefox |Not supported
|iOS Safari |16
|iOS Chrome |16
|iOS Firefox (Except on iPad) |16

Note that there is a known issue with `VideoFrameProcessor` in Safari 15: see [github issue 1059](https://github.com/aws/amazon-chime-sdk-js/issues/1059). This has been fixed with Safari 16.

## Video Processing APIs

Expand Down
17 changes: 14 additions & 3 deletions guides/15_Background_Filter_Video_Processor.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ Background replacement is available as part of the Amazon Chime SDK for JavaScri

### Browser compatibility

A background filter in the Amazon Chime SDK for JavaScript works in Firefox, Chrome, and Chromium-based browsers (including Electron) on desktop, Android, and Safari 14.1 and later on macOS.

There is a known issue with `VideoFrameProcessor` in Safari 15: see [github issue 1059](https://github.com/aws/amazon-chime-sdk-js/issues/1059)
The APIs for video processing in Amazon Chime SDK for JavaScript work in Firefox, Chrome, Chromium-based browsers
(including Electron) on desktop, Android and iOS operating systems. A full compatibility table is below.

|Browser |Minimum supported version
|--- |---
|Firefox |76
|Chromium-based browsers and environments, including Edge and Electron |78
|Android Chrome |78
|Safari on MacOS |13.0
|iOS Safari |16
|iOS Chrome |16
|iOS Firefox (Except on iPad) |16

Note that there is a known issue with `VideoFrameProcessor` in Safari 15: see [github issue 1059](https://github.com/aws/amazon-chime-sdk-js/issues/1059). This has been fixed with Safari 16.
xuesichao marked this conversation as resolved.
Show resolved Hide resolved

A background filter can be CPU-intensive and the web runtime affects performance. As such, not all mobile devices or lower-spec laptop or desktop computers will be sufficiently powerful, or will be able to use a background filter while also supporting multiple video streams and rich application functionality.

Expand Down
13 changes: 12 additions & 1 deletion src/browserbehavior/DefaultBrowserBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
// SPDX-License-Identifier: Apache-2.0

import { detect } from 'detect-browser';
import { UAParser } from 'ua-parser-js';

import BrowserBehavior from './BrowserBehavior';
import ExtendedBrowserBehavior from './ExtendedBrowserBehavior';

export default class DefaultBrowserBehavior implements BrowserBehavior, ExtendedBrowserBehavior {
private readonly browser = detect();
private readonly uaParserResult =
navigator && navigator.userAgent ? new UAParser(navigator.userAgent).getResult() : null;

private browserSupport: { [id: string]: number } = {
chrome: 78,
Expand Down Expand Up @@ -48,6 +51,7 @@ export default class DefaultBrowserBehavior implements BrowserBehavior, Extended
];

private webkitBrowsers: string[] = ['crios', 'fxios', 'safari', 'ios', 'ios-webview'];
private static MIN_IOS_SUPPORT_CANVAS_STREAM_PLAYBACK = 16;

version(): string {
return this.browser.version;
Expand All @@ -57,6 +61,10 @@ export default class DefaultBrowserBehavior implements BrowserBehavior, Extended
return parseInt(this.version().split('.')[0]);
}

osMajorVersion(): number {
return parseInt(this.uaParserResult.os.version.split('.')[0]);
}

name(): string {
return this.browser.name;
}
Expand Down Expand Up @@ -88,7 +96,10 @@ export default class DefaultBrowserBehavior implements BrowserBehavior, Extended
}

supportsCanvasCapturedStreamPlayback(): boolean {
return !this.isIOSSafari() && !this.isIOSChrome() && !this.isIOSFirefox();
return (
(!this.isIOSSafari() && !this.isIOSChrome() && !this.isIOSFirefox()) ||
this.osMajorVersion() >= DefaultBrowserBehavior.MIN_IOS_SUPPORT_CANVAS_STREAM_PLAYBACK
);
}

supportsBackgroundFilter(): boolean {
Expand Down
3 changes: 3 additions & 0 deletions test/backgroundprocessor/BackgroundBlurProcessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,9 @@ describe('BackgroundBlurProcessor', () => {
const supportedUserAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3865.75 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15',
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/107.0.5304.66 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/106.0 Mobile/15E148 Safari/605.1.15',
];
for (const supportedUserAgent of supportedUserAgents) {
setUserAgent(supportedUserAgent);
Expand Down
11 changes: 11 additions & 0 deletions test/browserbehavior/DefaultBrowserBehavior.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ describe('DefaultBrowserBehavior', () => {
mockBuilder.cleanup();
});

describe('construction', () => {
it('can be constructed without user agent', () => {
const userAgent = navigator.userAgent;
// @ts-ignore
delete navigator.userAgent;
new DefaultBrowserBehavior();
// @ts-ignore
navigator.userAgent = userAgent;
});
});

describe('platforms', () => {
it('can detect Firefox', () => {
setUserAgent(FIREFOX_MAC_USER_AGENT);
Expand Down
4 changes: 3 additions & 1 deletion test/task/CleanRestartedSessionTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as chai from 'chai';
import { NScaleVideoUplinkBandwidthPolicy } from '../../src';
import AudioVideoControllerState from '../../src/audiovideocontroller/AudioVideoControllerState';
import NoOpAudioVideoController from '../../src/audiovideocontroller/NoOpAudioVideoController';
import BrowserBehavior from '../../src/browserbehavior/BrowserBehavior';
import DefaultBrowserBehavior from '../../src/browserbehavior/DefaultBrowserBehavior';
import ConnectionHealthData from '../../src/connectionhealthpolicy/ConnectionHealthData';
import SignalingAndMetricsConnectionMonitor from '../../src/connectionmonitor/SignalingAndMetricsConnectionMonitor';
Expand Down Expand Up @@ -37,11 +38,12 @@ describe('CleanRestartedSessionTask', () => {
let domMockBuilder: DOMMockBuilder;
let domMockBehavior: DOMMockBehavior;
let task: Task;
const browserBehavior = new DefaultBrowserBehavior();
let browserBehavior: BrowserBehavior;

beforeEach(() => {
domMockBehavior = new DOMMockBehavior();
domMockBuilder = new DOMMockBuilder(domMockBehavior);
browserBehavior = new DefaultBrowserBehavior();
context = new AudioVideoControllerState();
context.audioVideoController = new NoOpAudioVideoController();
context.logger = context.audioVideoController.logger;
Expand Down
4 changes: 3 additions & 1 deletion test/task/CleanStoppedSessionTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import AudioVideoController from '../../src/audiovideocontroller/AudioVideoContr
import AudioVideoControllerState from '../../src/audiovideocontroller/AudioVideoControllerState';
import NoOpAudioVideoController from '../../src/audiovideocontroller/NoOpAudioVideoController';
import FullJitterBackoff from '../../src/backoff/FullJitterBackoff';
import BrowserBehavior from '../../src/browserbehavior/BrowserBehavior';
import DefaultBrowserBehavior from '../../src/browserbehavior/DefaultBrowserBehavior';
import ConnectionMonitor from '../../src/connectionmonitor/ConnectionMonitor';
import Logger from '../../src/logger/Logger';
Expand Down Expand Up @@ -40,10 +41,10 @@ describe('CleanStoppedSessionTask', () => {
const RECONNECT_SHORT_BACKOFF_MS = 1 * 1000;
const RECONNECT_LONG_BACKOFF_MS = 5 * 1000;
const behavior = new DOMMockBehavior();
const browserBehavior = new DefaultBrowserBehavior();

let context: AudioVideoControllerState;
let domMockBuilder: DOMMockBuilder | null = null;
let browserBehavior: BrowserBehavior;
let task: Task;
let webSocketAdapter: DefaultWebSocketAdapter;
let signalingClient: SignalingClient;
Expand All @@ -66,6 +67,7 @@ describe('CleanStoppedSessionTask', () => {

beforeEach(async () => {
domMockBuilder = new DOMMockBuilder(behavior);
browserBehavior = new DefaultBrowserBehavior();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a afterEach to set the browserBehavior to undefined. Not sure if this will keep stale objects when running unit tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for other tests included in this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think so as we initialize them every time to a new object. The old one should be garbage collected.

context = new AudioVideoControllerState();
context.audioVideoController = new NoOpAudioVideoController();
context.logger = context.audioVideoController.logger;
Expand Down
3 changes: 2 additions & 1 deletion test/task/CreatePeerConnectionTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('CreatePeerConnectionTask', () => {
let context: AudioVideoControllerState;
let domMockBuilder: DOMMockBuilder | null = null;
let task: Task;
const browser: BrowserBehavior = new DefaultBrowserBehavior();
let browser: BrowserBehavior;

function makeICEEvent(candidateStr: string | null): RTCPeerConnectionIceEvent {
let iceCandidate: RTCIceCandidate = null;
Expand All @@ -61,6 +61,7 @@ describe('CreatePeerConnectionTask', () => {
beforeEach(() => {
domMockBehavior = new DOMMockBehavior();
domMockBuilder = new DOMMockBuilder(domMockBehavior);
browser = new DefaultBrowserBehavior();

context = new AudioVideoControllerState();
context.audioVideoController = new NoOpAudioVideoController();
Expand Down
3 changes: 2 additions & 1 deletion test/task/CreateSDPTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ describe('CreateSDPTask', () => {
let context: AudioVideoControllerState;
let domMockBuilder: DOMMockBuilder;
let domMockBehavior: DOMMockBehavior;
const browser: BrowserBehavior = new DefaultBrowserBehavior();
let browser: BrowserBehavior;
let task: Task;

beforeEach(() => {
domMockBehavior = new DOMMockBehavior();
domMockBuilder = new DOMMockBuilder(domMockBehavior);
browser = new DefaultBrowserBehavior();
context = new AudioVideoControllerState();
context.audioVideoController = new NoOpAudioVideoController();
context.transceiverController = new DefaultTransceiverController(context.logger, browser);
Expand Down
3 changes: 2 additions & 1 deletion test/task/LeaveAndReceiveLeaveAckTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('LeaveAndReceiveLeaveAckTask', () => {
let signalingClient: SignalingClient;
let leaveAckBuffer: Uint8Array;
let request: SignalingClientConnectionRequest;
const browser: BrowserBehavior = new DefaultBrowserBehavior();
let browser: BrowserBehavior;

function makeLeaveAckFrame(): Uint8Array {
const frame = SdkLeaveAckFrame.create();
Expand All @@ -50,6 +50,7 @@ describe('LeaveAndReceiveLeaveAckTask', () => {

beforeEach(() => {
domMockBuilder = new DOMMockBuilder(behavior);
browser = new DefaultBrowserBehavior();
context = new AudioVideoControllerState();
context.audioVideoController = new NoOpAudioVideoController();
context.transceiverController = new DefaultTransceiverController(context.logger, browser);
Expand Down
3 changes: 2 additions & 1 deletion test/task/PromoteToPrimaryMeetingTask.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('PromoteToPrimaryMeetingTask', () => {
let signalingClient: SignalingClient;
let primaryMeetingJoinAck: Uint8Array;
let request: SignalingClientConnectionRequest;
const browser: BrowserBehavior = new DefaultBrowserBehavior();
let browser: BrowserBehavior;

function makePrimaryMeetingJoinAckFrame(errorStatus: number = undefined): Uint8Array {
const frame = SdkPrimaryMeetingJoinAckFrame.create();
Expand All @@ -61,6 +61,7 @@ describe('PromoteToPrimaryMeetingTask', () => {

beforeEach(() => {
domMockBuilder = new DOMMockBuilder(behavior);
browser = new DefaultBrowserBehavior();
context = new AudioVideoControllerState();
context.audioVideoController = new NoOpAudioVideoController();
context.transceiverController = new DefaultTransceiverController(context.logger, browser);
Expand Down