Skip to content

Commit

Permalink
Allow recording both h264 and jpeg
Browse files Browse the repository at this point in the history
  • Loading branch information
jtbandes committed Nov 16, 2023
1 parent 3180670 commit 0381b16
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 25 deletions.
17 changes: 5 additions & 12 deletions website/src/components/McapRecordingDemo/McapRecordingDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,10 @@ export function McapRecordingDemo(): JSX.Element {
};
}, [addPoseMessage, recording, recordOrientation]);

const enableCamera = recordH264 || recordJpeg;
useEffect(() => {
const videoContainer = videoContainerRef.current;
if (!videoContainer) {
return;
}
if (!recordH264 && !recordJpeg) {
if (!videoContainer || !enableCamera) {
return;
}

Expand Down Expand Up @@ -223,7 +221,7 @@ export function McapRecordingDemo(): JSX.Element {
setVideoStarted(false);
setVideoError(undefined);
};
}, [recordH264, recordJpeg]);
}, [enableCamera]);

useEffect(() => {
const video = videoRef.current;
Expand All @@ -236,7 +234,8 @@ export function McapRecordingDemo(): JSX.Element {

const stopCapture = startVideoCapture({
video,
compression: recordH264 ? "h264" : "jpeg",
enableH264: recordH264,
enableJpeg: recordJpeg,
frameDurationSec: 1 / 30,
onJpegFrame: (blob) => {
addJpegFrame(blob);
Expand Down Expand Up @@ -338,9 +337,6 @@ export function McapRecordingDemo(): JSX.Element {
checked={recordH264}
onChange={(event) => {
setRecordH264(event.target.checked);
if (event.target.checked) {
setRecordJpeg(false);
}
}}
/>
Camera (H.264)
Expand All @@ -352,9 +348,6 @@ export function McapRecordingDemo(): JSX.Element {
checked={recordJpeg}
onChange={(event) => {
setRecordJpeg(event.target.checked);
if (event.target.checked) {
setRecordH264(false);
}
}}
/>
Camera (JPEG)
Expand Down
32 changes: 19 additions & 13 deletions website/src/components/McapRecordingDemo/videoCapture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export type H264Frame = {
};

type VideoCaptureParams = {
compression: "h264" | "jpeg";
enableH264: boolean;
enableJpeg: boolean;
/** Video element to capture */
video: HTMLVideoElement;
/** Frame interval in seconds */
Expand Down Expand Up @@ -247,20 +248,24 @@ async function startVideoCaptureAsync(
) {
const {
video,
compression,
enableH264,
enableJpeg,
onJpegFrame,
onH264Frame,
onError,
frameDurationSec,
} = params;
if (!enableH264 && !enableJpeg) {
throw new Error("At least one of H.264 or JPEG encoding must be enabled");
}
const canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const ctx = canvas.getContext("2d");

let encoder: VideoEncoder | undefined;
const framePool: ArrayBuffer[] = [];
if (compression === "h264") {
if (enableH264) {
try {
const result = await selectSupportedVideoEncoderConfig({
width: video.videoWidth,
Expand All @@ -277,9 +282,6 @@ async function startVideoCaptureAsync(
}
encoder = new VideoEncoder({
output: (chunk) => {
if (signal.aborted) {
return;
}
let buffer = framePool.pop();
if (!buffer || buffer.byteLength < chunk.byteLength) {
buffer = new ArrayBuffer(chunk.byteLength);
Expand Down Expand Up @@ -311,19 +313,20 @@ async function startVideoCaptureAsync(
const keyframeInterval = 2000;
let lastKeyframeTime: number | undefined;

let processingFrame = false;
let processingH264 = false;
let processingJpeg = false;
const start = performance.now();
const interval = setInterval(() => {
if (processingFrame) {
if (processingH264 || processingJpeg) {
// last frame is not yet complete, skip frame
return;
}
processingFrame = true;
if (encoder) {
processingH264 = true;
encoder.addEventListener(
"dequeue",
() => {
processingFrame = false;
processingH264 = false;
},
{ once: true },
);
Expand All @@ -342,12 +345,15 @@ async function startVideoCaptureAsync(
}
encoder.encode(frame, encodeOptions);
frame.close();
} else {
}

if (enableJpeg) {
processingJpeg = true;
ctx?.drawImage(video, 0, 0);
canvas.toBlob(
(blob) => {
processingFrame = false;
if (blob && !signal.aborted) {
processingJpeg = false;
if (blob) {
onJpegFrame(blob);
}
},
Expand Down

0 comments on commit 0381b16

Please sign in to comment.