How to use transceivers method in wpt

Best JavaScript code snippet using wpt

DefaultTransceiverController.test.ts

Source:DefaultTransceiverController.test.ts Github

copy

Full Screen

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.2// SPDX-License-Identifier: Apache-2.03import * as chai from 'chai';4import BrowserBehavior from '../../src/browserbehavior/BrowserBehavior';5import DefaultBrowserBehavior from '../../src/browserbehavior/DefaultBrowserBehavior';6import LogLevel from '../../src/logger/LogLevel';7import NoOpLogger from '../../src/logger/NoOpLogger';8import TimeoutScheduler from '../../src/scheduler/TimeoutScheduler';9import {10 SdkIndexFrame,11 SdkStreamDescriptor,12 SdkStreamMediaType,13 SdkSubscribeAckFrame,14 SdkTrackMapping,15} from '../../src/signalingprotocol/SignalingProtocol.js';16import DefaultTransceiverController from '../../src/transceivercontroller/DefaultTransceiverController';17import TransceiverController from '../../src/transceivercontroller/TransceiverController';18import DefaultVideoStreamIdSet from '../../src/videostreamidset/DefaultVideoStreamIdSet';19import VideoStreamIdSet from '../../src/videostreamidset/VideoStreamIdSet';20import DefaultVideoStreamIndex from '../../src/videostreamindex/DefaultVideoStreamIndex';21import DOMMockBehavior from '../dommock/DOMMockBehavior';22import DOMMockBuilder from '../dommock/DOMMockBuilder';23describe('DefaultTransceiverController', () => {24 const expect: Chai.ExpectStatic = chai.expect;25 const logger = new NoOpLogger(LogLevel.DEBUG);26 const domMockBehavior: DOMMockBehavior = new DOMMockBehavior();27 let tc: TransceiverController;28 let domMockBuilder: DOMMockBuilder;29 let browser: BrowserBehavior;30 beforeEach(() => {31 domMockBehavior.browserName = 'firefox';32 domMockBuilder = new DOMMockBuilder(domMockBehavior);33 browser = new DefaultBrowserBehavior();34 tc = new DefaultTransceiverController(logger, browser);35 });36 afterEach(() => {37 tc = new DefaultTransceiverController(logger, browser);38 domMockBuilder.cleanup();39 });40 describe('construction', () => {41 it('can be constructed', () => {42 expect(tc).to.not.equal(null);43 });44 });45 describe('useTransceivers', () => {46 it('can set peer connection and reset', () => {47 expect(tc.useTransceivers()).to.equal(false);48 const peer: RTCPeerConnection = new RTCPeerConnection();49 tc.setPeer(peer);50 expect(tc.useTransceivers()).to.equal(true);51 tc.reset();52 expect(tc.useTransceivers()).to.equal(false);53 });54 });55 describe('setupLocalTransceivers', () => {56 it('can not set up transceivers if peer connection is not set', () => {57 const peer: RTCPeerConnection = new RTCPeerConnection();58 tc.setupLocalTransceivers();59 expect(peer.getTransceivers().length).to.equal(0);60 });61 it('can set up transceivers once', () => {62 const peer: RTCPeerConnection = new RTCPeerConnection();63 tc.setPeer(peer);64 expect(peer.getTransceivers().length).to.equal(0);65 tc.setupLocalTransceivers();66 const transceivers = peer.getTransceivers();67 expect(transceivers.length).to.equal(2);68 const audioTransceiver = transceivers[0];69 expect(audioTransceiver.direction).to.equal('inactive');70 expect(audioTransceiver.receiver.track.kind).to.equal('audio');71 expect(audioTransceiver.sender.track.kind).to.equal('audio');72 const videoTransceiver = transceivers[1];73 expect(videoTransceiver.direction).to.equal('inactive');74 expect(videoTransceiver.receiver.track.kind).to.equal('video');75 expect(videoTransceiver.sender.track.kind).to.equal('video');76 tc.setupLocalTransceivers();77 expect(peer.getTransceivers()[0]).to.equal(audioTransceiver);78 expect(peer.getTransceivers()[1]).to.equal(videoTransceiver);79 });80 });81 describe('hasVideoInput', () => {82 it('return false if video input doesnt exist', () => {83 const peer: RTCPeerConnection = new RTCPeerConnection();84 tc.setPeer(peer);85 tc.setupLocalTransceivers();86 expect(tc.hasVideoInput()).to.equal(false);87 });88 it('return true if video input exists', done => {89 const peer: RTCPeerConnection = new RTCPeerConnection();90 tc.setPeer(peer);91 tc.setupLocalTransceivers();92 const newVideoTrack = new MediaStreamTrack();93 tc.setVideoInput(newVideoTrack);94 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {95 expect(tc.hasVideoInput()).to.equal(true);96 done();97 });98 });99 });100 describe('trackIsVideoInput', () => {101 it('can check whether the given track is a video input', () => {102 const peer: RTCPeerConnection = new RTCPeerConnection();103 tc.setPeer(peer);104 tc.setupLocalTransceivers();105 const audioTrack = peer.getTransceivers()[0].receiver.track;106 expect(tc.trackIsVideoInput(audioTrack)).to.equal(false);107 const videoTrack = peer.getTransceivers()[1].receiver.track;108 expect(tc.trackIsVideoInput(videoTrack)).to.equal(true);109 });110 it('can not check if it has reset transceivers', () => {111 const peer: RTCPeerConnection = new RTCPeerConnection();112 tc.setPeer(peer);113 tc.setupLocalTransceivers();114 const videoTrack = peer.getTransceivers()[1].receiver.track;115 tc.reset();116 expect(tc.trackIsVideoInput(videoTrack)).to.equal(false);117 });118 });119 describe('setAudioInput', () => {120 it('can set the audio track to null', done => {121 const peer: RTCPeerConnection = new RTCPeerConnection();122 tc.setPeer(peer);123 tc.setupLocalTransceivers();124 tc.setAudioInput(null);125 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {126 const audioTransceiver = peer.getTransceivers()[0];127 expect(audioTransceiver.sender.track).to.equal(null);128 done();129 });130 });131 it('can set the audio track', done => {132 const peer: RTCPeerConnection = new RTCPeerConnection();133 tc.setPeer(peer);134 tc.setupLocalTransceivers();135 const newAudioTrack = new MediaStreamTrack();136 tc.setAudioInput(newAudioTrack);137 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {138 const audioTransceiver = peer.getTransceivers()[0];139 expect(audioTransceiver.direction).to.equal('sendrecv');140 expect(audioTransceiver.sender.track).to.equal(newAudioTrack);141 done();142 });143 });144 it('can not set the audio track if transceivers have not been set up', done => {145 const peer: RTCPeerConnection = new RTCPeerConnection();146 tc.setPeer(peer);147 const newAudioTrack = new MediaStreamTrack();148 tc.setAudioInput(newAudioTrack);149 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {150 const audioTransceiver = peer.getTransceivers()[0];151 expect(audioTransceiver).to.be.undefined;152 done();153 });154 });155 });156 describe('setVideoInput', () => {157 it('can set the video track to null', done => {158 const peer: RTCPeerConnection = new RTCPeerConnection();159 tc.setPeer(peer);160 tc.setupLocalTransceivers();161 tc.setVideoInput(null);162 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {163 const videoTransceiver = peer.getTransceivers()[1];164 expect(videoTransceiver.sender.track).to.equal(null);165 done();166 });167 });168 it('can set the video track', done => {169 const peer: RTCPeerConnection = new RTCPeerConnection();170 tc.setPeer(peer);171 tc.setupLocalTransceivers();172 const newVideoTrack = new MediaStreamTrack();173 tc.setVideoInput(newVideoTrack);174 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {175 const videoTransceiver = peer.getTransceivers()[1];176 expect(videoTransceiver.direction).to.equal('sendrecv');177 expect(videoTransceiver.sender.track).to.equal(newVideoTrack);178 done();179 });180 });181 it('can not set the video track if transceivers have not been set up', done => {182 const peer: RTCPeerConnection = new RTCPeerConnection();183 tc.setPeer(peer);184 const newVideoTrack = new MediaStreamTrack();185 tc.setVideoInput(newVideoTrack);186 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {187 const videoTransceiver = peer.getTransceivers()[1];188 expect(videoTransceiver).to.be.undefined;189 done();190 });191 });192 });193 describe('updateVideoTransceivers', () => {194 let peer: RTCPeerConnection;195 function prepareIndex(streamIds: number[]): DefaultVideoStreamIndex {196 const index: DefaultVideoStreamIndex = new DefaultVideoStreamIndex(logger);197 const sources: SdkStreamDescriptor[] = [];198 for (const id of streamIds) {199 sources.push(200 new SdkStreamDescriptor({201 streamId: id,202 groupId: id,203 maxBitrateKbps: 100,204 mediaType: SdkStreamMediaType.VIDEO,205 })206 );207 }208 index.integrateIndexFrame(209 new SdkIndexFrame({210 atCapacity: false,211 sources: sources,212 })213 );214 return index;215 }216 type Writable<T> = {217 -readonly [K in keyof T]: T[K];218 };219 function setTransceiverStreamId(videoStreamIds: VideoStreamIdSet): void {220 const streamIds = videoStreamIds.array();221 const transceivers: RTCRtpTransceiver[] = peer.getTransceivers();222 let transStartIndex = 0;223 // Look for first recvonly transceiver224 for (const [index, transceiver] of transceivers.entries()) {225 if (transceiver.direction === 'recvonly') {226 transStartIndex = index;227 break;228 }229 }230 for (const [index, streamId] of streamIds.entries()) {231 const transceiver = transceivers[transStartIndex + index];232 (transceiver as Writable<RTCRtpTransceiver>).mid = streamId.toString();233 }234 }235 function verifyTransceiverDirections(directions: string[]): void {236 const transceivers: RTCRtpTransceiver[] = peer.getTransceivers();237 const actualDirections = transceivers.map(transceiver => transceiver.direction);238 expect(actualDirections).deep.equal(directions);239 }240 beforeEach(() => {241 peer = new RTCPeerConnection();242 tc.setPeer(peer);243 });244 it('cannot update video transceivers if it has reset transceivers', () => {245 tc.reset();246 const videoStreamIndex = prepareIndex([7]);247 const videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet();248 const videoSubscriptions: number[] = tc.updateVideoTransceivers(249 videoStreamIndex,250 videosToReceive251 );252 expect(videoSubscriptions).to.deep.equal([]);253 expect(peer.getTransceivers().length).to.equal(0);254 });255 it('includes a zero for a potential local video', () => {256 const videoStreamIndex = prepareIndex([7]);257 const videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet();258 const videoSubscriptions: number[] = tc.updateVideoTransceivers(259 videoStreamIndex,260 videosToReceive261 );262 expect(videoSubscriptions).to.deep.equal([0]);263 expect(peer.getTransceivers().length).to.equal(0);264 });265 it('creates a transceiver to subscribe to one remote video', () => {266 const videoStreamIndex = prepareIndex([7]);267 const videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([7]);268 const videoSubscriptions: number[] = tc.updateVideoTransceivers(269 videoStreamIndex,270 videosToReceive271 );272 expect(videoSubscriptions).to.deep.equal([0, 7]);273 verifyTransceiverDirections(['recvonly']);274 });275 it('when unsubscribing from a remote video, marks the transceiver inactive and leaves a zero in the video subscriptions slot', () => {276 const videoStreamIndex = prepareIndex([7]);277 let videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([7]);278 let videoSubscriptions: number[] = tc.updateVideoTransceivers(279 videoStreamIndex,280 videosToReceive281 );282 expect(videoSubscriptions).to.deep.equal([0, 7]);283 verifyTransceiverDirections(['recvonly']);284 videosToReceive = new DefaultVideoStreamIdSet();285 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);286 expect(videoSubscriptions).to.deep.equal([0, 0]);287 verifyTransceiverDirections(['inactive']);288 });289 it('with two subscriptions, unsubscribes from the last', () => {290 const videoStreamIndex = prepareIndex([7, 8]);291 let videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([7, 8]);292 let videoSubscriptions: number[] = tc.updateVideoTransceivers(293 videoStreamIndex,294 videosToReceive295 );296 expect(videoSubscriptions).to.deep.equal([0, 7, 8]);297 verifyTransceiverDirections(['recvonly', 'recvonly']);298 const subackFrame = new SdkSubscribeAckFrame({299 tracks: [300 new SdkTrackMapping({ streamId: 7, trackLabel: 'v_7' }),301 new SdkTrackMapping({ streamId: 8, trackLabel: 'v_8' }),302 ],303 });304 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);305 setTransceiverStreamId(videosToReceive);306 videosToReceive = new DefaultVideoStreamIdSet([7]);307 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);308 expect(videoSubscriptions).to.deep.equal([0, 7, 0]);309 verifyTransceiverDirections(['recvonly', 'inactive']);310 });311 it('with two subscriptions, unsubscribes from both, then resubscribes to both', () => {312 const videoStreamIndex = prepareIndex([7, 8]);313 let videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([7, 8]);314 let videoSubscriptions: number[] = tc.updateVideoTransceivers(315 videoStreamIndex,316 videosToReceive317 );318 expect(videoSubscriptions).to.deep.equal([0, 7, 8]);319 verifyTransceiverDirections(['recvonly', 'recvonly']);320 let subackFrame = new SdkSubscribeAckFrame({321 tracks: [322 new SdkTrackMapping({ streamId: 7, trackLabel: 'v_7' }),323 new SdkTrackMapping({ streamId: 8, trackLabel: 'v_8' }),324 ],325 });326 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);327 setTransceiverStreamId(videosToReceive);328 videosToReceive = new DefaultVideoStreamIdSet([7]);329 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);330 expect(videoSubscriptions).to.deep.equal([0, 7, 0]);331 verifyTransceiverDirections(['recvonly', 'inactive']);332 subackFrame = new SdkSubscribeAckFrame({333 tracks: [new SdkTrackMapping({ streamId: 7, trackLabel: 'v_7' })],334 });335 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);336 setTransceiverStreamId(videosToReceive);337 videosToReceive = new DefaultVideoStreamIdSet([]);338 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);339 expect(videoSubscriptions).to.deep.equal([0, 0, 0]);340 verifyTransceiverDirections(['inactive', 'inactive']);341 subackFrame = new SdkSubscribeAckFrame({342 tracks: [],343 });344 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);345 setTransceiverStreamId(videosToReceive);346 videosToReceive = new DefaultVideoStreamIdSet([7]);347 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);348 expect(videoSubscriptions).to.deep.equal([0, 7, 0]);349 verifyTransceiverDirections(['recvonly', 'inactive']);350 subackFrame = new SdkSubscribeAckFrame({351 tracks: [new SdkTrackMapping({ streamId: 7, trackLabel: 'v_7' })],352 });353 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);354 setTransceiverStreamId(videosToReceive);355 videosToReceive = new DefaultVideoStreamIdSet([7, 8]);356 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);357 expect(videoSubscriptions).to.deep.equal([0, 7, 8]);358 verifyTransceiverDirections(['recvonly', 'recvonly']);359 });360 it('will not reuse transceiver when unsubscribe from one and subscribe to another', () => {361 const videoStreamIndex = prepareIndex([1, 4]);362 let videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([1]);363 let videoSubscriptions: number[] = tc.updateVideoTransceivers(364 videoStreamIndex,365 videosToReceive366 );367 expect(videoSubscriptions).to.deep.equal([0, 1]);368 verifyTransceiverDirections(['recvonly']);369 const subackFrame = new SdkSubscribeAckFrame({370 tracks: [new SdkTrackMapping({ streamId: 1, trackLabel: 'v_1' })],371 });372 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);373 setTransceiverStreamId(videosToReceive);374 videosToReceive = new DefaultVideoStreamIdSet([4]);375 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);376 expect(videoSubscriptions).to.deep.equal([0, 0, 4]);377 verifyTransceiverDirections(['inactive', 'recvonly']);378 });379 it('will not reuse transceiver when index removes one and adds one', () => {380 let videoStreamIndex = prepareIndex([1]);381 let videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([1]);382 let videoSubscriptions: number[] = tc.updateVideoTransceivers(383 videoStreamIndex,384 videosToReceive385 );386 expect(videoSubscriptions).to.deep.equal([0, 1]);387 verifyTransceiverDirections(['recvonly']);388 const subackFrame = new SdkSubscribeAckFrame({389 tracks: [new SdkTrackMapping({ streamId: 1, trackLabel: 'v_1' })],390 });391 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);392 setTransceiverStreamId(videosToReceive);393 videoStreamIndex = prepareIndex([4]);394 videosToReceive = new DefaultVideoStreamIdSet([4]);395 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);396 expect(videoSubscriptions).to.deep.equal([0, 0, 4]);397 verifyTransceiverDirections(['inactive', 'recvonly']);398 });399 it('will use local transceivers', () => {400 tc.setupLocalTransceivers();401 const videoStreamIndex = prepareIndex([7, 8]);402 const videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([7, 8]);403 let videoSubscriptions: number[] = tc.updateVideoTransceivers(404 videoStreamIndex,405 videosToReceive406 );407 const subackFrame = new SdkSubscribeAckFrame({408 tracks: [409 new SdkTrackMapping({ streamId: 7, trackLabel: 'v_7' }),410 new SdkTrackMapping({ streamId: 8, trackLabel: 'v_8' }),411 ],412 });413 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);414 setTransceiverStreamId(videosToReceive);415 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);416 expect(videoSubscriptions).to.deep.equal([0, 7, 8]);417 verifyTransceiverDirections(['inactive', 'inactive', 'recvonly', 'recvonly']);418 });419 it('will use a transceiver\'s mid prefixed with "v_" to get the streamId for the track', () => {420 const streamId = 4;421 const videoStreamIndex = prepareIndex([streamId, 8]);422 const videosToReceive: VideoStreamIdSet = new DefaultVideoStreamIdSet([streamId, 8]);423 let videoSubscriptions: number[] = tc.updateVideoTransceivers(424 videoStreamIndex,425 videosToReceive426 );427 const subackFrame = new SdkSubscribeAckFrame({428 tracks: [429 new SdkTrackMapping({ streamId: 2, trackLabel: 'b18b9db2' }),430 new SdkTrackMapping({ streamId: streamId, trackLabel: 'v_4' }),431 new SdkTrackMapping({ streamId: 8, trackLabel: 'v_8' }),432 ],433 });434 videoStreamIndex.integrateSubscribeAckFrame(subackFrame);435 setTransceiverStreamId(videosToReceive);436 videoSubscriptions = tc.updateVideoTransceivers(videoStreamIndex, videosToReceive);437 expect(videoSubscriptions).to.deep.equal([0, streamId, 8]);438 verifyTransceiverDirections(['recvonly', 'recvonly']);439 });440 });441 describe('setVideoSendingBitrateKbps', () => {442 it('will not set bitrate if transceiver is not set up', () => {443 tc.setVideoSendingBitrateKbps(100);444 });445 it('sets bitrate on RTCRtpSender correctly', done => {446 const peer: RTCPeerConnection = new RTCPeerConnection();447 tc.setPeer(peer);448 tc.setupLocalTransceivers();449 const newVideoTrack = new MediaStreamTrack();450 tc.setVideoInput(newVideoTrack);451 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {452 const videoTransceiver = peer.getTransceivers()[1];453 expect(videoTransceiver.direction).to.equal('sendrecv');454 expect(videoTransceiver.sender.track).to.equal(newVideoTrack);455 const parameter = {456 degradationPreference: null,457 transactionId: '',458 } as RTCRtpSendParameters;459 videoTransceiver.sender.setParameters(parameter);460 tc.setVideoSendingBitrateKbps(100);461 });462 new TimeoutScheduler(domMockBehavior.asyncWaitMs + 10).start(() => {463 tc.setVideoSendingBitrateKbps(200);464 const parameter = peer.getTransceivers()[1].sender.getParameters();465 expect(parameter.encodings[0].maxBitrate).to.equal(200 * 1000);466 done();467 });468 });469 });470 describe('replaceAudioTrack', () => {471 it('returns false if transceiver is not set up or audio transceiver is not sending', async () => {472 const newAudioTrack = new MediaStreamTrack();473 let success = await tc.replaceAudioTrack(newAudioTrack);474 expect(success).to.be.false;475 // set up local transceivers476 success = true;477 const peer: RTCPeerConnection = new RTCPeerConnection();478 tc.setPeer(peer);479 tc.setupLocalTransceivers();480 success = await tc.replaceAudioTrack(newAudioTrack);481 expect(success).to.be.false;482 // set audio input to activate transceiver483 tc.setAudioInput(newAudioTrack);484 const newAudioTrack2 = new MediaStreamTrack();485 success = await tc.replaceAudioTrack(newAudioTrack2);486 expect(success).to.be.true;487 const audioTransceiver = peer.getTransceivers()[0];488 expect(audioTransceiver.sender.track).to.equal(newAudioTrack2);489 });490 });491 describe('replaceAudioTrackForSender', () => {492 it('returns false if input sender is null', async () => {493 const audioTrack = new MediaStreamTrack();494 const success = await DefaultTransceiverController.replaceAudioTrackForSender(495 null,496 audioTrack497 );498 expect(success).to.be.false;499 });500 it('returns true if audio track is replaced', async () => {501 const sender = new RTCRtpSender();502 const audioTrack = new MediaStreamTrack();503 const success = await DefaultTransceiverController.replaceAudioTrackForSender(504 sender,505 audioTrack506 );507 expect(success).to.be.true;508 expect(sender.track).to.equal(audioTrack);509 });510 });...

Full Screen

Full Screen

DefaultTransceiverController.ts

Source:DefaultTransceiverController.ts Github

copy

Full Screen

1// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.2// SPDX-License-Identifier: Apache-2.03import BrowserBehavior from '../browserbehavior/DefaultBrowserBehavior';4import DefaultBrowserBehavior from '../browserbehavior/DefaultBrowserBehavior';5import Logger from '../logger/Logger';6import VideoStreamIdSet from '../videostreamidset/VideoStreamIdSet';7import VideoStreamIndex from '../videostreamindex/VideoStreamIndex';8import TransceiverController from './TransceiverController';9export default class DefaultTransceiverController implements TransceiverController {10 private localCameraTransceiver: RTCRtpTransceiver | null = null;11 private localAudioTransceiver: RTCRtpTransceiver | null = null;12 private videoSubscriptions: number[] = [];13 private defaultMediaStream: MediaStream | null = null;14 private peer: RTCPeerConnection | null = null;15 private browserBehavior: BrowserBehavior = new DefaultBrowserBehavior();16 constructor(private logger: Logger) {}17 static setVideoSendingBitrateKbpsForSender(18 sender: RTCRtpSender,19 bitrateKbps: number,20 logger: Logger21 ): void {22 if (!sender || bitrateKbps <= 0) {23 return;24 }25 const param: RTCRtpSendParameters = sender.getParameters();26 if (!param.encodings) {27 param.encodings = [{}];28 }29 for (const encodeParam of param.encodings) {30 encodeParam.maxBitrate = bitrateKbps * 1000;31 }32 sender.setParameters(param);33 logger.info(`set video send bandwidth to ${bitrateKbps}kbps`);34 }35 static async replaceAudioTrackForSender(36 sender: RTCRtpSender,37 track: MediaStreamTrack38 ): Promise<boolean> {39 if (!sender) {40 return false;41 }42 await sender.replaceTrack(track);43 return true;44 }45 setVideoSendingBitrateKbps(bitrateKbps: number): void {46 // this won't set bandwidth limitation for video in Chrome47 if (!this.localCameraTransceiver || this.localCameraTransceiver.direction !== 'sendrecv') {48 return;49 }50 const sender: RTCRtpSender = this.localCameraTransceiver.sender;51 DefaultTransceiverController.setVideoSendingBitrateKbpsForSender(52 sender,53 bitrateKbps,54 this.logger55 );56 }57 setPeer(peer: RTCPeerConnection): void {58 this.peer = peer;59 }60 reset(): void {61 this.localCameraTransceiver = null;62 this.localAudioTransceiver = null;63 this.videoSubscriptions = [];64 this.defaultMediaStream = null;65 this.peer = null;66 }67 useTransceivers(): boolean {68 if (!this.peer || !this.browserBehavior.requiresUnifiedPlan()) {69 return false;70 }71 return typeof this.peer.getTransceivers !== 'undefined';72 }73 trackIsVideoInput(track: MediaStreamTrack): boolean {74 if (!this.localCameraTransceiver) {75 return false;76 }77 return (78 track === this.localCameraTransceiver.sender.track ||79 track === this.localCameraTransceiver.receiver.track80 );81 }82 setupLocalTransceivers(): void {83 if (!this.useTransceivers()) {84 return;85 }86 if (!this.defaultMediaStream && typeof MediaStream !== 'undefined') {87 this.defaultMediaStream = new MediaStream();88 }89 if (!this.localAudioTransceiver) {90 this.localAudioTransceiver = this.peer.addTransceiver('audio', {91 direction: 'inactive',92 streams: [this.defaultMediaStream],93 });94 }95 if (!this.localCameraTransceiver) {96 this.localCameraTransceiver = this.peer.addTransceiver('video', {97 direction: 'inactive',98 streams: [this.defaultMediaStream],99 });100 }101 }102 setAudioInput(track: MediaStreamTrack | null): void {103 this.setTransceiverInput(this.localAudioTransceiver, track);104 }105 async replaceAudioTrack(track: MediaStreamTrack): Promise<boolean> {106 if (!this.localAudioTransceiver || this.localAudioTransceiver.direction !== 'sendrecv') {107 this.logger.info(`audio transceiver direction is not set up or not activated`);108 return false;109 }110 await this.localAudioTransceiver.sender.replaceTrack(track);111 return true;112 }113 setVideoInput(track: MediaStreamTrack | null): void {114 this.setTransceiverInput(this.localCameraTransceiver, track);115 }116 updateVideoTransceivers(117 videoStreamIndex: VideoStreamIndex,118 videosToReceive: VideoStreamIdSet119 ): number[] {120 if (!this.useTransceivers()) {121 return videosToReceive.array();122 }123 // See https://blog.mozilla.org/webrtc/rtcrtptransceiver-explored/ for details on transceivers124 const transceivers: RTCRtpTransceiver[] = this.peer.getTransceivers();125 // Subscription index 0 is reserved for transmitting camera.126 // We mark inactive slots with 0 in the subscription array.127 this.videoSubscriptions = [0];128 videosToReceive = videosToReceive.clone();129 this.unsubscribeTransceivers(transceivers, videoStreamIndex, videosToReceive);130 this.subscribeTransceivers(transceivers, videosToReceive);131 this.logger.debug(() => {132 return this.debugDumpTransceivers();133 });134 return this.videoSubscriptions;135 }136 private unsubscribeTransceivers(137 transceivers: RTCRtpTransceiver[],138 videoStreamIndex: VideoStreamIndex,139 videosToReceive: VideoStreamIdSet140 ): void {141 // disable transceivers which are no longer going to subscribe142 for (const transceiver of transceivers) {143 if (transceiver === this.localCameraTransceiver || !this.transceiverIsVideo(transceiver)) {144 continue;145 }146 // by convention with the video host, msid is equal to the media section mid, prefixed with the string "v_"147 // we use this to get the streamId for the track148 const streamId = videoStreamIndex.streamIdForTrack('v_' + transceiver.mid);149 if (streamId !== undefined && videosToReceive.contain(streamId)) {150 transceiver.direction = 'recvonly';151 this.videoSubscriptions.push(streamId);152 videosToReceive.remove(streamId);153 } else {154 transceiver.direction = 'inactive';155 // mark this slot inactive with a 0 in the subscription array156 this.videoSubscriptions.push(0);157 }158 }159 }160 private subscribeTransceivers(161 transceivers: RTCRtpTransceiver[],162 videosToReceive: VideoStreamIdSet163 ): void {164 if (videosToReceive.size() === 0) {165 return;166 }167 // Handle remaining subscriptions using existing inactive transceivers.168 const videosRemaining = videosToReceive.array();169 // Begin counting out index in the the subscription array at 1 since the camera.170 // Always occupies position 0 (whether active or not).171 let n = 1;172 for (const transceiver of transceivers) {173 if (transceiver === this.localCameraTransceiver || !this.transceiverIsVideo(transceiver)) {174 continue;175 }176 if (transceiver.direction === 'inactive') {177 transceiver.direction = 'recvonly';178 const streamId = videosRemaining.shift();179 this.videoSubscriptions[n] = streamId;180 if (videosRemaining.length === 0) {181 break;182 }183 }184 n += 1;185 }186 // add transceivers for the remaining subscriptions187 for (const index of videosRemaining) {188 // @ts-ignore189 const transceiver = this.peer.addTransceiver('video', {190 direction: 'recvonly',191 streams: [this.defaultMediaStream],192 });193 this.videoSubscriptions.push(index);194 this.logger.info(195 `adding transceiver mid: ${transceiver.mid} subscription: ${index} direction: recvonly`196 );197 }198 }199 private transceiverIsVideo(transceiver: RTCRtpTransceiver): boolean {200 return (201 (transceiver.receiver &&202 transceiver.receiver.track &&203 transceiver.receiver.track.kind === 'video') ||204 (transceiver.sender && transceiver.sender.track && transceiver.sender.track.kind === 'video')205 );206 }207 private debugDumpTransceivers(): string {208 let msg = '';209 let n = 0;210 for (const transceiver of this.peer.getTransceivers()) {211 if (!this.transceiverIsVideo(transceiver)) {212 continue;213 }214 msg += `transceiver index=${n} mid=${transceiver.mid} subscription=${this.videoSubscriptions[n]} direction=${transceiver.direction}\n`;215 n += 1;216 }217 return msg;218 }219 private setTransceiverInput(220 transceiver: RTCRtpTransceiver | null,221 track: MediaStreamTrack222 ): void {223 if (!transceiver) {224 return;225 }226 if (track) {227 transceiver.direction = 'sendrecv';228 } else {229 transceiver.direction = 'inactive';230 }231 transceiver.sender.replaceTrack(track);232 }...

Full Screen

Full Screen

peer.js

Source:peer.js Github

copy

Full Screen

1/*2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.3 *4 * Use of this source code is governed by a BSD-style license5 * that can be found in the LICENSE file in the root of the source6 * tree.7 */8'use strict';9/**10 * Establishes a Peer Connection with `other` using the Perfect Negotiation pattern.11 * @param {Window} other12 * @param {boolean} polite13 * @param {function(Error): void} fail14 * @return {RTCPeerConnection} Peer Connection15 */16function peer(other, polite, fail = undefined) { // eslint-disable-line no-unused-vars17 if (!fail) fail = e => void send(window.parent, {error: `${e.name}: ${e.message}`});18 const send = (target, msg) => void target.postMessage(JSON.parse(JSON.stringify(msg)), '*');19 const log = str => void console.log(`[${polite ? 'POLITE' : 'IMPOLITE'}] ${str}`);20 const assert_equals = !window.assert_equals ?21 (a, b, msg) => a === b || void fail(new Error(`${msg} expected ${b} but got ${a}`)) :22 window.assert_equals;23 const pc = new RTCPeerConnection();24 const localVideo1 = document.getElementById('localVideo1');25 const localVideo2 = document.getElementById('localVideo2');26 const remoteVideo = document.getElementById('remoteVideo');27 const transceiversForSending = [];28 const commands = {29 async swapTransceivers() {30 log('swapTransceivers');31 const stream1 = localVideo1.srcObject;32 const stream2 = localVideo2.srcObject;33 if (transceiversForSending.length == 0) {34 // This is the first time swapTransceivers is called.35 // Add the initial transceivers, which are remembered for future swaps.36 transceiversForSending.push(37 pc.addTransceiver(stream1.getTracks()[0], {streams: [stream1], direction: 'sendonly'}));38 transceiversForSending.push(39 pc.addTransceiver('video', {streams: [stream2], direction: 'inactive'}));40 return;41 }42 // We have sent before. Swap which transceiver is the sending one.43 if (transceiversForSending[0].direction == 'sendonly') {44 transceiversForSending[0].direction = 'inactive';45 transceiversForSending[0].sender.replaceTrack(null);46 transceiversForSending[1].direction = 'sendonly';47 transceiversForSending[1].sender.replaceTrack(stream2.getTracks()[0]);48 } else {49 transceiversForSending[1].direction = 'inactive';50 transceiversForSending[1].sender.replaceTrack(null);51 transceiversForSending[0].direction = 'sendonly';52 transceiversForSending[0].sender.replaceTrack(stream1.getTracks()[0]);53 }54 },55 };56 try {57 pc.ontrack = e => {58 log('ontrack');59 remoteVideo.srcObject = new MediaStream();60 remoteVideo.srcObject.addTrack(e.track);61 };62 pc.onicecandidate = ({candidate}) => void send(other, {candidate});63 let makingOffer = false;64 let ignoreOffer = false;65 let srdAnswerPending = false;66 pc.onnegotiationneeded = async () => {67 try {68 log('SLD due to negotiationneeded');69 assert_equals(pc.signalingState, 'stable', 'negotiationneeded always fires in stable state');70 assert_equals(makingOffer, false, 'negotiationneeded not already in progress');71 makingOffer = true;72 await pc.setLocalDescription();73 assert_equals(pc.signalingState, 'have-local-offer', 'negotiationneeded not racing with onmessage');74 assert_equals(pc.localDescription.type, 'offer', 'negotiationneeded SLD worked');75 send(other, {description: pc.localDescription});76 } catch (e) {77 fail(e);78 } finally {79 makingOffer = false;80 }81 };82 window.onmessage = async ({data: {description, candidate, run}}) => {83 try {84 if (description) {85 // If we have a setRemoteDescription() answer operation pending, then86 // we will be "stable" by the time the next setRemoteDescription() is87 // executed, so we count this being stable when deciding whether to88 // ignore the offer.89 const isStable =90 pc.signalingState == 'stable' ||91 (pc.signalingState == 'have-local-offer' && srdAnswerPending);92 ignoreOffer =93 description.type == 'offer' && !polite && (makingOffer || !isStable);94 if (ignoreOffer) {95 log('glare - ignoring offer');96 return;97 }98 srdAnswerPending = description.type == 'answer';99 log(`SRD(${description.type})`);100 await pc.setRemoteDescription(description);101 srdAnswerPending = false;102 if (description.type == 'offer') {103 assert_equals(pc.signalingState, 'have-remote-offer', 'Remote offer');104 assert_equals(pc.remoteDescription.type, 'offer', 'SRD worked');105 log('SLD to get back to stable');106 await pc.setLocalDescription();107 assert_equals(pc.signalingState, 'stable', 'onmessage not racing with negotiationneeded');108 assert_equals(pc.localDescription.type, 'answer', 'onmessage SLD worked');109 send(other, {description: pc.localDescription});110 } else {111 assert_equals(pc.remoteDescription.type, 'answer', 'Answer was set');112 assert_equals(pc.signalingState, 'stable', 'answered');113 pc.dispatchEvent(new Event('negotiated'));114 }115 } else if (candidate) {116 try {117 await pc.addIceCandidate(candidate);118 } catch (e) {119 if (!ignoreOffer) throw e;120 }121 } else if (run) {122 send(window.parent, {[run.id]: await commands[run.cmd]() || 0});123 }124 } catch (e) {125 fail(e);126 }127 };128 } catch (e) {129 fail(e);130 }131 return pc;132}...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1function testTransceiver() {2 var pc1 = new RTCPeerConnection();3 var pc2 = new RTCPeerConnection();4 pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);5 pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);6 pc2.ontrack = e => document.getElementById('video').srcObject = e.streams[0];7 pc1.createTransceiver('video');8 navigator.mediaDevices.getUserMedia({video: true})9 .then(stream => pc1.addTrack(stream.getTracks()[0], stream))10 .then(() => pc1.createOffer())11 .then(offer => pc1.setLocalDescription(offer))12 .then(() => pc2.setRemoteDescription(pc1.localDescription))13 .then(() => pc2.createAnswer())14 .then(answer => pc2.setLocalDescription(answer))15 .then(() => pc1.setRemoteDescription(pc2.localDescription));16}17function testAddTransceiver() {18 var pc1 = new RTCPeerConnection();19 var pc2 = new RTCPeerConnection();20 pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);21 pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);22 pc2.ontrack = e => document.getElementById('video').srcObject = e.streams[0];23 navigator.mediaDevices.getUserMedia({video: true})24 .then(stream => pc1.addTrack(stream.getTracks()[0], stream))25 .then(() => pc1.addTransceiver('video'))26 .then(() => pc1.createOffer())27 .then(offer => pc1.setLocalDescription(offer))28 .then(() => pc2.setRemoteDescription(pc1.localDescription))29 .then(() => pc2.createAnswer())30 .then(answer => pc2.setLocalDescription(answer))31 .then(() => pc1.setRemoteDescription(pc2.localDescription));32}33function testAddTransceiverWithInit() {34 var pc1 = new RTCPeerConnection();35 var pc2 = new RTCPeerConnection();36 pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);37 pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var webpagetest = new wpt('www.webpagetest.org');3}, function(err, data) {4 if (err) {5 console.log('Error: ' + err.message);6 }7 else {8 console.log('Test Results: ' + data.data.summary);9 }10});11var wpt = require('webpagetest');12var webpagetest = new wpt('www.webpagetest.org');13}, function(err, data) {14 if (err) {15 console.log('Error: ' + err.message);16 }17 else {18 console.log('Test Results: ' + data.data.summary);19 }20});21var wpt = require('webpagetest');22var webpagetest = new wpt('www.webpagetest.org');23}, function(err, data) {24 if (err) {25 console.log('Error: ' + err.message);26 }27 else {28 console.log('Test Results: ' + data.data.summary);29 }30});31var wpt = require('webpagetest');32var webpagetest = new wpt('www.webpagetest.org');33}, function(err, data) {34 if (err) {35 console.log('Error: ' + err.message);36 }37 else {38 console.log('

Full Screen

Using AI Code Generation

copy

Full Screen

1var test = async_test('Test to check if the transceivers method of RTCPeerConnection returns an array of RTCRtpTransceiver objects');2var pc = new RTCPeerConnection();3test.step(function() {4 assert_array_equals(pc.getTransceivers(), [], 'The transceivers method should return an empty array');5 test.done();6});

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful