| /* |
| * Copyright 2017 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| /*jshint esversion: 6 */ |
| |
| 'use strict'; |
| |
| const $ = document.getElementById.bind(document); |
| |
| function logError(err) { |
| console.error(err); |
| } |
| |
| |
| class FeedTable { |
| constructor() { |
| this.numCols = 5; |
| this.col = 0; |
| this.testTable = document.getElementById('test-table'); |
| this.row = this.testTable.insertRow(-1); |
| } |
| |
| addNewAudioCell() { |
| if (this.col == this.numCols) { |
| this.row = this.testTable.insertRow(-1); |
| this.col = 0; |
| } |
| var newCell = this.row.insertCell(-1); |
| var audio = document.createElement('audio'); |
| audio.autoplay = false; |
| newCell.appendChild(audio); |
| this.col++; |
| return audio; |
| } |
| } |
| |
| |
| class PeerConnection { |
| constructor(audioElement) { |
| this.localConnection = null; |
| this.remoteConnection = null; |
| this.remoteAudio = audioElement; |
| } |
| |
| start() { |
| const onGetUserMediaSuccess = this.onGetUserMediaSuccess.bind(this); |
| return navigator.mediaDevices |
| .getUserMedia({audio: true, video: true}) |
| .then(onGetUserMediaSuccess); |
| } |
| |
| onGetUserMediaSuccess(stream) { |
| this.localConnection = new RTCPeerConnection(null); |
| this.localConnection.onicecandidate = (event) => { |
| this.onIceCandidate(this.remoteConnection, event); |
| }; |
| this.localConnection.addStream(stream); |
| |
| this.remoteConnection = new RTCPeerConnection(null); |
| this.remoteConnection.onicecandidate = (event) => { |
| this.onIceCandidate(this.localConnection, event); |
| }; |
| this.remoteConnection.onaddstream = (e) => { |
| this.remoteAudio.srcObject = e.stream; |
| }; |
| |
| var onCreateOfferSuccess = this.onCreateOfferSuccess.bind(this); |
| this.localConnection |
| .createOffer({offerToReceiveAudio: 1, offerToReceiveVideo: 1}) |
| .then(onCreateOfferSuccess, logError); |
| } |
| |
| onCreateOfferSuccess(desc) { |
| this.localConnection.setLocalDescription(desc); |
| this.remoteConnection.setRemoteDescription(desc); |
| |
| var onCreateAnswerSuccess = this.onCreateAnswerSuccess.bind(this); |
| this.remoteConnection.createAnswer().then(onCreateAnswerSuccess, logError); |
| } |
| |
| onCreateAnswerSuccess(desc) { |
| this.remoteConnection.setLocalDescription(desc); |
| this.localConnection.setRemoteDescription(desc); |
| } |
| |
| onIceCandidate(connection, event) { |
| if (event.candidate) { |
| connection.addIceCandidate(new RTCIceCandidate(event.candidate)); |
| } |
| } |
| } |
| |
| |
| class TestRunner { |
| constructor(runtimeSeconds) { |
| this.runtimeSeconds = runtimeSeconds; |
| this.audioElements = []; |
| this.peerConnections = []; |
| this.feedTable = new FeedTable(); |
| this.iteration = 0; |
| this.startTime; |
| this.lastIterationTime; |
| } |
| |
| addPeerConnection() { |
| const audioElement = this.feedTable.addNewAudioCell(); |
| this.audioElements.push(audioElement); |
| this.peerConnections.push(new PeerConnection(audioElement)); |
| } |
| |
| startTest() { |
| this.startTime = Date.now(); |
| let promises = testRunner.peerConnections.map((conn) => conn.start()); |
| Promise.all(promises) |
| .then(() => { |
| this.startTime = Date.now(); |
| this.audioElements.forEach((feed) => feed.play()); |
| this.pauseAndPlayLoop(); |
| }) |
| .catch((e) => {throw e}); |
| } |
| |
| pauseAndPlayLoop() { |
| this.iteration++; |
| const status = this.getStatus(); |
| this.lastIterationTime = Date.now(); |
| $('status').textContent = status |
| if (status != 'ok-done') { |
| setTimeout(() => this.pauseAndPlayLoop()); |
| } else { |
| // Finished, pause the audio. |
| this.audioElements.forEach((feed) => feed.pause()); |
| } |
| } |
| |
| getStatus() { |
| if (this.iteration == 0) { |
| return 'not-started'; |
| } |
| const timeSpent = Date.now() - this.startTime; |
| if (timeSpent >= this.runtimeSeconds * 1000) { |
| return 'ok-done'; |
| } else { |
| return `running, iteration: ${this.iteration}`; |
| } |
| } |
| |
| getResults() { |
| const runTimeMillis = this.lastIterationTime - this.startTime; |
| return {'runTimeSeconds': runTimeMillis / 1000}; |
| } |
| } |
| |
| |
| let testRunner; |
| |
| function run(runtimeSeconds, numPeerConnections) { |
| testRunner = new TestRunner(runtimeSeconds); |
| for (let i = 0; i < numPeerConnections; i++) { |
| testRunner.addPeerConnection(); |
| } |
| testRunner.startTest(); |
| } |
| |