gunkiss/index.html

141 lines
4.9 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body
{
background: #000;
}
</style>
</head>
<body>
<!-- WebGL output will be drawn here through Emscripten. The dimensions will be set by Emscripten. -->
<canvas id="canvas"></canvas>
<script>
const FPS = 10;
const BPP = 4;
/* Direct output of webcam in HTML5 (not displayed) */
var video = document.createElement("video");
video.width = 320;
video.height = 240;
/* Undisplayed canvas which is used to draw the video frame and access the pixel data directly */
var intermediate = document.createElement("canvas");
intermediate.width = video.width;
intermediate.height = video.height;
var context = intermediate.getContext("2d");
/* Indicates whether webcam is opened or not */
var streaming = false;
/* Address of the webcam frame pixel data on the Emscripten heap */
var image_heap_address;
/* Stores the time when the last webcam frame was processed */
var previous_frame_timestamp;
var Module = {
/* When the Module is finished loading, launch the camera frame processor function. */
onRuntimeInitialized: function()
{
window.requestAnimationFrame(process_video);
},
/* Set Emscripten to use a canvas for display. */
canvas: document.getElementById("canvas")
};
/*!
* Open the webcam and start displaying frames if successfully opened. Allocate space for 32-bit RGBA frame pixel data
* on the Emscripten heap.
*/
function open_camera()
{
navigator.mediaDevices.getUserMedia(
{
video: {
width: video.width,
height: video.height
},
audio: false
})
.then(function(stream) {
video.srcObject = stream;
video.play();
streaming = true;
/* Get the memory address of the pixel data */
image_heap_address = Module._malloc(video.width * video.height * BPP);
/* Pass the address to the game object */
Module.set_heap_offset(image_heap_address);
})
.catch(function(err) {
console.log('Camera Error: ' + err.name + ' ' + err.message);
});
}
/*!
* Pause video streaming and free pixel memory.
*/
function close_camera()
{
Module._free(image_heap_address);
video.pause();
video.srcObject = null;
streaming = false;
}
/*!
* Run continuously, drawing the webcam frame to the intermediate canvas, reading the pixel data, storing the data on the heap,
* and setting the new frame available flag.
*
* @param timestamp time at which the method was called, provided automatically by `window.requestAnimationFrame`
*/
function process_video(timestamp)
{
if (timestamp - previous_frame_timestamp > 1000 / FPS || previous_frame_timestamp == undefined)
{
previous_frame_timestamp = timestamp
try
{
if (streaming)
{
/* Draw the webcam frame on a hidden canvas */
context.drawImage(video, 0, 0, video.width, video.height);
/* Read the pixel data */
image_data = context.getImageData(0, 0, video.width, video.height).data;
/* Get a memory view object that provides access to the heap at the previously allocated address */
image_heap_data = new Uint8Array(Module.HEAPU8.buffer, image_heap_address, video.width * video.height * BPP);
/* Write the pixel data to the heap */
image_heap_data.set(image_data);
/* Flag the game object that new data is available */
Module.flag_frame();
}
}
catch (err)
{
console.log(err);
}
}
window.requestAnimationFrame(process_video);
}
</script>
<!-- This file is built by Emscripten when compiling the program -->
<script src="gunkiss.js"></script>
</body>
</html>