141 lines
4.9 KiB
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>
|