Skip to content

Commit af51d79

Browse files
committed
web: Workaround Direct H.264 flickering on Firefox
1 parent c551b9f commit af51d79

File tree

1 file changed

+45
-13
lines changed

1 file changed

+45
-13
lines changed

web/share/js/kvm/stream_media.js

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ export function MediaStreamer(__setActive, __setInactive, __setInfo, __orient) {
3838
var __ping_timer = null;
3939
var __missed_heartbeats = 0;
4040

41-
var __decoder = null;
4241
var __codec = "";
42+
var __decoder = null;
43+
var __frame = null;
4344
var __canvas = $("stream-canvas");
4445
var __ctx = __canvas.getContext("2d");
4546

@@ -208,7 +209,7 @@ export function MediaStreamer(__setActive, __setInactive, __setInfo, __orient) {
208209
__closeDecoder();
209210
__codec = codec;
210211
__decoder = new VideoDecoder({ // eslint-disable-line no-undef
211-
"output": __drawFrame,
212+
"output": __renderFrame,
212213
"error": (err) => __logInfo(err.message),
213214
});
214215
if (started) {
@@ -241,24 +242,41 @@ export function MediaStreamer(__setActive, __setInactive, __setInfo, __orient) {
241242
if (__decoder !== null) {
242243
try {
243244
__decoder.close();
244-
} catch {
245-
// Pass
246245
} finally {
247-
__decoder = null;
248246
__codec = "";
247+
__decoder = null;
248+
if (__frame !== null) {
249+
try {
250+
__closeFrame(__frame);
251+
} finally {
252+
__frame = null;
253+
}
254+
}
249255
}
250256
}
251257
};
252258

253-
var __drawFrame = function(frame) {
259+
var __renderFrame = function(frame) {
260+
if (__frame === null) {
261+
__frame = frame;
262+
window.requestAnimationFrame(__drawPendingFrame, __canvas);
263+
} else {
264+
__closeFrame(frame);
265+
}
266+
};
267+
268+
var __drawPendingFrame = function() {
269+
if (__frame === null) {
270+
return;
271+
}
254272
try {
255-
let width = frame.displayWidth;
256-
let height = frame.displayHeight;
273+
let width = __frame.displayWidth;
274+
let height = __frame.displayHeight;
257275
switch (__orient) {
258276
case 90:
259277
case 270:
260-
width = frame.displayHeight;
261-
height = frame.displayWidth;
278+
width = __frame.displayHeight;
279+
height = __frame.displayWidth;
262280
}
263281

264282
if (__canvas.width !== width || __canvas.height !== height) {
@@ -267,7 +285,7 @@ export function MediaStreamer(__setActive, __setInactive, __setInfo, __orient) {
267285
}
268286

269287
if (__orient === 0) {
270-
__ctx.drawImage(frame, 0, 0);
288+
__ctx.drawImage(__frame, 0, 0);
271289
} else {
272290
__ctx.save();
273291
try {
@@ -276,14 +294,28 @@ export function MediaStreamer(__setActive, __setInactive, __setInfo, __orient) {
276294
case 180: __ctx.translate(width, height); __ctx.rotate(-Math.PI); break;
277295
case 270: __ctx.translate(width, 0); __ctx.rotate(Math.PI / 2); break;
278296
}
279-
__ctx.drawImage(frame, 0, 0);
297+
__ctx.drawImage(__frame, 0, 0);
280298
} finally {
281299
__ctx.restore();
282300
}
283301
}
284-
285302
__fps_accum += 1;
286303
} finally {
304+
__closeFrame(__frame);
305+
__frame = null;
306+
}
307+
};
308+
309+
var __closeFrame = function(frame) {
310+
if (!tools.browser.is_firefox) {
311+
// FIXME: On Firefox, image is flickering when we're closing the frame for some reason.
312+
// So we're just not performing the close() and it seems there is no problems here
313+
// because Firefox is implementing some auto-closing logic. With auto-close,
314+
// no flickering observed.
315+
// - https://github.com/mozilla/gecko-dev/blob/82333a9/dom/media/webcodecs/VideoFrame.cpp
316+
// Note at 2025.05.13:
317+
// - The problem is not observed on nightly Firefox 140.
318+
// - It's also not observed with hardware accelleration on 138.
287319
frame.close();
288320
}
289321
};

0 commit comments

Comments
 (0)