Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Unified Diff: tools/perf/page_sets/webrtc_cases/audio.js

Issue 2761163003: Use local pages for webrtc telemetry tests. (Closed)
Patch Set: Exclude all of webrtc_cases in PRESUBMIT.py and add a comment explaining it is because these are te… Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/perf/page_sets/webrtc_cases/audio.html ('k') | tools/perf/page_sets/webrtc_cases/canvas-capture.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/perf/page_sets/webrtc_cases/audio.js
diff --git a/tools/perf/page_sets/webrtc_cases/audio.js b/tools/perf/page_sets/webrtc_cases/audio.js
new file mode 100644
index 0000000000000000000000000000000000000000..2485837ac9d2b2ee5e42173de19702f215687ef0
--- /dev/null
+++ b/tools/perf/page_sets/webrtc_cases/audio.js
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+var audio2 = document.querySelector('audio#audio2');
+var callButton = document.querySelector('button#callButton');
+var hangupButton = document.querySelector('button#hangupButton');
+var codecSelector = document.querySelector('select#codec');
+hangupButton.disabled = true;
+callButton.onclick = call;
+hangupButton.onclick = hangup;
+
+var pc1;
+var pc2;
+var localStream;
+
+var bitrateGraph;
+var bitrateSeries;
+
+var packetGraph;
+var packetSeries;
+
+var lastResult;
+
+var offerOptions = {
+ offerToReceiveAudio: 1,
+ offerToReceiveVideo: 0,
+ voiceActivityDetection: false
+};
+
+function gotStream(stream) {
+ hangupButton.disabled = false;
+ trace('Received local stream');
+ localStream = stream;
+ var audioTracks = localStream.getAudioTracks();
+ if (audioTracks.length > 0) {
+ trace('Using Audio device: ' + audioTracks[0].label);
+ }
+ pc1.addStream(localStream);
+ trace('Adding Local Stream to peer connection');
+
+ pc1.createOffer(
+ offerOptions
+ ).then(
+ gotDescription1,
+ onCreateSessionDescriptionError
+ );
+
+ bitrateSeries = new TimelineDataSeries();
+ bitrateGraph = new TimelineGraphView('bitrateGraph', 'bitrateCanvas');
+ bitrateGraph.updateEndDate();
+
+ packetSeries = new TimelineDataSeries();
+ packetGraph = new TimelineGraphView('packetGraph', 'packetCanvas');
+ packetGraph.updateEndDate();
+}
+
+function onCreateSessionDescriptionError(error) {
+ trace('Failed to create session description: ' + error.toString());
+}
+
+function call() {
+ callButton.disabled = true;
+ codecSelector.disabled = true;
+ trace('Starting call');
+ var servers = null;
+ var pcConstraints = {
+ 'optional': []
+ };
+ pc1 = new RTCPeerConnection(servers, pcConstraints);
+ trace('Created local peer connection object pc1');
+ pc1.onicecandidate = function(e) {
+ onIceCandidate(pc1, e);
+ };
+ pc2 = new RTCPeerConnection(servers, pcConstraints);
+ trace('Created remote peer connection object pc2');
+ pc2.onicecandidate = function(e) {
+ onIceCandidate(pc2, e);
+ };
+ pc2.onaddstream = gotRemoteStream;
+ trace('Requesting local stream');
+ navigator.mediaDevices.getUserMedia({
+ audio: true,
+ video: false
+ })
+ .then(gotStream)
+ .catch(function(e) {
+ alert('getUserMedia() error: ' + e.name);
+ });
+}
+
+function gotDescription1(desc) {
+ trace('Offer from pc1 \n' + desc.sdp);
+ pc1.setLocalDescription(desc).then(
+ function() {
+ desc.sdp = forceChosenAudioCodec(desc.sdp);
+ pc2.setRemoteDescription(desc).then(
+ function() {
+ pc2.createAnswer().then(
+ gotDescription2,
+ onCreateSessionDescriptionError
+ );
+ },
+ onSetSessionDescriptionError
+ );
+ },
+ onSetSessionDescriptionError
+ );
+}
+
+function gotDescription2(desc) {
+ trace('Answer from pc2 \n' + desc.sdp);
+ pc2.setLocalDescription(desc).then(
+ function() {
+ desc.sdp = forceChosenAudioCodec(desc.sdp);
+ pc1.setRemoteDescription(desc).then(
+ function() {
+ },
+ onSetSessionDescriptionError
+ );
+ },
+ onSetSessionDescriptionError
+ );
+}
+
+function hangup() {
+ trace('Ending call');
+ localStream.getTracks().forEach(function(track) {
+ track.stop();
+ });
+ pc1.close();
+ pc2.close();
+ pc1 = null;
+ pc2 = null;
+ hangupButton.disabled = true;
+ callButton.disabled = false;
+ codecSelector.disabled = false;
+}
+
+function gotRemoteStream(e) {
+ audio2.srcObject = e.stream;
+ trace('Received remote stream');
+}
+
+function getOtherPc(pc) {
+ return (pc === pc1) ? pc2 : pc1;
+}
+
+function getName(pc) {
+ return (pc === pc1) ? 'pc1' : 'pc2';
+}
+
+function onIceCandidate(pc, event) {
+ getOtherPc(pc).addIceCandidate(event.candidate)
+ .then(
+ function() {
+ onAddIceCandidateSuccess(pc);
+ },
+ function(err) {
+ onAddIceCandidateError(pc, err);
+ }
+ );
+ trace(getName(pc) + ' ICE candidate: \n' + (event.candidate ?
+ event.candidate.candidate : '(null)'));
+}
+
+function onAddIceCandidateSuccess() {
+ trace('AddIceCandidate success.');
+}
+
+function onAddIceCandidateError(error) {
+ trace('Failed to add ICE Candidate: ' + error.toString());
+}
+
+function onSetSessionDescriptionError(error) {
+ trace('Failed to set session description: ' + error.toString());
+}
+
+function forceChosenAudioCodec(sdp) {
+ return maybePreferCodec(sdp, 'audio', 'send', codecSelector.value);
+}
+
+// Copied from AppRTC's sdputils.js:
+
+// Sets |codec| as the default |type| codec if it's present.
+// The format of |codec| is 'NAME/RATE', e.g. 'opus/48000'.
+function maybePreferCodec(sdp, type, dir, codec) {
+ var str = type + ' ' + dir + ' codec';
+ if (codec === '') {
+ trace('No preference on ' + str + '.');
+ return sdp;
+ }
+
+ trace('Prefer ' + str + ': ' + codec);
+
+ var sdpLines = sdp.split('\r\n');
+
+ // Search for m line.
+ var mLineIndex = findLine(sdpLines, 'm=', type);
+ if (mLineIndex === null) {
+ return sdp;
+ }
+
+ // If the codec is available, set it as the default in m line.
+ var codecIndex = findLine(sdpLines, 'a=rtpmap', codec);
+ console.log('codecIndex', codecIndex);
+ if (codecIndex) {
+ var payload = getCodecPayloadType(sdpLines[codecIndex]);
+ if (payload) {
+ sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], payload);
+ }
+ }
+
+ sdp = sdpLines.join('\r\n');
+ return sdp;
+}
+
+// Find the line in sdpLines that starts with |prefix|, and, if specified,
+// contains |substr| (case-insensitive search).
+function findLine(sdpLines, prefix, substr) {
+ return findLineInRange(sdpLines, 0, -1, prefix, substr);
+}
+
+// Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
+// and, if specified, contains |substr| (case-insensitive search).
+function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
+ var realEndLine = endLine !== -1 ? endLine : sdpLines.length;
+ for (var i = startLine; i < realEndLine; ++i) {
+ if (sdpLines[i].indexOf(prefix) === 0) {
+ if (!substr ||
+ sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
+ return i;
+ }
+ }
+ }
+ return null;
+}
+
+// Gets the codec payload type from an a=rtpmap:X line.
+function getCodecPayloadType(sdpLine) {
+ var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
+ var result = sdpLine.match(pattern);
+ return (result && result.length === 2) ? result[1] : null;
+}
+
+// Returns a new m= line with the specified codec as the first one.
+function setDefaultCodec(mLine, payload) {
+ var elements = mLine.split(' ');
+
+ // Just copy the first three parameters; codec order starts on fourth.
+ var newLine = elements.slice(0, 3);
+
+ // Put target payload first and copy in the rest.
+ newLine.push(payload);
+ for (var i = 3; i < elements.length; i++) {
+ if (elements[i] !== payload) {
+ newLine.push(elements[i]);
+ }
+ }
+ return newLine.join(' ');
+}
+
+// query getStats every second
+window.setInterval(function() {
+ if (!window.pc1) {
+ return;
+ }
+ window.pc1.getStats(null).then(function(res) {
+ res.forEach(function(report) {
+ var bytes;
+ var packets;
+ var now = report.timestamp;
+ if ((report.type === 'outboundrtp') ||
+ (report.type === 'outbound-rtp') ||
+ (report.type === 'ssrc' && report.bytesSent)) {
+ bytes = report.bytesSent;
+ packets = report.packetsSent;
+ if (lastResult && lastResult.get(report.id)) {
+ // calculate bitrate
+ var bitrate = 8 * (bytes - lastResult.get(report.id).bytesSent) /
+ (now - lastResult.get(report.id).timestamp);
+
+ // append to chart
+ bitrateSeries.addPoint(now, bitrate);
+ bitrateGraph.setDataSeries([bitrateSeries]);
+ bitrateGraph.updateEndDate();
+
+ // calculate number of packets and append to chart
+ packetSeries.addPoint(now, packets -
+ lastResult.get(report.id).packetsSent);
+ packetGraph.setDataSeries([packetSeries]);
+ packetGraph.updateEndDate();
+ }
+ }
+ });
+ lastResult = res;
+ });
+}, 1000);
« no previous file with comments | « tools/perf/page_sets/webrtc_cases/audio.html ('k') | tools/perf/page_sets/webrtc_cases/canvas-capture.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698