Skip to content

Commit d33fe79

Browse files
committed
Add playback stats for WebRTC and add test codes
1 parent 5879368 commit d33fe79

File tree

4 files changed

+260
-10
lines changed

4 files changed

+260
-10
lines changed

src/main/js/peer_stats.js

+34-3
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,44 @@ export class PeerStats {
6666
this.lastBytesSent = 0;
6767

6868
/**
69+
* @deprecated use videoPacketsSent
6970
* The total number of video packets sent.
7071
* @type {number}
7172
*/
7273
this.totalVideoPacketsSent = 0;
74+
/**
75+
* The total number of video packets sent.
76+
* @type {number}
77+
*/
78+
this.videoPacketsSent = 0;
79+
/**
80+
* The total number of video packets received.
81+
* @type {number}
82+
*/
83+
this.videoPacketsReceived = 0;
84+
7385

7486
/**
75-
* The total number of audio packets sent.
87+
* @deprecated use audioPacketsSent
88+
* The total number of audio packets sent.
7689
* @type {number}
7790
*/
7891
this.totalAudioPacketsSent = 0;
79-
80-
/**
92+
93+
/**
94+
*
95+
* The total number of audio packets sent.
96+
* @type {number}
97+
*/
98+
this.audioPacketsSent = 0;
99+
/*
100+
* The total number of audio packets received.
101+
* @type {number}
102+
*
103+
* */
104+
this.audioPacketsReceived = 0;
105+
106+
/**
81107
* The current timestamp.
82108
* @type {number}
83109
*/
@@ -216,6 +242,11 @@ export class PeerStats {
216242
* @type {*[]}
217243
*/
218244
this.inboundRtpList = [];
245+
246+
/**
247+
* The current round trip time for the candidate pair
248+
*/
249+
this.currentRoundTripTime = 0;
219250
}
220251
//kbits/sec
221252
get averageOutgoingBitrate() {

src/main/js/webrtc_adaptor.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -1499,26 +1499,37 @@ export class WebRTCAdaptor {
14991499
var audioJitterAverageDelay = -1;
15001500
var videoJitterAverageDelay = -1;
15011501
var availableOutgoingBitrate = Infinity;
1502+
var currentRoundTripTime = -1;
1503+
1504+
var audioPacketsReceived = -1;
1505+
var videoPacketsReceived = -1;
15021506

15031507
var inboundRtp = [];
15041508

15051509
stats.forEach(value => {
15061510
//Logger.debug(value);
15071511
if (value.type == "inbound-rtp" && typeof value.kind != "undefined") {
1512+
//this is coming when webrtc playing
1513+
15081514
let inboundRtpObj = {};
15091515

15101516
inboundRtpObj.trackIdentifier = value.trackIdentifier;
15111517

15121518
bytesReceived += value.bytesReceived;
15131519
if (value.kind == "audio") {
15141520
audioPacketsLost = value.packetsLost;
1521+
audioJitter = value.jitter;
1522+
audioPacketsReceived = value.packetsReceived;
1523+
15151524
inboundRtpObj.audioPacketsLost = value.packetsLost;
15161525
} else if (value.kind == "video") {
15171526
videoPacketsLost = value.packetsLost;
15181527
inboundRtpObj.videoPacketsLost = value.packetsLost;
15191528
inboundRtpObj.framesDropped = value.framesDropped;
15201529
inboundRtpObj.framesDecoded = value.framesDecoded;
15211530
inboundRtpObj.framesPerSecond = value.framesPerSecond;
1531+
videoJitter = value.jitter;
1532+
videoPacketsReceived = value.packetsReceived;
15221533
}
15231534

15241535
inboundRtpObj.bytesReceived = value.bytesReceived;
@@ -1556,7 +1567,11 @@ export class WebRTCAdaptor {
15561567

15571568
inboundRtp.push(inboundRtpObj);
15581569

1559-
} else if (value.type == "outbound-rtp") {//TODO: SPLIT AUDIO AND VIDEO BITRATES
1570+
}
1571+
else if (value.type == "outbound-rtp")
1572+
{
1573+
//TODO: SPLIT AUDIO AND VIDEO BITRATES
1574+
//it is for the publishing
15601575
if (value.kind == "audio") {
15611576
audioPacketsSent = value.packetsSent;
15621577
} else if (value.kind == "video") {
@@ -1640,6 +1655,8 @@ export class WebRTCAdaptor {
16401655
}
16411656
else if(value.type == "candidate-pair" && value.state == "succeeded" && value.availableOutgoingBitrate !=undefined){
16421657
availableOutgoingBitrate = value.availableOutgoingBitrate/1000
1658+
//currentRoundTripTime
1659+
currentRoundTripTime = value.currentRoundTripTime;
16431660
}
16441661
});
16451662

@@ -1655,6 +1672,9 @@ export class WebRTCAdaptor {
16551672
this.remotePeerConnectionStats[streamId].totalBytesSent = bytesSent;
16561673
this.remotePeerConnectionStats[streamId].totalVideoPacketsSent = videoPacketsSent;
16571674
this.remotePeerConnectionStats[streamId].totalAudioPacketsSent = audioPacketsSent;
1675+
this.remotePeerConnectionStats[streamId].videoPacketsSent = videoPacketsSent;
1676+
this.remotePeerConnectionStats[streamId].audioPacketsSent = audioPacketsSent;
1677+
16581678
this.remotePeerConnectionStats[streamId].audioLevel = audioLevel;
16591679
this.remotePeerConnectionStats[streamId].qualityLimitationReason = qlr;
16601680
this.remotePeerConnectionStats[streamId].totalFramesEncoded = framesEncoded;
@@ -1676,9 +1696,13 @@ export class WebRTCAdaptor {
16761696
this.remotePeerConnectionStats[streamId].availableOutgoingBitrate = availableOutgoingBitrate;
16771697

16781698
this.remotePeerConnectionStats[streamId].inboundRtpList = inboundRtp;
1699+
1700+
this.remotePeerConnectionStats[streamId].currentRoundTripTime = currentRoundTripTime;
1701+
this.remotePeerConnectionStats[streamId].audioPacketsReceived = audioPacketsReceived;
1702+
this.remotePeerConnectionStats[streamId].videoPacketsReceived = videoPacketsReceived;
16791703

16801704
this.notifyEventListeners("updated_stats", this.remotePeerConnectionStats[streamId]);
1681-
resolve(true);
1705+
resolve(this.remotePeerConnectionStats[streamId]);
16821706
}).catch(err=>{
16831707
resolve(false);
16841708
});

src/main/js/websocket_adaptor.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ export class WebSocketAdaptor {
5050

5151
this.wsConn = new WebSocket(this.websocket_url);
5252
this.wsConn.onopen = () => {
53-
if (this.debug) {
54-
Logger.debug("websocket connected");
55-
}
53+
Logger.debug("websocket connected");
54+
5655

5756
this.pingTimerId = setInterval(() => {
5857
this.sendPing();
@@ -182,7 +181,7 @@ export class WebSocketAdaptor {
182181
}
183182
}
184183
catch (error) {
185-
Logger.warn("Cannot send message:" + text);
184+
Logger.warn("Make sure you call methods after you receive initialized callback. Cannot send message:" + text + " Error is " + error);
186185
}
187186
}
188187

src/test/js/webrtc_adaptor.test.js

+197-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ describe("WebRTCAdaptor", function() {
1212
var initialized = false;
1313

1414
var currentTest;
15+
16+
var processStarted = false;
1517

1618
beforeEach(function() {
1719
clock = sinon.useFakeTimers();
@@ -197,7 +199,7 @@ describe("WebRTCAdaptor", function() {
197199
});
198200

199201

200-
it.only("should set connected and connecting to false and log the correct message", function() {
202+
it("should set connected and connecting to false and log the correct message", function() {
201203

202204
var adaptor = new WebRTCAdaptor({
203205
websocketURL: "ws://example.com",
@@ -1711,6 +1713,200 @@ describe("WebRTCAdaptor", function() {
17111713

17121714

17131715
});
1716+
1717+
it("WebRTCGetStats", async function()
1718+
{
1719+
1720+
clock.restore();
1721+
1722+
this.timeout(15000);
1723+
1724+
var websocketURL = "wss://test.antmedia.io/live/websocket";
1725+
processStarted = false;
1726+
initialized = false;
1727+
var adaptor = new WebRTCAdaptor({
1728+
websocketURL: websocketURL,
1729+
callback: (info, obj) => {
1730+
console.log("callback info: " + info);
1731+
if (info == "initialized") {
1732+
initialized = true;
1733+
}
1734+
else if (info == "publish_started") {
1735+
console.log("publish started");
1736+
processStarted = true;
1737+
}
1738+
else if (info == "publish_finished") {
1739+
console.log("publish finished")
1740+
}
1741+
},
1742+
});
1743+
1744+
await new Promise((resolve, reject)=>{
1745+
setTimeout(()=> {
1746+
resolve();
1747+
}, 3000);
1748+
});
1749+
1750+
expect(initialized).to.be.true;
1751+
1752+
var streamId = "stream1desadafg23424";
1753+
1754+
adaptor.publish(streamId);
1755+
1756+
await new Promise((resolve, reject)=>{
1757+
1758+
setTimeout(()=> {
1759+
expect(processStarted).to.be.true;
1760+
resolve();
1761+
}, 3000);
1762+
});
1763+
1764+
//getStats
1765+
var peerStats = await adaptor.getStats(streamId);
1766+
1767+
console.log("publish peerStats: " + JSON.stringify(peerStats));
1768+
expect(peerStats.streamId).to.be.equal(streamId);
1769+
expect(peerStats.audioPacketsSent).to.be.above(0);
1770+
expect(peerStats.videoPacketsSent).to.be.above(0);
1771+
expect(peerStats.frameWidth).to.be.above(0);
1772+
expect(peerStats.frameHeight).to.be.above(0);
1773+
expect(peerStats.currentRoundTripTime).to.be.above(0);
1774+
expect(peerStats.currentRoundTripTime).to.be.most(1);
1775+
1776+
expect(peerStats.videoPacketsLost).to.be.least(0);
1777+
expect(peerStats.audioPacketsLost).to.be.least(0);
1778+
expect(peerStats.videoJitter).to.be.least(0);
1779+
expect(peerStats.audioJitter).to.be.least(0);
1780+
expect(peerStats.totalBytesSentCount).to.be.above(0);
1781+
expect(peerStats.lastFramesEncoded).to.be.above(0);
1782+
expect(peerStats.totalFramesEncodedCount).to.be.above(0);
1783+
expect(peerStats.frameWidth).to.be.equal(640);
1784+
expect(peerStats.frameHeight).to.be.equal(480);
1785+
expect(peerStats.qualityLimitationReason).to.be.equal("none");
1786+
expect(peerStats.firstByteSentCount).to.be.not.equal(0);
1787+
expect(peerStats.srcFps).to.be.above(0);
1788+
expect(peerStats.videoRoundTripTime).to.be.above(0);
1789+
//expect(peerStats.audioRoundTripTime).to.be.above(0);
1790+
expect(peerStats.availableOutgoingBitrate).to.be.above(0);
1791+
1792+
1793+
1794+
1795+
expect(peerStats.totalBytesReceivedCount).to.be.equal(-1);
1796+
expect(peerStats.lastBytesSent).to.be.equal(0);
1797+
expect(peerStats.videoPacketsLost).to.be.equal(0);
1798+
expect(peerStats.fractionLost).to.be.equal(-1);
1799+
expect(peerStats.startTime).to.be.not.equal(0);
1800+
expect(peerStats.lastBytesReceived).to.be.equal(0);
1801+
expect(peerStats.currentTimestamp).to.be.not.equal(0);
1802+
expect(peerStats.lastTime).to.be.equal(0);
1803+
expect(peerStats.timerId).to.be.equal(0);
1804+
expect(peerStats.firstBytesReceivedCount).to.be.equal(-1);
1805+
expect(peerStats.audioLevel).to.be.equal(-1);
1806+
expect(peerStats.resWidth).to.be.equal(640);
1807+
expect(peerStats.resHeight).to.be.equal(480);
1808+
expect(peerStats.framesReceived).to.be.equal(-1);
1809+
expect(peerStats.framesDropped).to.be.equal(-1);
1810+
expect(peerStats.framesDecoded).to.be.equal(-1);
1811+
expect(peerStats.audioJitterAverageDelay).to.be.equal(-1);
1812+
expect(peerStats.videoJitterAverageDelay).to.be.equal(-1);
1813+
expect(peerStats.inboundRtpList).to.be.empty;
1814+
expect(peerStats.audioPacketsReceived).to.be.equal(-1);
1815+
expect(peerStats.videoPacketsReceived).to.be.equal(-1);
1816+
1817+
//getStats
1818+
processStarted = false;
1819+
initialized = false;
1820+
var playAdaptor = new WebRTCAdaptor({
1821+
websocketURL: websocketURL,
1822+
callback: (info, obj) => {
1823+
console.log("callback info: " + info);
1824+
if (info == "initialized") {
1825+
initialized = true;
1826+
}
1827+
else if (info == "play_started") {
1828+
console.log("play started");
1829+
processStarted = true;
1830+
}
1831+
else if (info == "play_finished") {
1832+
console.log("play finished")
1833+
}
1834+
},
1835+
});
1836+
await new Promise((resolve, reject)=>{
1837+
setTimeout(()=> {
1838+
resolve();
1839+
}, 3000);
1840+
});
1841+
1842+
expect(initialized).to.be.true;
1843+
1844+
playAdaptor.play(streamId);
1845+
1846+
await new Promise((resolve, reject)=>{
1847+
1848+
setTimeout(()=> {
1849+
expect(processStarted).to.be.true;
1850+
resolve();
1851+
}, 3000);
1852+
});
1853+
1854+
peerStats = await playAdaptor.getStats(streamId);
1855+
1856+
console.log("play peerStats: " + JSON.stringify(peerStats));
1857+
expect(peerStats.streamId).to.be.equal(streamId);
1858+
expect(peerStats.frameWidth).to.be.equal(640);
1859+
expect(peerStats.frameHeight).to.be.equal(480);
1860+
expect(peerStats.currentRoundTripTime).to.be.above(0);
1861+
expect(peerStats.currentRoundTripTime).to.be.most(1);
1862+
1863+
expect(peerStats.videoPacketsLost).to.be.least(0);
1864+
expect(peerStats.audioPacketsLost).to.be.least(0);
1865+
expect(peerStats.videoJitter).to.be.least(0);
1866+
expect(peerStats.audioJitter).to.be.least(0);
1867+
expect(peerStats.lastFramesEncoded).to.be.equal(-1);
1868+
expect(peerStats.totalFramesEncodedCount).to.be.equal(-1);
1869+
expect(peerStats.frameWidth).to.be.equal(640);
1870+
expect(peerStats.frameHeight).to.be.equal(480);
1871+
expect(peerStats.qualityLimitationReason).to.be.equal("");
1872+
expect(peerStats.firstByteSentCount).to.be.not.equal(0);
1873+
expect(peerStats.srcFps).to.be.equal(-1);
1874+
expect(peerStats.videoRoundTripTime).to.be.equal(-1);
1875+
expect(peerStats.audioRoundTripTime).to.be.equal(-1);
1876+
expect(peerStats.availableOutgoingBitrate).to.be.above(-1);
1877+
1878+
1879+
1880+
1881+
expect(peerStats.totalBytesReceivedCount).to.be.above(0);
1882+
expect(peerStats.lastBytesSent).to.be.equal(0);
1883+
expect(peerStats.videoPacketsLost).to.be.equal(0);
1884+
//expect(peerStats.fractionLost).to.be.equal(-1);
1885+
expect(peerStats.startTime).to.be.not.equal(0);
1886+
expect(peerStats.lastBytesReceived).to.be.equal(0);
1887+
expect(peerStats.currentTimestamp).to.be.not.equal(0);
1888+
expect(peerStats.lastTime).to.be.equal(0);
1889+
expect(peerStats.timerId).to.be.equal(0);
1890+
expect(peerStats.firstBytesReceivedCount).to.be.above(0);
1891+
expect(peerStats.audioLevel).to.be.equal(-1);
1892+
expect(peerStats.resWidth).to.be.equal(-1);
1893+
expect(peerStats.resHeight).to.be.equal(-1);
1894+
expect(peerStats.framesReceived).to.be.above(0);
1895+
expect(peerStats.framesDropped).to.be.least(0);
1896+
expect(peerStats.framesDecoded).to.be.above(0);
1897+
expect(peerStats.audioJitterAverageDelay).to.be.equal(-1);
1898+
expect(peerStats.videoJitterAverageDelay).to.be.equal(-1);
1899+
expect(peerStats.audioPacketsReceived).to.be.above(0);
1900+
expect(peerStats.videoPacketsReceived).to.be.above(0);
1901+
1902+
1903+
expect(peerStats.totalBytesSentCount).to.be.equal(-1);
1904+
expect(peerStats.totalAudioPacketsSent).to.be.equal(-1);
1905+
expect(peerStats.totalVideoPacketsSent).to.be.equal(-1);
1906+
1907+
1908+
1909+
});
17141910

17151911

17161912

0 commit comments

Comments
 (0)