Group calls: Make renderVideoFrame generate less garbage

This commit is contained in:
Jordan Rose 2021-12-10 16:21:28 -08:00 committed by GitHub
parent fed84be0b6
commit 683823a114
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 21 deletions

View file

@ -26,7 +26,7 @@ import { MAX_FRAME_SIZE } from '../calling/constants';
const MAX_TIME_TO_SHOW_STALE_VIDEO_FRAMES = 5000;
type BasePropsType = {
getFrameBuffer: () => ArrayBuffer;
getFrameBuffer: () => Buffer;
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType;
onVisibilityChanged?: (demuxId: number, isVisible: boolean) => unknown;
@ -93,6 +93,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
const lastReceivedVideoAt = useRef(-Infinity);
const remoteVideoRef = useRef<HTMLCanvasElement | null>(null);
const canvasContextRef = useRef<CanvasRenderingContext2D | null>(null);
const imageDataRef = useRef<ImageData | null>(null);
const [intersectionRef, intersectionObserverEntry] =
useIntersectionObserver();
@ -134,9 +135,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
// for other participants, or pixel data from a previous frame. That's why we
// return early and use the `frameWidth` and `frameHeight`.
const frameBuffer = getFrameBuffer();
const frameDimensions = videoFrameSource.receiveVideoFrame(
Buffer.from(frameBuffer)
);
const frameDimensions = videoFrameSource.receiveVideoFrame(frameBuffer);
if (!frameDimensions) {
return;
}
@ -154,15 +153,16 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
canvasEl.width = frameWidth;
canvasEl.height = frameHeight;
canvasContext.putImageData(
new ImageData(
new Uint8ClampedArray(frameBuffer, 0, frameWidth * frameHeight * 4),
frameWidth,
frameHeight
),
0,
0
);
let imageData = imageDataRef.current;
if (
imageData?.width !== frameWidth ||
imageData?.height !== frameHeight
) {
imageData = new ImageData(frameWidth, frameHeight);
imageDataRef.current = imageData;
}
imageData.data.set(frameBuffer.subarray(0, frameWidth * frameHeight * 4));
canvasContext.putImageData(imageData, 0, 0);
lastReceivedVideoAt.current = Date.now();