@@ -6,19 +6,28 @@ let stopped = false;
66let preferredCodec = "VP8" ;
77let mode = "L1T3" ;
88let latencyPref = "realtime" , bitPref = "variable" ;
9- let hw = "no-preference" ;
9+ let encHw = "no-preference" , decHw = "no-preference" ;
1010let streamWorker ;
1111let inputStream , outputStream ;
12- let videoSource ;
12+ let metrics = {
13+ all : [ ] ,
14+ } ;
15+ let e2e = {
16+ all : [ ] ,
17+ } ;
18+
1319const rate = document . querySelector ( '#rate' ) ;
1420const connectButton = document . querySelector ( '#connect' ) ;
1521const stopButton = document . querySelector ( '#stop' ) ;
1622const codecButtons = document . querySelector ( '#codecButtons' ) ;
1723const resButtons = document . querySelector ( '#resButtons' ) ;
1824const 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' ) ;
2028const videoSelect = document . querySelector ( 'select#videoSource' ) ;
2129const selectors = [ videoSelect ] ;
30+ chart2_div . style . display = "none" ;
2231connectButton . disabled = false ;
2332stopButton . disabled = true ;
2433
@@ -36,6 +45,34 @@ const eightKConstraints = {video: {width: {min: 7680}, height: {min: 4320}}};
3645
3746let constraints = qvgaConstraints ;
3847
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+
3976function addToEventLog ( text , severity = 'info' ) {
4077 let log = document . querySelector ( 'textarea' ) ;
4178 log . value += 'log-' + severity + ': ' + text + '\n' ;
@@ -132,15 +169,21 @@ function getModeValue(radio) {
132169 addToEventLog ( 'Mode selected: ' + mode ) ;
133170}
134171
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 ) ;
138180}
139181
140182function stop ( ) {
141183 stopped = true ;
142184 stopButton . disabled = true ;
143185 connectButton . disabled = true ;
186+ chart2_div . style . display = "initial" ;
144187 streamWorker . postMessage ( { type : "stop" } ) ;
145188 try {
146189 inputStream . cancel ( ) ;
@@ -159,13 +202,15 @@ function stop() {
159202document . addEventListener ( 'DOMContentLoaded' , async function ( event ) {
160203 if ( stopped ) return ;
161204 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' ) ;
167211 return ;
168- }
212+ }
213+
169214 try {
170215 gotDevices ( await navigator . mediaDevices . enumerateDevices ( ) ) ;
171216 } catch ( e ) {
@@ -179,9 +224,32 @@ document.addEventListener('DOMContentLoaded', async function(event) {
179224 // Create a new worker.
180225 streamWorker = new Worker ( "js/stream_worker.js" ) ;
181226 addToEventLog ( 'Worker created.' ) ;
182- // Print messages from the worker in the text area.
227+
183228 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+ }
185253 } , false ) ;
186254
187255 stopButton . onclick = ( ) => {
@@ -192,7 +260,8 @@ document.addEventListener('DOMContentLoaded', async function(event) {
192260 connectButton . onclick = ( ) => {
193261 connectButton . disabled = true ;
194262 stopButton . disabled = false ;
195- hwButtons . style . display = "none" ;
263+ decHwButtons . style . display = "none" ;
264+ encHwButtons . style . display = "none" ;
196265 prefButtons . style . display = "none" ;
197266 bitButtons . style . display = "none" ;
198267 codecButtons . style . display = "none" ;
@@ -226,6 +295,36 @@ document.addEventListener('DOMContentLoaded', async function(event) {
226295 outputStream = generator . writable ;
227296 document . getElementById ( 'outputVideo' ) . srcObject = new MediaStream ( [ generator ] ) ;
228297
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+
229328 //Create video Encoder configuration
230329 const vConfig = {
231330 keyInterval : keygap ,
@@ -244,7 +343,8 @@ document.addEventListener('DOMContentLoaded', async function(event) {
244343 codec : preferredCodec ,
245344 width : ts . width / vConfig . resolutionScale ,
246345 height : ts . height / vConfig . resolutionScale ,
247- hardwareAcceleration : hw ,
346+ hardwareAcceleration : encHw ,
347+ decHwAcceleration : decHw ,
248348 bitrate : rate ,
249349 framerate : ts . frameRate / vConfig . framerateScale ,
250350 keyInterval : vConfig . keyInterval ,
0 commit comments