diff --git a/sample/videoUploading/index.html b/sample/videoUploading/index.html index 7f712340..52f97c62 100644 --- a/sample/videoUploading/index.html +++ b/sample/videoUploading/index.html @@ -23,9 +23,8 @@ height: 100%; /* make body fill the browser window */ } canvas { - width: 100%; - height: 100%; - max-width: 100%; + width: min(100vw, 100vh); + aspect-ratio: 4 / 3; display: block; } @@ -34,5 +33,6 @@ +

   
 
diff --git a/sample/videoUploading/main.ts b/sample/videoUploading/main.ts
index a66c1e6b..96a3f1ee 100644
--- a/sample/videoUploading/main.ts
+++ b/sample/videoUploading/main.ts
@@ -20,8 +20,14 @@ const videos = {
     url: '../../assets/video/Video_360°._Timelapse._Bled_Lake_in_Slovenia..webm.720p.vp9.webm',
     mode: '360',
   },
+  webcam: {
+    url: '',
+    mode: 'mirror',
+  },
 } as const;
 
+const videoinfo = document.getElementById('videoinfo') as HTMLPreElement;
+
 const canvas = document.querySelector('canvas') as HTMLCanvasElement;
 const context = canvas.getContext('webgpu');
 const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
@@ -90,7 +96,21 @@ let canReadVideo = false;
 
 async function playVideo(videoName: keyof typeof videos) {
   canReadVideo = false;
-  video.src = videos[videoName].url;
+
+  if (video.srcObject) {
+    (video.srcObject as MediaStream)
+      .getTracks()
+      .forEach((track) => track.stop());
+    video.srcObject = null;
+  }
+
+  if (videoName === 'webcam') {
+    video.srcObject = await navigator.mediaDevices.getUserMedia({
+      video: true,
+    });
+  } else {
+    video.src = videos[videoName].url;
+  }
   await video.play();
   canReadVideo = true;
 }
@@ -120,8 +140,22 @@ function drawVideo() {
   const maxSize = device.limits.maxTextureDimension2D;
   canvas.width = Math.min(Math.max(1, canvas.offsetWidth), maxSize);
   canvas.height = Math.min(Math.max(1, canvas.offsetHeight), maxSize);
-  const externalTextureSource =
-    settings.videoSource === 'videoFrame' ? new VideoFrame(video) : video;
+  const videoFrame =
+    settings.videoSource === 'videoFrame' ? new VideoFrame(video) : null;
+  const externalTextureSource = videoFrame ?? video;
+  videoinfo.textContent = `HTMLVideoElement: ${video.videoWidth}x${video.videoHeight}`;
+  if (videoFrame) {
+    videoinfo.textContent +=
+      '\nVideoFrame: ' +
+      JSON.stringify(
+        {
+          codedRect: videoFrame.codedRect,
+          visibleRect: videoFrame.visibleRect,
+        },
+        undefined,
+        2
+      );
+  }
 
   const mode = videos[settings.video].mode;
   const pipeline = mode === '360' ? video360Pipeline : videoCoverPipeline;
@@ -182,6 +216,9 @@ function drawVideo() {
       combinedAspect > 1 ? [1 / combinedAspect, 1] : [1, combinedAspect],
       mat
     );
+    if (mode === 'mirror') {
+      mat3.scale(mat, [-1, 1], mat);
+    }
     mat3.translate(mat, [-0.5, -0.5], mat);
     device.queue.writeBuffer(uniformBuffer, 0, mat);
   }