Skip to content

Commit a7f9a4f

Browse files
Justineantoinejourdain
authored andcommitted
fix(worker): debounce chunks decoding to fix Chromium 1-frame delay
1 parent 653c2c4 commit a7f9a4f

1 file changed

Lines changed: 45 additions & 7 deletions

File tree

vue-components/src/utils/decoder.js

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,37 +45,75 @@ function createDecoder(canvas) {
4545
return new VideoDecoder(init);
4646
}
4747
48+
let decoder = null;
49+
let debounceTimer = null;
50+
let lastChunkData = null;
51+
let lastChunkMeta = null;
52+
53+
function resetDebounceTimer() {
54+
if (debounceTimer) {
55+
clearTimeout(debounceTimer);
56+
debounceTimer = null;
57+
}
58+
}
59+
60+
function executeDebouncedDecode() {
61+
if (lastChunkData && decoder) {
62+
decoder.decode(new EncodedVideoChunk({
63+
timestamp: lastChunkMeta.timestamp + 1,
64+
type: lastChunkMeta.type,
65+
data: lastChunkData,
66+
}));
67+
lastChunkData = null;
68+
lastChunkMeta = null;
69+
}
70+
}
71+
4872
onmessage = async function({ data: msg }) {
4973
switch(msg.action) {
5074
case 1: // init
5175
this.canvas = msg.canvas;
52-
this.decoder = createDecoder(this.canvas);
76+
decoder = createDecoder(this.canvas);
5377
break;
78+
5479
case 2: // config
5580
this.canvas.width = msg.config.codedWidth;
5681
this.canvas.height = msg.config.codedHeight;
57-
this.decoder.configure(msg.config);
82+
decoder.configure(msg.config);
5883
break;
84+
5985
case 3: // chunk
60-
this.decoder.decode(new EncodedVideoChunk({
86+
resetDebounceTimer();
87+
lastChunkData = msg.data.slice(0);
88+
lastChunkMeta = { timestamp: msg.timestamp, type: msg.type };
89+
90+
decoder.decode(new EncodedVideoChunk({
6191
timestamp: msg.timestamp,
6292
type: msg.type,
6393
data: msg.data,
6494
}));
95+
96+
debounceTimer = setTimeout(executeDebouncedDecode, 35);
6597
break;
98+
6699
case 4: // flush
67-
this.decoder.flush();
100+
resetDebounceTimer();
101+
decoder.flush();
68102
break;
103+
69104
case 5: // reset
70-
this.decoder.reset();
105+
resetDebounceTimer();
106+
decoder.reset();
71107
break;
108+
72109
case 6: // close
73110
// flush before close() to avoid currepoted state.
74111
// calling postMessage(flush)
75112
// postMessage(close) is not enough since the second
76113
// abort the first before it finishes.
77-
await this.decoder.flush();
78-
this.decoder.close();
114+
resetDebounceTimer();
115+
await decoder.flush();
116+
decoder.close();
79117
break;
80118
}
81119
}

0 commit comments

Comments
 (0)