Skip to content

Commit

Permalink
decouple from dqp
Browse files Browse the repository at this point in the history
  • Loading branch information
niyatim23 committed Dec 21, 2023
1 parent eed81a2 commit cf0ce35
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 78 deletions.
10 changes: 10 additions & 0 deletions examples/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function getFormValues() {
secretAccessKey: $('#secretAccessKey').val(),
sessionToken: $('#sessionToken').val() || null,
enableDQPmetrics: $('#enableDQPmetrics').is(':checked'),
enableDatachannelBenchmarking: $('#enableDatachannelBenchmarking').is(':checked'),
sendHostCandidates: $('#send-host').is(':checked'),
acceptHostCandidates: $('#accept-host').is(':checked'),
sendRelayCandidates: $('#send-relay').is(':checked'),
Expand Down Expand Up @@ -137,6 +138,10 @@ function onStop() {
$('#webrtc-live-stats').addClass('d-none');
}

if (getFormValues().enableDatachannelBenchmarking) {
$('#datachannel-benchmarking').addClass('d-none');
}

$('#form').removeClass('d-none');
$('#join-storage-session-button').addClass('d-none');
ROLE = null;
Expand Down Expand Up @@ -216,6 +221,10 @@ $('#viewer-button').click(async () => {
$('#webrtc-live-stats').removeClass('d-none');
}

if (formValues.enableDatachannelBenchmarking) {
$('#datachannel-benchmarking').removeClass('d-none');
}

$(remoteMessage).empty();
localMessage.value = '';
toggleDataChannelElements();
Expand Down Expand Up @@ -426,6 +435,7 @@ const fields = [
{ field: 'forceTURN', type: 'radio', name: 'natTraversal' },
{ field: 'natTraversalDisabled', type: 'radio', name: 'natTraversal' },
{ field: 'enableDQPmetrics', type: 'checkbox' },
{ field: 'enableDatachannelBenchmarking', type: 'checkbox' },
{ field: 'send-host', type: 'checkbox' },
{ field: 'accept-host', type: 'checkbox' },
{ field: 'send-relay', type: 'checkbox' },
Expand Down
52 changes: 36 additions & 16 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,18 @@ <h4>Amazon KVS WebRTC DQP</h4>
</div>
</div>

<h4>Amazon KVS WebRTC Datachannel Benchmarking</h4>
<div class="form-group">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="enableDatachannelBenchmarking" value="enableDatachannelBenchmarking">
<label for="enableDatachannelBenchmarking" class="form-check-label">Enable KVS WebRTC Datachannel Benchmarking <small>(Master + Viewer)</small></label>
<span data-delay="{ &quot;hide&quot;: 1500 }" data-position="auto" tabindex="0" class="text-info ml-1" data-toggle="tooltip" data-html="true" title="
<p>Enables the test and metrics for the Amazon KVS WebRTC by sending the master-side metrics to the viewer via datachannel and display a timeline chart.</p>
<a href=&quot;https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-js/tree/develop?tab=readme-ov-file#metrics&quot;>Additional information</a>
"><sup>&#9432;</sup></span>
</div>
</div>

<details><summary class="h4">Advanced</summary>
<p><small>Filter settings for which ICE candidates and sent to and received from the peer.</small></p>
<div class="container">
Expand Down Expand Up @@ -339,26 +351,34 @@ <h5>From Master</h5>
</div>
</div>

<div id="dqpmetrics" class="d-none">
<h3 id="dqpmetrics-header">DQP Test Metrics (from Master)</h3>
<div class="row">
<div class="col">
<div class="card bg-light mb-3">
<div id="dqp-test"></div>
<div>
<div id="dqpmetrics" class="d-none">
<h3 id="dqpmetrics-header">DQP Test Metrics (from Master)</h3>
<div class="row">
<div class="col">
<div class="card bg-light mb-3">
<div id="dqp-test"></div>
</div>
</div>
</div>
<div class="col">
<div class="card bg-light mb-3">
<canvas id="metricsChart" style="width:100%"; height="400px"></canvas>
<div class="col">
<div class="card bg-light mb-3">
<canvas id="metricsChart" style="width:100%"; height="400px"></canvas>
</div>
</div>
</div>
<h3 id="live-stats-header">Live Stats (from Master)</h3>
<div class="card bg-light mb-3">
<div id="webrtc-live-stats"></div>
</div>
</div>
<div class="row">
<div id="timeline-chart" style="width:100%;height:0px"></div>
</div>
<h3 id="live-stats-header">Live Stats (from Master)</h3>
<div class="card bg-light mb-3">
<div id="webrtc-live-stats"></div>
<div id="datachannel-benchmarking" class="d-none" style="padding-top:20px;">
<div class="row">
<div class="col">
<h4 id="datachannel-benchmarking-header"></h4>
<div id="timeline-chart" style="width:100%;height:0px">
</div>
</div>
</div>
</div>
</div>

Expand Down
155 changes: 93 additions & 62 deletions examples/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
const viewer = {};

//globals for DQP metrics and test
const timelineChartTestLength = 20;
const DQPtestLength = 120; //test time in seconds
const DatachannelBenchmarkingTestLength = 20;
let viewerButtonPressed = Date.now();
let initialDate = 0;
let chart = {};
Expand All @@ -16,7 +16,7 @@ let vFDroppedPrev = 0;
let aBytesPrev = 0;
let connectionTime = 0;
let statStartTime = 0;
let timelineChartStartTime = 0;
let benchmarkingStartTime = 0;
let statStartDate = 0;
let rttSum = 0;
let vjitterSum = 0;
Expand Down Expand Up @@ -126,7 +126,7 @@ let metrics = {
tooltip: 'Time to first frame after the viewer\'s peer connection has been established',
color: '#2196F3',
},
video: {
ttff: {
name: 'ttff',
startTime: '',
endTime: '',
Expand Down Expand Up @@ -248,29 +248,38 @@ let dataChannelLatencyCalcMessage = {
async function startViewer(localView, remoteView, formValues, onStatsReport, remoteMessage) {
try {
console.log('[VIEWER] Client id is:', formValues.clientId);
viewerButtonPressed = Date.now();

if (formValues.enableDatachannelBenchmarking) {
setTimeout(dataChannelBenchmarkingCalculations, DatachannelBenchmarkingTestLength * 1000);
}

viewer.localView = localView;
viewer.remoteView = remoteView;

viewer.remoteView.addEventListener('loadeddata', () => {
metrics.viewer.video.endTime = Date.now();
if (formValues.enableDatachannelBenchmarking) {
viewer.remoteView.addEventListener('loadeddata', () => {
metrics.viewer.ttff.endTime = Date.now();

metrics.viewer.ttffAfterPc.endTime = metrics.viewer.video.endTime;
metrics.master.ttffAfterPc.endTime = metrics.viewer.video.endTime;
metrics.viewer.ttffAfterPc.endTime = metrics.viewer.ttff.endTime;
metrics.master.ttffAfterPc.endTime = metrics.viewer.ttff.endTime;


// if the ice-gathering on the master side is not complete by the time the metrics are sent, the endTime > startTime
// in order to plot it, we can show it as an ongoing process
if (metrics.master.iceGathering.startTime > metrics.master.iceGathering.endTime) {
metrics.master.iceGathering.endTime = metrics.viewer.video.endTime;
}
});
// if the ice-gathering on the master side is not complete by the time the metrics are sent, the endTime > startTime
// in order to plot it, we can show it as an ongoing process
if (metrics.master.iceGathering.startTime > metrics.master.iceGathering.endTime) {
metrics.master.iceGathering.endTime = metrics.viewer.ttff.endTime;
}
});
}

if (formValues.enableDQPmetrics) {
viewerButtonPressed = Date.now();
metrics.viewer.video.startTime = viewerButtonPressed;
if (formValues.enableDatachannelBenchmarking) {
metrics.viewer.ttff.startTime = viewerButtonPressed;
metrics.master.waitTime.endTime = viewerButtonPressed;

}

if (formValues.enableDQPmetrics) {
console.log('[WebRTC] DQP METRICS TEST STARTED: ', viewerButtonPressed);

let htmlString = '<table><tr><strong><FONT COLOR=RED>Connecting to MASTER...</FONT></strong></tr></table>';
Expand Down Expand Up @@ -474,41 +483,43 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem
};
viewer.peerConnection = new RTCPeerConnection(configuration);

viewer.peerConnection.onicegatheringstatechange = (event) => {
if (viewer.peerConnection.iceGatheringState === 'gathering') {
metrics.viewer.iceGathering.startTime = Date.now();
} else if (viewer.peerConnection.iceGatheringState === 'complete') {
metrics.viewer.iceGathering.endTime = Date.now();
}
};

viewer.peerConnection.onconnectionstatechange = (event) => {
if (viewer.peerConnection.connectionState === 'new' || viewer.peerConnection.connectionState === 'connecting') {
metrics.viewer.peerConnection.startTime = Date.now();
}
if (viewer.peerConnection.connectionState === 'connected') {
metrics.viewer.peerConnection.endTime = Date.now();
metrics.viewer.ttffAfterPc.startTime = metrics.viewer.peerConnection.endTime;
}
};

viewer.peerConnection.oniceconnectionstatechange = (event) => {
if (viewer.peerConnection.iceConnectionState === 'connected') {
viewer.peerConnection.getStats().then(stats => {
stats.forEach(report => {
if (report.type === 'candidate-pair') {
activeCandidatePair = report;
}
if (formValues.enableDatachannelBenchmarking) {
viewer.peerConnection.onicegatheringstatechange = (event) => {
if (viewer.peerConnection.iceGatheringState === 'gathering') {
metrics.viewer.iceGathering.startTime = Date.now();
} else if (viewer.peerConnection.iceGatheringState === 'complete') {
metrics.viewer.iceGathering.endTime = Date.now();
}
};

viewer.peerConnection.onconnectionstatechange = (event) => {
if (viewer.peerConnection.connectionState === 'new' || viewer.peerConnection.connectionState === 'connecting') {
metrics.viewer.peerConnection.startTime = Date.now();
}
if (viewer.peerConnection.connectionState === 'connected') {
metrics.viewer.peerConnection.endTime = Date.now();
metrics.viewer.ttffAfterPc.startTime = metrics.viewer.peerConnection.endTime;
}
};

viewer.peerConnection.oniceconnectionstatechange = (event) => {
if (viewer.peerConnection.iceConnectionState === 'connected') {
viewer.peerConnection.getStats().then(stats => {
stats.forEach(report => {
if (report.type === 'candidate-pair') {
activeCandidatePair = report;
}
});
});
});
}
};

}
};
}
if (formValues.openDataChannel) {
const dataChannelObj = viewer.peerConnection.createDataChannel('kvsDataChannel');
viewer.dataChannel = dataChannelObj;
dataChannelObj.onopen = () => {
if (formValues.enableDQPmetrics) {
if (formValues.enableDatachannelBenchmarking) {
dataChannelLatencyCalcMessage.firstMessageFromViewerTs = Date.now().toString();
dataChannelObj.send(JSON.stringify(dataChannelLatencyCalcMessage));
} else {
Expand All @@ -519,7 +530,7 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem
let onRemoteDataMessageViewer = (message) => {

remoteMessage.append(`${message.data}\n\n`);
if (formValues.enableDQPmetrics) {
if (formValues.enableDatachannelBenchmarking) {

// The datachannel first sends a message of the following format with firstMessageFromViewerTs attached,
// to which the master responds back with the same message attaching firstMessageFromMasterTs.
Expand Down Expand Up @@ -552,8 +563,8 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem
metrics.master.signaling.startTime = dataChannelMessage.signalingStartTime;
metrics.master.signaling.endTime = dataChannelMessage.signalingEndTime;

if (metrics.viewer.video.startTime < metrics.master.signaling.startTime) {
metrics.viewer.video.startTime = metrics.master.signaling.startTime;
if (metrics.viewer.ttff.startTime < metrics.master.signaling.startTime) {
metrics.viewer.ttff.startTime = metrics.master.signaling.startTime;
}

metrics.master.waitTime.startTime = metrics.master.signaling.endTime;
Expand Down Expand Up @@ -603,6 +614,18 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem
viewer.peerConnectionStatsInterval = setInterval(() => viewer.peerConnection.getStats().then(stats => calcStats(stats, formValues.clientId)), 1000);
}

if (formValues.enableDatachannelBenchmarking) {
benchmarkingStartTime = new Date().getTime();
let headerElement = document.getElementById("datachannel-benchmarking-header");
viewer.dataChannelBenchmarkingInterval = setInterval(() => {
let statRunTime = calcDiffTimestamp2Sec(new Date().getTime(), benchmarkingStartTime);
statRunTime = Number.parseFloat(statRunTime).toFixed(0);
if (statRunTime <= DatachannelBenchmarkingTestLength) {
headerElement.textContent = "Datachannel benchmarking timeline chart available in " + (DatachannelBenchmarkingTestLength - statRunTime);
}
}, 1000);
}

viewer.signalingClient.on('open', async () => {

metrics.viewer.connectAsViewer.endTime = Date.now();
Expand Down Expand Up @@ -773,6 +796,18 @@ function stopViewer() {
chart.destroy();
statStartTime = 0;
}

if (getFormValues().enableDatachannelBenchmarking) {
let container = document.getElementById('timeline-chart');
let headerElement = document.getElementById("datachannel-benchmarking-header");
container.innerHTML = "";
container.style.height = "0px";
if (viewer.dataChannelBenchmarkingInterval) {
clearInterval(viewer.dataChannelBenchmarkingInterval);
}
headerElement.textContent = "";
}

} catch (e) {
console.error('[VIEWER] Encountered error stopping', e);
}
Expand All @@ -794,6 +829,14 @@ function sendViewerMessage(message) {
}
}

function dataChannelBenchmarkingCalculations() {
let headerElement = document.getElementById("datachannel-benchmarking-header");
headerElement.textContent = "Datachannel benchmarking timeline chart";
google.charts.load('current', {packages:['timeline']});
google.charts.setOnLoadCallback(drawChart);
clearInterval(viewer.dataChannelBenchmarkingInterval);
}

// Functions below support DQP test and metrics

// function to calculate difference between two epoch timestamps and return seconds with large being the most recent and small being the oldest.
Expand Down Expand Up @@ -942,18 +985,6 @@ function calcStats(stats, clientId) {
const avgAbitrate = aBitrateSum / count;
const avgAjitter = ajitterSum / count;

if (timelineChartStartTime === 0) {
timelineChartStartTime = currentTime;
}

let timelineChartRunTime = calcDiffTimestamp2Sec(currentTime, timelineChartStartTime);
timelineChartRunTime = Number.parseFloat(timelineChartRunTime).toFixed(0);

if (timelineChartRunTime > timelineChartTestLength) {
google.charts.load('current', {packages:['timeline']});
google.charts.setOnLoadCallback(drawChart);
}

// Display test progress and results
if (statRunTime <= DQPtestLength) {
// prettier-ignore
Expand Down Expand Up @@ -1041,7 +1072,7 @@ function getCalculatedEpoch(time, diffInMillis, minTime) {

function drawChart() {
const viewerOrder = ['signaling', 'describeChannel', 'describeMediaStorageConfiguration', 'channelEndpoint', 'iceServerConfig', 'connectAsViewer', 'setupMediaPlayer', 'waitTime',
'offAnswerTime', 'iceGathering', 'peerConnection', 'dataChannel', 'ttffAfterPc', 'video'];
'offAnswerTime', 'iceGathering', 'peerConnection', 'dataChannel', 'ttffAfterPc', 'ttff'];
const masterOrder = ['signaling', 'describeChannel', 'channelEndpoint', 'iceServerConfig', 'getToken', 'createChannel', 'connectAsMaster', 'waitTime',
'offAnswerTime', 'iceGathering', 'peerConnection', 'dataChannel', 'ttffAfterPc'];
const container = document.getElementById('timeline-chart');
Expand Down

0 comments on commit cf0ce35

Please sign in to comment.