Skip to content

Commit

Permalink
Enable pagination in demo by default, without needing to use priority…
Browse files Browse the repository at this point in the history
… policy (#2880)
  • Loading branch information
hensmi-amazon authored Apr 19, 2024
1 parent a180b62 commit 6cca77b
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 65 deletions.
20 changes: 9 additions & 11 deletions demos/browser/app/meetingV2/meetingV2.html
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,7 @@ <h5 class="modal-title" id="additional-options-modal-label">Additional Options</
</div>
<div class="form-check" id='echo-reduction-checkbox' style="text-align: left; display: none;">
<input type="checkbox" id="echo-reduction-capability" class="form-check-input">
<label for="echo-reduction-capability" class="form-check-label">Use Echo Reduction (new meetings
only)</label>
<label for="echo-reduction-capability" class="form-check-label">Use Echo Reduction</label>
</div>
<div class="form-check" id="disable-audio-redundancy-checkbox" style="text-align: left; display: block;">
<input type="checkbox" id="disable-audio-redundancy" class="form-check-input">
Expand Down Expand Up @@ -213,6 +212,14 @@ <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>
<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>
<option value="4">4</option>
<option value="9">9</option>
<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
Expand All @@ -225,15 +232,6 @@ <h5 class="modal-title" id="additional-options-modal-label">Additional Options</
<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>
<label id="pagination-title" for="pagination-page-size" style="display: none; padding-top:5px">Paginate displayed video tiles</label>
<select id="pagination-page-size" class="form-select" style="width:100%; display: none;">
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25" selected>25</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
20 changes: 7 additions & 13 deletions demos/browser/app/meetingV2/meetingV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ import {
MeetingSessionCredentials,
POSTLogger,
VideoCodecCapability,
AllHighestVideoBandwidthPolicy,
} from 'amazon-chime-sdk-js';
import { Modal } from 'bootstrap';

import TestSound from './audio/TestSound';
import MeetingToast from './util/MeetingToast'; MeetingToast; // Make sure this file is included in webpack
import VideoTileCollection from './video/VideoTileCollection'
import VideoPreferenceManager from './video/VideoPreferenceManager';
import RemoteVideoManager from './video/RemoteVideoManager';
import CircularCut from './video/filters/CircularCut';
import EmojifyVideoFrameProcessor from './video/filters/EmojifyVideoFrameProcessor';
import SegmentationProcessor from './video/filters/SegmentationProcessor';
Expand Down Expand Up @@ -294,12 +295,12 @@ export class DemoMeetingApp
primaryMeetingSessionCredentials: MeetingSessionCredentials | undefined = undefined;
meetingSession: MeetingSession | null = null;
priorityBasedDownlinkPolicy: VideoPriorityBasedPolicy | null = null;
allHighestDownlinkPolicy: AllHighestVideoBandwidthPolicy | null = null;
audioVideo: AudioVideoFacade | null = null;
deviceController: DefaultDeviceController | undefined = undefined;
canStartLocalVideo: boolean = true;
defaultBrowserBehavior: DefaultBrowserBehavior = new DefaultBrowserBehavior();
videoTileCollection: VideoTileCollection | undefined = undefined;
videoPreferenceManager: VideoPreferenceManager | undefined = undefined;

// eslint-disable-next-line
roster: Roster = new Roster();
Expand Down Expand Up @@ -667,25 +668,15 @@ export class DemoMeetingApp
const serverSideNetworkAdaption = document.getElementById(
'server-side-network-adaption'
) as HTMLSelectElement;
const paginationPageSize = document.getElementById(
'pagination-page-size'
) as HTMLElement;
const paginationTitle = document.getElementById(
'pagination-title'
) as HTMLElement;
const serverSideNetworkAdaptionTitle = document.getElementById(
'server-side-network-adaption-title'
) as HTMLElement;

if (this.usePriorityBasedDownlinkPolicy) {
serverSideNetworkAdaption.style.display = 'block';
paginationPageSize.style.display = 'block';
paginationTitle.style.display = 'block';
serverSideNetworkAdaptionTitle.style.display = 'block';
} else {
serverSideNetworkAdaption.style.display = 'none';
paginationTitle.style.display = 'none';
paginationPageSize.style.display = 'none';
serverSideNetworkAdaptionTitle.style.display = 'none';
}
});
Expand Down Expand Up @@ -1886,6 +1877,9 @@ export class DemoMeetingApp
this.priorityBasedDownlinkPolicy = new VideoPriorityBasedPolicy(this.meetingLogger, this.videoPriorityBasedPolicyConfig);
configuration.videoDownlinkBandwidthPolicy = this.priorityBasedDownlinkPolicy;
this.priorityBasedDownlinkPolicy.addObserver(this);
} else {
this.allHighestDownlinkPolicy = new AllHighestVideoBandwidthPolicy(configuration.credentials.attendeeId);
configuration.videoDownlinkBandwidthPolicy = this.allHighestDownlinkPolicy;
}
configuration.disablePeriodicKeyframeRequestOnContentSender = this.disablePeriodicKeyframeRequestOnContentSender;

Expand Down Expand Up @@ -1945,7 +1939,7 @@ export class DemoMeetingApp
let paginationPageSize = parseInt((document.getElementById('pagination-page-size') as HTMLSelectElement).value)
this.videoTileCollection = new VideoTileCollection(this.audioVideo,
this.meetingLogger,
this.usePriorityBasedDownlinkPolicy ? new VideoPreferenceManager(this.meetingLogger, this.priorityBasedDownlinkPolicy) : undefined,
new RemoteVideoManager(this.meetingLogger, this.usePriorityBasedDownlinkPolicy ? this.priorityBasedDownlinkPolicy : this.allHighestDownlinkPolicy),
paginationPageSize)
this.audioVideo.addObserver(this.videoTileCollection);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,36 @@ import {
VideoPreferences,
VideoQualityAdaptationPreference,
VideoPriorityBasedPolicy,
VideoSource
VideoSource,
AllHighestVideoBandwidthPolicy,
Attendee
} from 'amazon-chime-sdk-js';

export default class VideoPreferenceManager {
export default class RemoteVideoManager {
static readonly DefaultVideoTilePriority: number = 5;
static readonly DefaultVideoTileTargetDisplaySize: TargetDisplaySize = TargetDisplaySize.Maximum;

attendeeIdToVideoPreference = new Map<string, VideoPreference>();
priorityBasedDownlinkPolicy: VideoPriorityBasedPolicy | null = null;
private attendeeIdToVideoPreference = new Map<string, VideoPreference>();

_visibleAttendees = new Array<string>();
public set visibleAttendees(value: Array<string>) {
this._visibleAttendees = value;
this.updateDownlinkPreference();
}

constructor(private logger: Logger, private downlinkPolicy: VideoPriorityBasedPolicy) {}
constructor(private logger: Logger, private downlinkPolicy: VideoPriorityBasedPolicy | AllHighestVideoBandwidthPolicy) {
if (this.downlinkPolicy instanceof AllHighestVideoBandwidthPolicy) {
this.downlinkPolicy.chooseRemoteVideoSources([]);
}
}

ensureDefaultPreferences(videoSources: VideoSource[]): void {
this.logger.info(`Available remote video sources changed: ${JSON.stringify(videoSources)}`);
for (const source of videoSources) {
if (!this.attendeeIdToVideoPreference.has(source.attendee.attendeeId)) {
this.attendeeIdToVideoPreference.set(
source.attendee.attendeeId,
new VideoPreference(source.attendee.attendeeId, VideoPreferenceManager.DefaultVideoTilePriority, VideoPreferenceManager.DefaultVideoTileTargetDisplaySize))
new VideoPreference(source.attendee.attendeeId, RemoteVideoManager.DefaultVideoTilePriority, RemoteVideoManager.DefaultVideoTileTargetDisplaySize))
}
}
}
Expand All @@ -41,7 +46,7 @@ export default class VideoPreferenceManager {
if (this.attendeeIdToVideoPreference.has(attendeeId)) {
this.attendeeIdToVideoPreference.get(attendeeId).targetSize = targetDisplaySize;
} else {
this.attendeeIdToVideoPreference.set(attendeeId, new VideoPreference(attendeeId, VideoPreferenceManager.DefaultVideoTilePriority, targetDisplaySize));
this.attendeeIdToVideoPreference.set(attendeeId, new VideoPreference(attendeeId, RemoteVideoManager.DefaultVideoTilePriority, targetDisplaySize));
}
this.updateDownlinkPreference();
}
Expand All @@ -50,7 +55,7 @@ export default class VideoPreferenceManager {
if (this.attendeeIdToVideoPreference.has(attendeeId)) {
this.attendeeIdToVideoPreference.get(attendeeId).priority = priority
} else {
this.attendeeIdToVideoPreference.set(attendeeId, new VideoPreference(attendeeId, priority, VideoPreferenceManager.DefaultVideoTileTargetDisplaySize));
this.attendeeIdToVideoPreference.set(attendeeId, new VideoPreference(attendeeId, priority, RemoteVideoManager.DefaultVideoTileTargetDisplaySize));
}
this.updateDownlinkPreference();
}
Expand All @@ -60,24 +65,45 @@ export default class VideoPreferenceManager {
this.attendeeIdToVideoPreference.get(attendeeId).degradationPreference = preference
} else {
this.attendeeIdToVideoPreference.set(attendeeId, new VideoPreference(
attendeeId, VideoPreferenceManager.DefaultVideoTilePriority, VideoPreferenceManager.DefaultVideoTileTargetDisplaySize, preference));
attendeeId, RemoteVideoManager.DefaultVideoTilePriority, RemoteVideoManager.DefaultVideoTileTargetDisplaySize, preference));
}
this.updateDownlinkPreference();
}

supportsRemoteVideoPreferences(): boolean {
return (this.downlinkPolicy instanceof VideoPriorityBasedPolicy);
}

private updateDownlinkPreference(): void {
if (this.attendeeIdToVideoPreference.size === 0) {
// Preserve default behavior if no preferences have been set yet
this.logger.info('No video preferences set yet, not updating');
return;
}

const videoPreferences = VideoPreferences.prepare();
for (const [attendeeId, preference] of this.attendeeIdToVideoPreference.entries()) {
if (this._visibleAttendees.includes(attendeeId)) {
videoPreferences.add(preference);
}
if (this.downlinkPolicy instanceof VideoPriorityBasedPolicy) {
const videoPreferences = VideoPreferences.prepare();
for (const [attendeeId, preference] of this.attendeeIdToVideoPreference.entries()) {
if (this._visibleAttendees.includes(attendeeId)) {
videoPreferences.add(preference);
}
}
this.downlinkPolicy.chooseRemoteVideoSources(videoPreferences.build());
} else {
// Just convert this list to the simpler 'VideoSource' class used by all highest policy
let videoSources: VideoSource[] = [];
for (const attendeeId of this.attendeeIdToVideoPreference.keys()) {
if (!this._visibleAttendees.includes(attendeeId)) {
continue;
}

let videoSource = new VideoSource();
let attendee = new Attendee();
attendee.attendeeId = attendeeId;
videoSource.attendee = attendee;
videoSources.push(videoSource);
}
this.downlinkPolicy.chooseRemoteVideoSources(videoSources);
}
this.downlinkPolicy.chooseRemoteVideoSources(videoPreferences.build());
}
}
42 changes: 16 additions & 26 deletions demos/browser/app/meetingV2/video/VideoTileCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
VideoTileState,
} from 'amazon-chime-sdk-js';

import VideoPreferenceManager from './VideoPreferenceManager';
import RemoteVideoManager from './RemoteVideoManager';
import PaginationManager from './PaginationManager';
import { DemoVideoTile } from './VideoTile'; DemoVideoTile; // Make sure this file is included in webpack

Expand Down Expand Up @@ -129,29 +129,24 @@ export default class VideoTileCollection implements AudioVideoObserver {

constructor(private videoTileController: VideoTileControllerFacade,
private logger: Logger,
private videoPreferenceManager?: VideoPreferenceManager,
pageSize?: number) {
private remoteVideoManager: RemoteVideoManager,
private pageSize: number) {
this.setupVideoTiles();

if (this.videoPreferenceManager === undefined) {
if (!this.remoteVideoManager.supportsRemoteVideoPreferences()) {
// Don't show priority related configuration if we don't support it
for (let i = 0; i <= TileOrganizer.MaxTiles; i++) {
this.tileIndexToDemoVideoTile.get(i).showRemoteVideoPreferences = false;
}
} else {
// Pagination is only possible with priority based policy
this.pagination = new PaginationManager<string>(pageSize);
document.getElementById('video-paginate-left').addEventListener('click', (event: Event) => { this.paginateLeft() });
document.getElementById('video-paginate-right').addEventListener('click', (event: Event) => { this.paginateRight() });
this.updatePaginatedVisibleTiles();
}

this.pagination = new PaginationManager<string>(this.pageSize);
document.getElementById('video-paginate-left').addEventListener('click', (event: Event) => { this.paginateLeft() });
document.getElementById('video-paginate-right').addEventListener('click', (event: Event) => { this.paginateRight() });
this.updatePaginatedVisibleTiles();
}

remoteVideoSourcesDidChange(videoSources: VideoSource[]): void {
if (this.videoPreferenceManager === undefined) {
return;
}

// Add these sources to the pagination list
for (const source of videoSources) {
this.pagination.add(source.attendee.attendeeId);
Expand All @@ -161,7 +156,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
});

// Update the preference manager explicitly as it needs to add default preferences
this.videoPreferenceManager.ensureDefaultPreferences(videoSources);
this.remoteVideoManager.ensureDefaultPreferences(videoSources);
this.updatePaginatedVisibleTiles();
}

Expand All @@ -181,7 +176,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
demoVideoTile.pauseButtonElement.addEventListener('click', this.tileIndexToPauseEventListener[tileIndex]);
}

if (this.videoPreferenceManager !== undefined && !tileState.localTile) { // No current config possible on local tile
if (this.remoteVideoManager.supportsRemoteVideoPreferences() && !tileState.localTile) { // No current config possible on local tile
this.logger.info('adding config listeners for tileIndex ' + tileIndex);
demoVideoTile.targetResolutionRadioElement.removeEventListener('click', this.tileIndexToTargetResolutionEventListener[tileIndex]);
this.tileIndexToTargetResolutionEventListener[tileIndex] = this.createTargetResolutionListener(tileState);
Expand Down Expand Up @@ -403,7 +398,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
}

private updateLayout(): void {
this.tileArea.className = `v-grid size-${this.videoTileCount()}`;
this.tileArea.className = `v-grid size-${this.pagination.currentPage().length}`;

const localTileId = this.localTileId();
const activeTile = this.activeTileId();
Expand All @@ -414,11 +409,6 @@ export default class VideoTileCollection implements AudioVideoObserver {
}
}

private videoTileCount(): number {
return (
this.tileOrganizer.remoteTileCount + (this.videoTileController.hasStartedLocalVideoTile() ? 1 : 0)
);
}

private localTileId(): number | null {
return this.videoTileController.hasStartedLocalVideoTile()
Expand Down Expand Up @@ -446,7 +436,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
// Refresh visible attendees incase ones have been added
let attendeesToShow = this.pagination.currentPage();
this.logger.info(`Showing current page ${JSON.stringify(attendeesToShow)}`)
this.videoPreferenceManager.visibleAttendees = attendeesToShow;
this.remoteVideoManager.visibleAttendees = attendeesToShow;

// We need to manually control visibility of paused tiles anyways so we just do
// everything here, even though the preference manager adding/removing will
Expand Down Expand Up @@ -475,7 +465,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
const value = (event.target as HTMLInputElement).value;
this.logger.info(`target resolution changed for: ${attendeeId} to ${value}`);
const targetDisplaySize = ConfigLevelToTargetDisplaySize[value as ConfigLevel];
this.videoPreferenceManager.setAttendeeTargetDisplaySize(attendeeId, targetDisplaySize);
this.remoteVideoManager.setAttendeeTargetDisplaySize(attendeeId, targetDisplaySize);
}
}

Expand All @@ -489,7 +479,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
const value = (event.target as HTMLInputElement).value;
this.logger.info(`priority changed for: ${attendeeId} to ${value}`);
const priority = ConfigLevelToVideoPriority[value as ConfigLevel];
this.videoPreferenceManager.setAttendeePriority(attendeeId, priority);
this.remoteVideoManager.setAttendeePriority(attendeeId, priority);
}
}

Expand All @@ -503,7 +493,7 @@ export default class VideoTileCollection implements AudioVideoObserver {
const value = (event.target as HTMLInputElement).value;
const preference = StringToVideoQualityAdaptationPreference[value as DegrationPreferenceString];
this.logger.info(`degradation preference changed for: ${attendeeId} to ${preference}`);
this.videoPreferenceManager.setAttendeeDegradationPreference(attendeeId, preference);
this.remoteVideoManager.setAttendeeDegradationPreference(attendeeId, preference);
}
}

Expand Down

0 comments on commit 6cca77b

Please sign in to comment.