Skip to content

Commit

Permalink
enable screen share simulcast by default (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasIO authored Feb 22, 2022
1 parent cd32c2b commit faa0ad5
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/room/participant/LocalParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import LocalVideoTrack, { videoLayersFromEncodings } from '../track/LocalVideoTr
import {
CreateLocalTracksOptions,
ScreenShareCaptureOptions,
TrackPublishOptions, VideoCodec, VideoPresets,
ScreenSharePresets,
TrackPublishOptions, VideoCodec,
} from '../track/options';
import { Track } from '../track/Track';
import { constraintsForOptions, mergeDefaultOptions } from '../track/utils';
Expand Down Expand Up @@ -272,7 +273,7 @@ export default class LocalParticipant extends Participant {
options = {};
}
if (options.resolution === undefined) {
options.resolution = VideoPresets.fhd.resolution;
options.resolution = ScreenSharePresets.h720fps15.resolution;
}

let videoConstraints: MediaTrackConstraints | boolean = true;
Expand Down
17 changes: 16 additions & 1 deletion src/room/participant/publishUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { VideoPreset, VideoPresets, VideoPresets43 } from '../track/options';
import {
ScreenSharePresets, VideoPreset, VideoPresets, VideoPresets43,
} from '../track/options';
import {
computeDefaultScreenShareSimulcastPresets,
computeVideoEncodings,
determineAppropriateEncoding,
presets169,
Expand Down Expand Up @@ -128,3 +131,15 @@ describe('customSimulcastLayers', () => {
expect(sortedPresets[2].encoding.maxFramerate).toBe(20);
});
});

describe('screenShareSimulcastDefaults', () => {
it('computes appropriate bitrate from original preset', () => {
const defaultSimulcastLayers = computeDefaultScreenShareSimulcastPresets(
ScreenSharePresets.h720fps15,
);
expect(defaultSimulcastLayers[0].width).toBe(640);
expect(defaultSimulcastLayers[0].height).toBe(360);
expect(defaultSimulcastLayers[0].encoding.maxFramerate).toBe(3);
expect(defaultSimulcastLayers[0].encoding.maxBitrate).toBe(150_000);
});
});
31 changes: 21 additions & 10 deletions src/room/participant/publishUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ export const defaultSimulcastPresets43 = [
VideoPresets43.h360,
];

/* @internal */
export const computeDefaultScreenShareSimulcastPresets = (fromPreset: VideoPreset) => {
const layers = [{ scaleResolutionDownBy: 2, fps: 3 }];
return layers.map((t) => new VideoPreset(
Math.floor(fromPreset.width / t.scaleResolutionDownBy),
Math.floor(fromPreset.height / t.scaleResolutionDownBy),
Math.max(150_000, Math.floor(fromPreset.encoding.maxBitrate
/ (t.scaleResolutionDownBy ** 2 * ((fromPreset.encoding.maxFramerate ?? 30) / t.fps)))),
t.fps,
));
};

const videoRids = ['q', 'h', 'f'];

/* @internal */
Expand All @@ -59,9 +71,7 @@ export function computeVideoEncodings(
if (isScreenShare) {
videoEncoding = options?.screenShareEncoding;
}
// only use simulcast for screenshares if the simulcast layers are provided via config
const useSimulcast = (!isScreenShare || options?.screenShareSimulcastLayers)
&& options?.simulcast;
const useSimulcast = options?.simulcast;

if ((!videoEncoding && !useSimulcast) || !width || !height) {
// when we aren't simulcasting, will need to return a single encoding without
Expand All @@ -78,22 +88,22 @@ export function computeVideoEncodings(
if (!useSimulcast) {
return [videoEncoding];
}
const original = new VideoPreset(
width, height, videoEncoding.maxBitrate, videoEncoding.maxFramerate,
);
let presets: Array<VideoPreset> = [];
if (isScreenShare) {
presets = sortPresets(options?.screenShareSimulcastLayers)
?? defaultSimulcastLayers(isScreenShare, width, height);
?? defaultSimulcastLayers(isScreenShare, original);
} else {
presets = sortPresets(options?.videoSimulcastLayers)
?? defaultSimulcastLayers(isScreenShare, width, height);
?? defaultSimulcastLayers(isScreenShare, original);
}
let midPreset: VideoPreset | undefined;
const lowPreset = presets[0];
if (presets.length > 1) {
[, midPreset] = presets;
}
const original = new VideoPreset(
width, height, videoEncoding.maxBitrate, videoEncoding.maxFramerate,
);

// NOTE:
// 1. Ordering of these encodings is important. Chrome seems
Expand Down Expand Up @@ -159,11 +169,12 @@ export function presetsForResolution(

/* @internal */
export function defaultSimulcastLayers(
isScreenShare: boolean, width: number, height: number,
isScreenShare: boolean, original: VideoPreset,
): VideoPreset[] {
if (isScreenShare) {
return [];
return computeDefaultScreenShareSimulcastPresets(original);
}
const { width, height } = original;
const aspect = width > height ? width / height : height / width;
if (Math.abs(aspect - 16.0 / 9) < Math.abs(aspect - 4.0 / 3)) {
return defaultSimulcastPresets169;
Expand Down
4 changes: 2 additions & 2 deletions src/room/track/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const publishDefaults: TrackPublishDefaults = {
audioBitrate: AudioPresets.speech.maxBitrate,
dtx: true,
simulcast: true,
screenShareEncoding: ScreenSharePresets.hd_15.encoding,
screenShareEncoding: ScreenSharePresets.h720fps15.encoding,
stopMicTrackOnMute: false,
};

Expand All @@ -19,5 +19,5 @@ export const audioDefaults: AudioCaptureOptions = {
};

export const videoDefaults: VideoCaptureOptions = {
resolution: VideoPresets.qhd.resolution,
resolution: VideoPresets.h540.resolution,
};

0 comments on commit faa0ad5

Please sign in to comment.