Skip to content

Commit

Permalink
Make server side network adaptation the default when creating `VideoP…
Browse files Browse the repository at this point in the history
…riorityBasedPolicy` (#2889)
  • Loading branch information
hensmi-amazon authored May 8, 2024
1 parent d1f502d commit 5354ada
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 125 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Avoid subscribes when simulcast is enabled but not currently sending, or when using server side network adaptation.
- Made server side network adaptation the default when creating `VideoPriorityBasedPolicy`.

### Fixed

Expand Down
16 changes: 4 additions & 12 deletions demos/browser/app/meetingV2/meetingV2.html
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ <h5 class="modal-title" id="additional-options-modal-label">Additional Options</
<input type="checkbox" id="svc" class="form-check-input">
<label for="svc" class="form-check-label">Enable SVC for Chrome</label>
</div>
<div class="form-check" style="text-align: left;">
<input type="checkbox" id="priority-downlink-policy" class="form-check-input">
<label for="priority-downlink-policy" class="form-check-label">Enable remote video quality adaptation</label>
</div>
<label id="pagination-title" for="pagination-page-size" style="padding-top:5px">Paginate displayed video tiles</label>
<select id="pagination-page-size" class="form-select" style="width:100%;">
<option value="1">1</option>
Expand All @@ -220,18 +224,6 @@ <h5 class="modal-title" id="additional-options-modal-label">Additional Options</
<option value="16">16</option>
<option value="25" selected>25</option>
</select>
<div class="form-check" style="text-align: left;">
<input type="checkbox" id="priority-downlink-policy" class="form-check-input">
<label for="priority-downlink-policy" class="form-check-label">Use Priority-Based Downlink
Policy</label>
</div>
<label id="server-side-network-adaption-title" for="server-side-network-adaption" style="display: none; padding-top:5px">Server Side Network Adaption</label>
<select id="server-side-network-adaption" class="form-select" style="width:100%; display: none;">
<option value="default">Default</option>
<option value="none">None (Deprecated)</option>
<option value="enable-bandwidth-probing">Enable Bandwidth Probing (Deprecated)</option>
<option value="enable-bandwidth-probing-and-video-adaption" selected>Enable Bandwidth Probing and Video Quality Adaption</option>
</select>
<div class="form-check" style="text-align: left;">
<input type="checkbox" checked id="preconnect" class="form-check-input">
<label for="preconnect" class="form-check-label">Open signaling connection early</label>
Expand Down
38 changes: 3 additions & 35 deletions demos/browser/app/meetingV2/meetingV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import {
NoOpVideoFrameProcessor,
VideoFxConfig,
RemovableAnalyserNode,
ServerSideNetworkAdaption,
SimulcastLayers,
Transcript,
TranscriptEvent,
Expand All @@ -63,7 +62,6 @@ import {
VideoFrameProcessor,
VideoInputDevice,
VideoPriorityBasedPolicy,
VideoPriorityBasedPolicyConfig,
VideoQualitySettings,
VoiceFocusDeviceTransformer,
VoiceFocusModelComplexity,
Expand Down Expand Up @@ -347,7 +345,6 @@ export class DemoMeetingApp
enableSimulcast = false;
enableSVC = false;
usePriorityBasedDownlinkPolicy = false;
videoPriorityBasedPolicyConfig = new VideoPriorityBasedPolicyConfig;
enablePin = false;
echoReductionCapability = false;
usingStereoMusicAudioProfile = false;
Expand Down Expand Up @@ -664,21 +661,6 @@ export class DemoMeetingApp

document.getElementById('priority-downlink-policy').addEventListener('change', e => {
this.usePriorityBasedDownlinkPolicy = (document.getElementById('priority-downlink-policy') as HTMLInputElement).checked;

const serverSideNetworkAdaption = document.getElementById(
'server-side-network-adaption'
) as HTMLSelectElement;
const serverSideNetworkAdaptionTitle = document.getElementById(
'server-side-network-adaption-title'
) as HTMLElement;

if (this.usePriorityBasedDownlinkPolicy) {
serverSideNetworkAdaption.style.display = 'block';
serverSideNetworkAdaptionTitle.style.display = 'block';
} else {
serverSideNetworkAdaption.style.display = 'none';
serverSideNetworkAdaptionTitle.style.display = 'none';
}
});

const echoReductionCheckbox = (document.getElementById('echo-reduction-checkbox') as HTMLInputElement);
Expand Down Expand Up @@ -1859,22 +1841,7 @@ export class DemoMeetingApp
configuration.enableSimulcastForUnifiedPlanChromiumBasedBrowsers = this.enableSimulcast;
configuration.enableSVC = this.enableSVC;
if (this.usePriorityBasedDownlinkPolicy) {
const serverSideNetworkAdaptionDropDown = document.getElementById('server-side-network-adaption') as HTMLSelectElement;
switch (serverSideNetworkAdaptionDropDown.value) {
case 'default':
this.videoPriorityBasedPolicyConfig.serverSideNetworkAdaption = ServerSideNetworkAdaption.Default;
break;
case 'none':
this.videoPriorityBasedPolicyConfig.serverSideNetworkAdaption = ServerSideNetworkAdaption.None;
break;
case 'enable-bandwidth-probing':
this.videoPriorityBasedPolicyConfig.serverSideNetworkAdaption = ServerSideNetworkAdaption.BandwidthProbing;
break;
case 'enable-bandwidth-probing-and-video-adaption':
this.videoPriorityBasedPolicyConfig.serverSideNetworkAdaption = ServerSideNetworkAdaption.BandwidthProbingAndRemoteVideoQualityAdaption;
break;
}
this.priorityBasedDownlinkPolicy = new VideoPriorityBasedPolicy(this.meetingLogger, this.videoPriorityBasedPolicyConfig);
this.priorityBasedDownlinkPolicy = new VideoPriorityBasedPolicy(this.meetingLogger);
configuration.videoDownlinkBandwidthPolicy = this.priorityBasedDownlinkPolicy;
this.priorityBasedDownlinkPolicy.addObserver(this);
} else {
Expand Down Expand Up @@ -1940,7 +1907,8 @@ export class DemoMeetingApp
this.videoTileCollection = new VideoTileCollection(this.audioVideo,
this.meetingLogger,
new RemoteVideoManager(this.meetingLogger, this.usePriorityBasedDownlinkPolicy ? this.priorityBasedDownlinkPolicy : this.allHighestDownlinkPolicy),
paginationPageSize)
paginationPageSize,
this.meetingSession.configuration.credentials.attendeeId)
this.audioVideo.addObserver(this.videoTileCollection);

this.contentShare = new ContentShareManager(this.meetingLogger, this.audioVideo, this.usingStereoMusicAudioProfile);
Expand Down
16 changes: 10 additions & 6 deletions demos/browser/app/meetingV2/video/PaginationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default class PaginationManager<Type> {
private currentPageStart: number = 0;

private all = new Array<Type>();

constructor(private pageSize: number) {}

currentPage(): Array<Type> {
Expand All @@ -20,23 +20,25 @@ export default class PaginationManager<Type> {
}

remove(toRemove: Type) {
this.all.splice(this.all.indexOf(toRemove));
if (this.all.includes(toRemove)) {
this.all.splice(this.all.indexOf(toRemove), 1);
}
}

removeIf(toRemoveFn: (value: Type) => boolean) {
const index = this.all.findIndex(toRemoveFn);
if (index === -1) {
return;
}
this.all.splice(index,1);
this.all.splice(index, 1);
}

hasNextPage(): boolean {
return this.currentPageStart + this.pageSize < this.all.length;
}

nextPage(): void {
if (!this.hasNextPage) {
if (!this.hasNextPage()) {
return;
}
this.currentPageStart += this.pageSize;
Expand All @@ -47,6 +49,8 @@ export default class PaginationManager<Type> {
}

previousPage(): void {
this.currentPageStart -= this.pageSize;
if (this.hasPreviousPage()) {
this.currentPageStart -= this.pageSize;
}
}
}
}
26 changes: 19 additions & 7 deletions demos/browser/app/meetingV2/video/VideoTileCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ export default class VideoTileCollection implements AudioVideoObserver {
constructor(private videoTileController: VideoTileControllerFacade,
private logger: Logger,
private remoteVideoManager: RemoteVideoManager,
private pageSize: number) {
private pageSize: number,
private localAttendeeId: string) {
this.setupVideoTiles();

if (!this.remoteVideoManager.supportsRemoteVideoPreferences()) {
Expand All @@ -151,8 +152,9 @@ export default class VideoTileCollection implements AudioVideoObserver {
for (const source of videoSources) {
this.pagination.add(source.attendee.attendeeId);
}
const localTileId = this.localTileId()
this.pagination.removeIf((value: string) => {
return !videoSources.some((source: VideoSource) => source.attendee.attendeeId === value)
return !videoSources.some((source: VideoSource) => source.attendee.attendeeId === value) && (localTileId && this.tileIdToAttendeeId[localTileId] !== value);
});

// Update the preference manager explicitly as it needs to add default preferences
Expand All @@ -161,7 +163,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
}

videoTileDidUpdate(tileState: VideoTileState): void {
console.log(`video tile updated: ${JSON.stringify(tileState, null, ' ')}`);
this.logger.info(`video tile updated: ${JSON.stringify(tileState, null, ' ')}`);
if (!tileState.boundAttendeeId) {
return;
}
Expand Down Expand Up @@ -208,12 +210,20 @@ export default class VideoTileCollection implements AudioVideoObserver {
}
demoVideoTile.attendeeId = tileState.boundAttendeeId;

// We need to add local video or content to pagination from tile updates
const shouldUpdatePagination = tileState.localTile || (tileState.isContent && tileState.boundAttendeeId.startsWith(this.localAttendeeId));
if (tileState.boundVideoStream) {
demoVideoTile.show(tileState.isContent);
if (shouldUpdatePagination) {
this.pagination.add(tileState.boundAttendeeId);
}
} else {
// Hide non-active tiles that aren't just paused
demoVideoTile.hide();
if (shouldUpdatePagination) {
this.pagination.remove(tileState.boundAttendeeId);
}
}
this.updatePaginatedVisibleTiles();
this.updateLayout();
this.layoutFeaturedTile();
}
Expand Down Expand Up @@ -363,6 +373,9 @@ export default class VideoTileCollection implements AudioVideoObserver {
for (const tile of this.videoTileController.getAllVideoTiles()) {
const state = tile.state();
if (state.isContent) {
if (state.boundAttendeeId.startsWith(this.localAttendeeId) && !this.pagination.currentPage().includes(state.boundAttendeeId)) {
return null;
}
return state.tileId;
}
}
Expand Down Expand Up @@ -441,11 +454,10 @@ export default class VideoTileCollection implements AudioVideoObserver {
// We need to manually control visibility of paused tiles anyways so we just do
// everything here, even though the preference manager adding/removing will
// result in tile callbacks as well.
for (let [index, videoTile] of this.tileIndexToDemoVideoTile.entries()) {
for (let videoTile of this.tileIndexToDemoVideoTile.values()) {
if (attendeesToShow.includes(videoTile.attendeeId)) {
videoTile.show(false);
} else if (index !== VideoTileCollection.LocalVideoTileIndex
&& this.tileIndexToTileId[index] !== this.findContentTileId()) { // Always show local tile and content
} else {
videoTile.hide();
}
}
Expand Down
Loading

0 comments on commit 5354ada

Please sign in to comment.