@@ -6,19 +6,28 @@ let stopped = false;
6
6
let preferredCodec = "VP8" ;
7
7
let mode = "L1T3" ;
8
8
let latencyPref = "realtime" , bitPref = "variable" ;
9
- let hw = "no-preference" ;
9
+ let encHw = "no-preference" , decHw = "no-preference" ;
10
10
let streamWorker ;
11
11
let inputStream , outputStream ;
12
- let videoSource ;
12
+ let metrics = {
13
+ all : [ ] ,
14
+ } ;
15
+ let e2e = {
16
+ all : [ ] ,
17
+ } ;
18
+
13
19
const rate = document . querySelector ( '#rate' ) ;
14
20
const connectButton = document . querySelector ( '#connect' ) ;
15
21
const stopButton = document . querySelector ( '#stop' ) ;
16
22
const codecButtons = document . querySelector ( '#codecButtons' ) ;
17
23
const resButtons = document . querySelector ( '#resButtons' ) ;
18
24
const modeButtons = document . querySelector ( '#modeButtons' ) ;
19
- const hwButtons = document . querySelector ( '#hwButtons' ) ;
25
+ const decHwButtons = document . querySelector ( '#decHwButtons' ) ;
26
+ const encHwButtons = document . querySelector ( '#encHwButtons' ) ;
27
+ const chart2_div = document . getElementById ( 'chart2_div' ) ;
20
28
const videoSelect = document . querySelector ( 'select#videoSource' ) ;
21
29
const selectors = [ videoSelect ] ;
30
+ chart2_div . style . display = "none" ;
22
31
connectButton . disabled = false ;
23
32
stopButton . disabled = true ;
24
33
@@ -36,6 +45,34 @@ const eightKConstraints = {video: {width: {min: 7680}, height: {min: 4320}}};
36
45
37
46
let constraints = qvgaConstraints ;
38
47
48
+ function metrics_update ( data ) {
49
+ metrics . all . push ( data ) ;
50
+ }
51
+
52
+ function metrics_report ( ) {
53
+ metrics . all . sort ( ( a , b ) => {
54
+ return ( 100000 * ( a . mediaTime - b . mediaTime ) + a . output - b . output ) ;
55
+ } ) ;
56
+ const len = metrics . all . length ;
57
+ let j = 0 ;
58
+ for ( let i = 0 ; i < len ; i ++ ) {
59
+ if ( metrics . all [ i ] . output == 1 ) {
60
+ const frameno = metrics . all [ i ] . presentedFrames ;
61
+ const g2g = metrics . all [ i ] . expectedDisplayTime - metrics . all [ i - 1 ] . captureTime ;
62
+ const mediaTime = metrics . all [ i ] . mediaTime ;
63
+ const captureTime = metrics . all [ i - 1 ] . captureTime ;
64
+ const expectedDisplayTime = metrics . all [ i ] . expectedDisplayTime ;
65
+ const delay = metrics . all [ i ] . expectedDisplayTime - metrics . all [ i - 1 ] . expectedDisplayTime ;
66
+ const data = [ frameno , g2g ] ;
67
+ e2e . all . push ( data ) ;
68
+ }
69
+ }
70
+ // addToEventLog('Data dump: ' + JSON.stringify(e2e.all));
71
+ return {
72
+ count : e2e . all . length
73
+ } ;
74
+ }
75
+
39
76
function addToEventLog ( text , severity = 'info' ) {
40
77
let log = document . querySelector ( 'textarea' ) ;
41
78
log . value += 'log-' + severity + ': ' + text + '\n' ;
@@ -132,15 +169,21 @@ function getModeValue(radio) {
132
169
addToEventLog ( 'Mode selected: ' + mode ) ;
133
170
}
134
171
135
- function getHwValue ( radio ) {
136
- hw = radio . value ;
137
- addToEventLog ( 'Hardware Acceleration preference: ' + hw ) ;
172
+ function getDecHwValue ( radio ) {
173
+ decHw = radio . value ;
174
+ addToEventLog ( 'Decoder Hardware Acceleration preference: ' + decHw ) ;
175
+ }
176
+
177
+ function getEncHwValue ( radio ) {
178
+ encHw = radio . value ;
179
+ addToEventLog ( 'Encoder Hardware Acceleration preference: ' + encHw ) ;
138
180
}
139
181
140
182
function stop ( ) {
141
183
stopped = true ;
142
184
stopButton . disabled = true ;
143
185
connectButton . disabled = true ;
186
+ chart2_div . style . display = "initial" ;
144
187
streamWorker . postMessage ( { type : "stop" } ) ;
145
188
try {
146
189
inputStream . cancel ( ) ;
@@ -159,13 +202,15 @@ function stop() {
159
202
document . addEventListener ( 'DOMContentLoaded' , async function ( event ) {
160
203
if ( stopped ) return ;
161
204
addToEventLog ( 'DOM Content Loaded' ) ;
162
-
163
- if ( typeof MediaStreamTrackProcessor === 'undefined' ||
164
- typeof MediaStreamTrackGenerator === 'undefined' ) {
165
- addToEventLog ( 'Your browser does not support the experimental Mediacapture-transform API.\n' +
166
- 'Please launch with the --enable-blink-features=WebCodecs,MediaStreamInsertableStreams flag' , 'fatal' ) ;
205
+
206
+ // Need to support standard mediacapture-transform implementations
207
+
208
+ if ( typeof MediaStreamTrackProcessor === 'undefined' ||
209
+ typeof MediaStreamTrackGenerator === 'undefined' ) {
210
+ addToEventLog ( 'Your browser does not support the MSTP and MSTG APIs.' , 'fatal' ) ;
167
211
return ;
168
- }
212
+ }
213
+
169
214
try {
170
215
gotDevices ( await navigator . mediaDevices . enumerateDevices ( ) ) ;
171
216
} catch ( e ) {
@@ -179,9 +224,32 @@ document.addEventListener('DOMContentLoaded', async function(event) {
179
224
// Create a new worker.
180
225
streamWorker = new Worker ( "js/stream_worker.js" ) ;
181
226
addToEventLog ( 'Worker created.' ) ;
182
- // Print messages from the worker in the text area.
227
+
183
228
streamWorker . addEventListener ( 'message' , function ( e ) {
184
- addToEventLog ( 'Worker msg: ' + e . data . text , e . data . severity ) ;
229
+ if ( e . data . severity != 'chart' ) {
230
+ addToEventLog ( 'Worker msg: ' + e . data . text , e . data . severity ) ;
231
+ } else {
232
+ // draw the glass-glass latency chart
233
+ metrics_report ( ) ;
234
+ google . charts . load ( 'current' , { 'packages' :[ 'corechart' ] } ) ;
235
+ google . charts . setOnLoadCallback ( ( ) => {
236
+ let data = new google . visualization . DataTable ( ) ;
237
+ // addToEventLog('Data dump: ' + JSON.stringify(e2e.all));
238
+ data . addColumn ( 'number' , 'Frame Number' ) ;
239
+ data . addColumn ( 'number' , 'Glass-Glass Latency (ms)' ) ;
240
+ data . addRows ( e2e . all ) ;
241
+ let options = {
242
+ width : 900 ,
243
+ height : 500 ,
244
+ title : 'Glass-Glass Latency (ms) versus Frame Number' ,
245
+ haxis : { title : 'Frame Number' } ,
246
+ vaxis : { title : 'Glass-Glass Latency' } ,
247
+ legend : 'none'
248
+ } ;
249
+ let chart = new google . visualization . ScatterChart ( chart2_div ) ;
250
+ chart . draw ( data , options ) ;
251
+ } ) ;
252
+ }
185
253
} , false ) ;
186
254
187
255
stopButton . onclick = ( ) => {
@@ -192,7 +260,8 @@ document.addEventListener('DOMContentLoaded', async function(event) {
192
260
connectButton . onclick = ( ) => {
193
261
connectButton . disabled = true ;
194
262
stopButton . disabled = false ;
195
- hwButtons . style . display = "none" ;
263
+ decHwButtons . style . display = "none" ;
264
+ encHwButtons . style . display = "none" ;
196
265
prefButtons . style . display = "none" ;
197
266
bitButtons . style . display = "none" ;
198
267
codecButtons . style . display = "none" ;
@@ -226,6 +295,36 @@ document.addEventListener('DOMContentLoaded', async function(event) {
226
295
outputStream = generator . writable ;
227
296
document . getElementById ( 'outputVideo' ) . srcObject = new MediaStream ( [ generator ] ) ;
228
297
298
+ // Initialize variables
299
+ let paint_count = 0 ;
300
+ let start_time = 0.0 ;
301
+
302
+ const recordOutputFrames = ( now , metadata ) => {
303
+ metadata . output = 1. ;
304
+ metadata . time = now ;
305
+ if ( start_time == 0.0 ) start_time = now ;
306
+ let elapsed = ( now - start_time ) / 1000. ;
307
+ let fps = ( ++ paint_count / elapsed ) . toFixed ( 3 ) ;
308
+ metadata . fps = fps ;
309
+ metrics_update ( metadata ) ;
310
+ outputVideo . requestVideoFrameCallback ( recordOutputFrames ) ;
311
+ } ;
312
+
313
+ outputVideo . requestVideoFrameCallback ( recordOutputFrames ) ;
314
+
315
+ const recordInputFrames = ( now , metadata ) => {
316
+ metadata . output = 0 ;
317
+ metadata . time = now ;
318
+ if ( start_time == 0.0 ) start_time = now ;
319
+ let elapsed = ( now - start_time ) / 1000. ;
320
+ let fps = ( ++ paint_count / elapsed ) . toFixed ( 3 ) ;
321
+ metadata . fps = fps ;
322
+ metrics_update ( metadata ) ;
323
+ inputVideo . requestVideoFrameCallback ( recordInputFrames ) ;
324
+ } ;
325
+
326
+ inputVideo . requestVideoFrameCallback ( recordInputFrames ) ;
327
+
229
328
//Create video Encoder configuration
230
329
const vConfig = {
231
330
keyInterval : keygap ,
@@ -244,7 +343,8 @@ document.addEventListener('DOMContentLoaded', async function(event) {
244
343
codec : preferredCodec ,
245
344
width : ts . width / vConfig . resolutionScale ,
246
345
height : ts . height / vConfig . resolutionScale ,
247
- hardwareAcceleration : hw ,
346
+ hardwareAcceleration : encHw ,
347
+ decHwAcceleration : decHw ,
248
348
bitrate : rate ,
249
349
framerate : ts . frameRate / vConfig . framerateScale ,
250
350
keyInterval : vConfig . keyInterval ,
0 commit comments