263 lines
7.0 KiB
JavaScript
263 lines
7.0 KiB
JavaScript
// Test webcam display
|
|
var draw2d
|
|
var graphics
|
|
var os = use('os');
|
|
var input = use('input')
|
|
var json = use('json')
|
|
var surface = use('surface')
|
|
input.watch($_)
|
|
|
|
// Create SDL video actor
|
|
var video_actor = use('sdl_video');
|
|
var camera = use('camera')
|
|
|
|
var window_id = null;
|
|
var renderer_id = null;
|
|
var cam_id = null;
|
|
var cam_obj = null;
|
|
var cam_approved = false;
|
|
var webcam_texture = null;
|
|
|
|
// Handle camera events
|
|
$_.receiver(e => {
|
|
if (e.type === 'camera_device_approved' && e.which === cam_id) {
|
|
log.console("Camera approved!");
|
|
cam_approved = true;
|
|
} else if (e.type === 'camera_device_denied' && e.which === cam_id) {
|
|
log.error("Camera access denied!");
|
|
$_.stop();
|
|
}
|
|
})
|
|
|
|
// Create window
|
|
send(video_actor, {
|
|
kind: "window",
|
|
op: "create",
|
|
data: {
|
|
title: "Webcam Test",
|
|
width: 800,
|
|
height: 600
|
|
}
|
|
}, function(response) {
|
|
if (response.error) {
|
|
log.error("Failed to create window:", response.error);
|
|
return;
|
|
}
|
|
|
|
window_id = response.id;
|
|
log.console("Created window with id:", window_id);
|
|
|
|
// Create renderer
|
|
send(video_actor, {
|
|
kind: "window",
|
|
op: "makeRenderer",
|
|
id: window_id
|
|
}, function(response) {
|
|
if (response.error) {
|
|
log.error("Failed to create renderer:", response.error);
|
|
return;
|
|
}
|
|
|
|
renderer_id = response.id;
|
|
log.console("Created renderer with id:", renderer_id);
|
|
|
|
// Configure draw2d and graphics
|
|
draw2d = use('draw2d', video_actor, renderer_id)
|
|
graphics = use('graphics', video_actor, renderer_id)
|
|
|
|
// List available cameras
|
|
var cameras = camera.list();
|
|
if (cameras.length === 0) {
|
|
log.error("No cameras found!");
|
|
log.console(json.encode(cameras))
|
|
$_.stop();
|
|
return;
|
|
}
|
|
|
|
log.console("Found", cameras.length, "camera(s)");
|
|
|
|
// Open the first camera
|
|
cam_id = cameras[0];
|
|
var cam_name = camera.name(cam_id);
|
|
var cam_position = camera.position(cam_id);
|
|
log.console("Opening camera:", cam_name, "Position:", cam_position);
|
|
|
|
// Get supported formats and try to find a good one
|
|
var formats = camera.supported_formats(cam_id);
|
|
log.console("Camera supports", formats.length, "formats");
|
|
|
|
// Look for a 640x480 format with preferred colorspace
|
|
var preferred_format = null;
|
|
for (var i = 0; i < formats.length; i++) {
|
|
if (formats[i].width === 640 && formats[i].height === 480) {
|
|
preferred_format = formats[i];
|
|
// Prefer JPEG or sRGB colorspace if available
|
|
if (formats[i].colorspace === "jpeg" || formats[i].colorspace === "srgb") {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!preferred_format && formats.length > 0) {
|
|
// Use first available format
|
|
preferred_format = formats[0];
|
|
}
|
|
|
|
preferred_format.framerate_numerator = 30
|
|
|
|
if (preferred_format) {
|
|
log.console("Using format:", preferred_format.width + "x" + preferred_format.height,
|
|
"FPS:", preferred_format.framerate_numerator + "/" + preferred_format.framerate_denominator,
|
|
"Format:", preferred_format.format,
|
|
"Colorspace:", preferred_format.colorspace);
|
|
cam_obj = camera.open(cam_id, preferred_format);
|
|
} else {
|
|
cam_obj = camera.open(cam_id);
|
|
}
|
|
|
|
if (!cam_obj) {
|
|
log.error("Failed to open camera!");
|
|
$_.stop();
|
|
return;
|
|
}
|
|
|
|
log.console("Camera driver:", cam_obj.get_driver());
|
|
|
|
// Get and display the actual format being used
|
|
var actual_format = cam_obj.get_format();
|
|
log.console("Actual camera format:");
|
|
log.console(" Resolution:", actual_format.width + "x" + actual_format.height);
|
|
log.console(" Format:", actual_format.format);
|
|
log.console(" Colorspace:", actual_format.colorspace);
|
|
log.console(" FPS:", actual_format.framerate_numerator + "/" + actual_format.framerate_denominator);
|
|
|
|
// Start capturing after a short delay to wait for approval
|
|
$_.delay(start_capturing, 0.5);
|
|
});
|
|
});
|
|
|
|
var captured = false
|
|
|
|
function start_capturing() {
|
|
if (!cam_approved) {
|
|
log.console("Waiting for camera approval...");
|
|
$_.delay(start_capturing, 0.1);
|
|
return;
|
|
}
|
|
|
|
var frame = 0;
|
|
var start_time = os.now();
|
|
|
|
function capture_and_draw() {
|
|
frame++;
|
|
var t = os.now() - start_time;
|
|
|
|
// Clear the screen with a dark background
|
|
send(video_actor, {
|
|
kind: "renderer",
|
|
id: renderer_id,
|
|
op: "set",
|
|
prop: "drawColor",
|
|
value: [0.1, 0.1, 0.15, 1]
|
|
});
|
|
|
|
send(video_actor, {
|
|
kind: "renderer",
|
|
id: renderer_id,
|
|
op: "clear"
|
|
});
|
|
|
|
// Clear draw2d commands
|
|
draw2d.clear();
|
|
|
|
// Capture frame from camera
|
|
var surface = cam_obj.capture()
|
|
|
|
if (surface) {
|
|
// Create texture from surface directly
|
|
send(video_actor, {
|
|
kind: "renderer",
|
|
id: renderer_id,
|
|
op: "loadTexture",
|
|
data: surface
|
|
}, function(tex_response) {
|
|
if (tex_response.id) {
|
|
// Destroy old texture if exists to avoid memory leak
|
|
if (webcam_texture) {
|
|
send(video_actor, {
|
|
kind: "texture",
|
|
id: webcam_texture,
|
|
op: "destroy"
|
|
});
|
|
}
|
|
webcam_texture = tex_response.id;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Draw the webcam texture if we have one
|
|
if (webcam_texture) {
|
|
send(video_actor, {
|
|
kind: "renderer",
|
|
id: renderer_id,
|
|
op: "copyTexture",
|
|
data: {
|
|
texture_id: webcam_texture,
|
|
dest: {x: 50, y: 50, width: 640, height: 480}
|
|
}
|
|
});
|
|
} else {
|
|
// Draw placeholder text while waiting for first frame
|
|
// draw2d.text("Waiting for webcam...", {x: 200, y: 250, size: 20});
|
|
}
|
|
|
|
// Draw info
|
|
/*
|
|
draw2d.text("Camera: " + camera.name(cam_id), {x: 20, y: 20, size: 16});
|
|
draw2d.text("Position: " + camera.position(cam_id), {x: 20, y: 40, size: 16});
|
|
draw2d.text("Frame: " + frame, {x: 20, y: 60, size: 16});
|
|
*/
|
|
// Flush all commands to renderer
|
|
draw2d.flush();
|
|
|
|
// Present the frame
|
|
send(video_actor, {
|
|
kind: "renderer",
|
|
id: renderer_id,
|
|
op: "present"
|
|
});
|
|
|
|
// Schedule next frame (30 FPS for webcam)
|
|
if (frame < 300) { // Run for 10 seconds
|
|
$_.delay(capture_and_draw, 1/30);
|
|
} else {
|
|
log.console("Test completed - captured", frame, "frames");
|
|
|
|
// Clean up resources
|
|
if (webcam_texture) {
|
|
send(video_actor, {
|
|
kind: "texture",
|
|
id: webcam_texture,
|
|
op: "destroy"
|
|
});
|
|
}
|
|
|
|
// Note: Camera is automatically closed when the object is garbage collected
|
|
cam_obj = null;
|
|
|
|
$_.delay($_.stop, 0.5);
|
|
}
|
|
}
|
|
|
|
capture_and_draw();
|
|
}
|
|
|
|
$_.delay(_ => {
|
|
// Capture frame from camera
|
|
var surface = cam_obj.capture().convert("rgba8888", "srgb")
|
|
log.console('capturing!')
|
|
graphics.save_png("test.png", surface.width, surface.height, surface.pixels(),surface.pitch)
|
|
}, 3)
|
|
|
|
// Stop after 12 seconds if not already stopped
|
|
$_.delay($_.stop, 12); |