blob: e6aaa83fb73260ba017e36926c8d9217bfed6102 [file] [log] [blame]
/*
* 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();
}