Update device orientation & motion permission native SPI as per latest proposal
[WebKit-https.git] / LayoutTests / webrtc / video-stats.html
1 <!doctype html>
2 <html>
3     <head>
4         <meta charset="utf-8">
5         <title>Testing basic video exchange from offerer to receiver</title>
6         <script src="../resources/testharness.js"></script>
7         <script src="../resources/testharnessreport.js"></script>
8     </head>
9     <body>
10         <script src ="routines.js"></script>
11         <script>
12 function getStatsType(connection)
13 {
14     return connection.getStats().then((report) => {
15         var reportTypes = [];
16         report.forEach((statItem) => {
17             if (reportTypes.indexOf(statItem.type) === -1)
18                 reportTypes.push(statItem.type);
19         });
20         return reportTypes.sort();
21     });
22 }
23
24 function checkStatsReportIterator(report)
25 {
26     assert_equals(Object.getOwnPropertyDescriptor(report.__proto__, Symbol.iterator).value, Object.getOwnPropertyDescriptor(report.__proto__, 'entries').value);
27     assert_equals(Object.getOwnPropertyDescriptor(report.__proto__, Symbol.iterator).value.name, "entries");
28     for (let pair of report)
29         assert_equals(pair.length, 2);
30 }
31
32 function getInboundRTPStats(connection)
33 {
34     return connection.getStats().then((report) => {
35         checkStatsReportIterator(report);
36         var stats;
37         report.forEach((statItem) => {
38             if (statItem.type === "inbound-rtp") {
39                 stats = statItem;
40             }
41         });
42         return stats;
43     });
44 }
45
46 function getOutboundRTPStats(connection)
47 {
48     return connection.getStats().then((report) => {
49         checkStatsReportIterator(report);
50         var stats;
51         report.forEach((statItem) => {
52             if (statItem.type === "outbound-rtp") {
53                 stats = statItem;
54             }
55         });
56         return stats;
57     });
58 }
59
60 function testTimestampDifference(timeStampDifference, numberOfFrames)
61 {
62     // Let's ensure timestamp is not in microseconds but milliseconds.
63     return timeStampDifference > 100000 * (numberOfFrames / 30.0);
64 }
65
66 function checkInboundFramesNumberIncreased(secondConnection, statsSecondConnection, count)
67 {
68     return getInboundRTPStats(secondConnection).then((stats) => {
69         if (stats.framesDecoded > statsSecondConnection.framesDecoded) {
70             if (testTimestampDifference(stats.timestamp - statsSecondConnection.timestamp, stats.framesDecoded - statsSecondConnection.framesDecoded))
71                 return Promise.reject("timestamp and frames increment do not match");
72             assert_not_equals(Object.keys(stats).indexOf("codecId"), -1, "codecId");
73             assert_not_equals(Object.keys(stats).indexOf("trackId"), -1, "trackId");
74             return;
75         }
76         if (++count === 20)
77             return Promise.reject("checking inbound stats frame number increasing timed out");
78         return waitFor(50).then(() => {
79             return checkInboundFramesNumberIncreased(secondConnection, statsSecondConnection, count)
80         });
81     });
82 }
83
84 function checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, count)
85 {
86     return getOutboundRTPStats(firstConnection).then((stats) => {
87         if (stats.framesEncoded > statsFirstConnection.framesEncoded) {
88             if (testTimestampDifference(stats.timestamp - statsFirstConnection.timestamp, stats.framesEncoded - statsFirstConnection.framesEncoded))
89                 return Promise.reject("timestamp and frames increment do not match");
90             assert_not_equals(Object.keys(stats).indexOf("codecId"), -1, "codecId");
91             assert_not_equals(Object.keys(stats).indexOf("trackId"), -1, "trackId");
92             return;
93         }
94         if (++count === 20)
95             return Promise.reject("checking outbound stats frame number increasing timed out");
96         return waitFor(50).then(() => {
97             return checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, count)
98         });
99     });
100 }
101
102 var firstConnection, secondConnection;
103 promise_test(async (test) => {
104     if (window.testRunner)
105         testRunner.setUserMediaPermission(true);
106
107     const localStream = await navigator.mediaDevices.getUserMedia({ video: true});
108     await new Promise((resolve, reject) => {
109         createConnections((connection) => {
110             firstConnection = connection;
111             firstConnection.addTrack(localStream.getVideoTracks()[0], localStream);
112         }, (connection) => {
113             secondConnection = connection;
114             secondConnection.addTrack(localStream.getVideoTracks()[0], localStream);
115             secondConnection.ontrack = (trackEvent) => {
116                 resolve();
117             };
118         });
119         setTimeout(() => reject("Test timed out"), 5000);
120     });
121
122     let stats = await getOutboundRTPStats(firstConnection);
123     assert_true(!!stats, "outbound-rtp stats should not be null");
124     assert_true(Number.isInteger(stats.framesEncoded), "framesEncoded should be an integer");
125     assert_true(Number.isInteger(stats.qpSum), "outbound qpSum should be an integer");
126     assert_true(typeof stats.timestamp === "number", "timestamp should be a double");
127     statsFirstConnection = stats;
128
129     stats = await getInboundRTPStats(secondConnection);
130     assert_true(!!stats, "inbound-rtp stats should not be null");
131     assert_true(Number.isInteger(stats.framesDecoded), "framesDecoded should be an integer");
132     assert_true(Number.isInteger(stats.qpSum), "inbound qpSum should be an integer");
133     assert_true(typeof stats.timestamp === "number", "timestamp should be a double");
134     statsSecondConnection = stats;
135
136     await checkInboundFramesNumberIncreased(secondConnection, statsSecondConnection, 0);
137     await checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, 0);
138
139     let types = await getStatsType(firstConnection);
140     assert_array_equals(types, ["candidate-pair", "certificate", "codec", "inbound-rtp", "local-candidate", "outbound-rtp", "peer-connection", "remote-candidate", "track", "transport"]);
141
142     types = await getStatsType(secondConnection);
143     assert_array_equals(types, ["candidate-pair", "certificate", "codec", "inbound-rtp", "local-candidate", "outbound-rtp", "peer-connection", "remote-candidate", "track", "transport"]);
144 }, "Basic video stats");
145
146 promise_test(async (test) => {
147     const report = await firstConnection.getSenders()[0].getStats();
148     checkStatsReportIterator(report);
149     var instats, outstats;
150     report.forEach((statItem) => {
151         if (statItem.type === "outbound-rtp")
152             outstats = statItem;
153         else if (statItem.type === "inbound-rtp")
154             instats = statItem;
155     });
156     assert_true(!!outstats);
157     assert_false(!!instats);
158 }, "Sender stats");
159
160 promise_test(async (test) => {
161     const report = await secondConnection.getReceivers()[0].getStats();
162     checkStatsReportIterator(report);
163     var instats, outstats;
164     report.forEach((statItem) => {
165         if (statItem.type === "outbound-rtp")
166             outstats = statItem;
167         else if (statItem.type === "inbound-rtp")
168             instats = statItem;
169     });
170     assert_false(!!outstats);
171     assert_true(!!instats);
172 }, "Receiver stats");
173
174 promise_test(async (test) => {
175     let instats1, instats2;
176
177     let report1 = await secondConnection.getReceivers()[0].getStats();
178     report1.forEach((statItem) => {
179         if (statItem.type === "inbound-rtp")
180             instats1 = statItem;
181     });
182     waitFor(50);
183     let report2 = await secondConnection.getReceivers()[0].getStats();
184     report2.forEach((statItem) => {
185         if (statItem.type === "inbound-rtp")
186             instats2 = statItem;
187     });
188     assert_equals(instats1.ssrc, instats2.ssrc);
189 }, "Check ssrc is not changing in inbound rtp stats");
190         </script>
191     </body>
192 </html>