chore: limpopo update
This commit is contained in:
1571
2020-11-02/pw313/Cargo.lock
generated
Normal file
1571
2020-11-02/pw313/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
2020-11-02/pw313/Cargo.toml
Normal file
14
2020-11-02/pw313/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "pw313"
|
||||
version = "0.1.0"
|
||||
authors = ["Rekai Musuka <rekai@musuka.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
uvc = "0.1"
|
||||
winit = "0.23"
|
||||
sdl2 = { version = "0.34" }
|
||||
anyhow = "1.0"
|
||||
image = "0.23"
|
||||
172
2020-11-02/pw313/src/main.rs
Normal file
172
2020-11-02/pw313/src/main.rs
Normal file
@@ -0,0 +1,172 @@
|
||||
use anyhow::Result;
|
||||
use sdl2::{
|
||||
event::Event,
|
||||
keyboard::Keycode,
|
||||
pixels::PixelFormatEnum,
|
||||
render::{Texture, TextureCreator},
|
||||
surface::Surface,
|
||||
video::WindowContext,
|
||||
};
|
||||
use std::sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc, Mutex,
|
||||
};
|
||||
use uvc::{Context, Device, DeviceHandle};
|
||||
|
||||
fn log_found_device(device: &Device) -> Result<()> {
|
||||
let info = device.description()?;
|
||||
|
||||
println!(
|
||||
"Found device: Bus {:03} Device {:03} : ID {:04x}:{:04x} {} ({})",
|
||||
device.bus_number(),
|
||||
device.device_address(),
|
||||
info.vendor_id,
|
||||
info.product_id,
|
||||
info.product.unwrap_or_else(|| "Unknown".to_string()),
|
||||
info.manufacturer.unwrap_or_else(|| "Unknown".to_string()),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn log_device_settings(device: &DeviceHandle) {
|
||||
println!(
|
||||
"Scanning mode: {:?}\nAuto-exposure mode: {:?}\nAuto-exposure priority: {:?}\nAbsolute exposure: {:?}\nRelative exposure: {:?}\nAboslute focus: {:?}\nRelative focus: {:?}",
|
||||
device.scanning_mode(),
|
||||
device.ae_mode(),
|
||||
device.ae_priority(),
|
||||
device.exposure_abs(),
|
||||
device.exposure_rel(),
|
||||
device.focus_abs(),
|
||||
device.focus_rel(),
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let uvc_ctx = Context::new().expect("Could not create context");
|
||||
let device = uvc_ctx
|
||||
.find_device(Some(0x07ca), Some(0x313a), None)
|
||||
.expect("Unable to find the AVerMedia PW313");
|
||||
|
||||
log_found_device(&device).unwrap();
|
||||
|
||||
let device = device.open().expect("Unable to open webcam.");
|
||||
let format = device
|
||||
.get_preferred_format(|x, y| {
|
||||
if x.fps >= y.fps && x.width * x.height >= y.width * y.height {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
println!("Chosen format: {:?}", format);
|
||||
|
||||
let mut stream = device.get_stream_handle_with_format(format).unwrap();
|
||||
log_device_settings(&device);
|
||||
|
||||
let frame_guard = Arc::new(Mutex::new(MyFrame::default()));
|
||||
let frame_cpy = frame_guard.clone();
|
||||
|
||||
let counter = Arc::new(AtomicUsize::new(0));
|
||||
let stream = stream
|
||||
.start_stream(
|
||||
move |frame_ref, count| {
|
||||
let mut frame = frame_cpy.lock().unwrap();
|
||||
|
||||
*frame = MyFrame {
|
||||
data: frame_ref.to_rgb().unwrap().to_bytes().to_owned(),
|
||||
width: frame_ref.width(),
|
||||
height: frame_ref.height(),
|
||||
};
|
||||
|
||||
count.fetch_add(1, Ordering::SeqCst);
|
||||
},
|
||||
counter.clone(),
|
||||
)
|
||||
.expect("Could not start stream.");
|
||||
|
||||
let sdl_ctx = sdl2::init().unwrap();
|
||||
let video_subsystem = sdl_ctx.video().unwrap();
|
||||
|
||||
let window = video_subsystem
|
||||
.window("AVerMedia PW313 Web Camera", format.width, format.height)
|
||||
.position_centered()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut canvas = window
|
||||
.into_canvas()
|
||||
.present_vsync()
|
||||
.accelerated()
|
||||
.build()
|
||||
.unwrap();
|
||||
let texture_creator = canvas.texture_creator();
|
||||
|
||||
'main: loop {
|
||||
for event in sdl_ctx.event_pump().unwrap().poll_iter() {
|
||||
match event {
|
||||
Event::Quit { .. }
|
||||
| Event::KeyDown {
|
||||
keycode: Some(Keycode::Escape),
|
||||
..
|
||||
} => break 'main,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let texture = do_thing(&frame_guard, &texture_creator);
|
||||
match texture {
|
||||
Some(thing) => {
|
||||
canvas.copy(&thing, None, None).unwrap();
|
||||
canvas.present();
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_thing<'a>(
|
||||
guard: &'a Arc<Mutex<MyFrame>>,
|
||||
creator: &'a TextureCreator<WindowContext>,
|
||||
) -> Option<Texture<'a>> {
|
||||
let mut frame = guard.lock().ok()?;
|
||||
let width = frame.width;
|
||||
let height = frame.height;
|
||||
|
||||
if !frame.data.is_empty() {
|
||||
// Flip Image
|
||||
let surface = Surface::from_data(
|
||||
frame.data.as_mut_slice(),
|
||||
width,
|
||||
height,
|
||||
width * (24 / 8),
|
||||
PixelFormatEnum::RGB24,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Some(Texture::from_surface(&surface, creator).ok()?)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
// let surface = Surface::new(600, 800, PixelFormatEnum::RGB24).unwrap();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct MyFrame {
|
||||
data: Vec<u8>,
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
impl Default for MyFrame {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
data: vec![],
|
||||
width: 600,
|
||||
height: 800,
|
||||
}
|
||||
}
|
||||
}
|
||||
185
2020-11-02/pw313/src/old.rs
Normal file
185
2020-11-02/pw313/src/old.rs
Normal file
@@ -0,0 +1,185 @@
|
||||
use glium::{implement_vertex, uniform};
|
||||
|
||||
use std::error::Error;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use glium::Surface;
|
||||
use uvc::{Context, Frame};
|
||||
|
||||
fn frame_to_raw_image(
|
||||
frame: &Frame,
|
||||
) -> Result<glium::texture::RawImage2d<'static, u8>, Box<dyn Error>> {
|
||||
let new_frame = frame.to_rgb()?;
|
||||
let data = new_frame.to_bytes();
|
||||
|
||||
let image = glium::texture::RawImage2d::from_raw_rgb(
|
||||
data.to_vec(),
|
||||
(new_frame.width(), new_frame.height()),
|
||||
);
|
||||
|
||||
Ok(image)
|
||||
}
|
||||
|
||||
fn callback_frame_to_image(
|
||||
frame: &Frame,
|
||||
data: &mut Arc<Mutex<Option<glium::texture::RawImage2d<u8>>>>,
|
||||
) {
|
||||
let image = frame_to_raw_image(frame);
|
||||
match image {
|
||||
Err(x) => println!("{:#?}", x),
|
||||
Ok(x) => {
|
||||
let mut data = Mutex::lock(&data).unwrap();
|
||||
*data = Some(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ctx = Context::new().expect("Could not create context");
|
||||
let dev = ctx
|
||||
.find_device(None, None, None)
|
||||
.expect("Could not find device");
|
||||
|
||||
let description = dev.description().unwrap();
|
||||
println!(
|
||||
"Found device: Bus {:03} Device {:03} : ID {:04x}:{:04x} {} ({})",
|
||||
dev.bus_number(),
|
||||
dev.device_address(),
|
||||
description.vendor_id,
|
||||
description.product_id,
|
||||
description.product.unwrap_or_else(|| "Unknown".to_owned()),
|
||||
description
|
||||
.manufacturer
|
||||
.unwrap_or_else(|| "Unknown".to_owned())
|
||||
);
|
||||
|
||||
// Open multiple devices by enumerating:
|
||||
// let mut list = ctx.devices().expect("Could not get devices");
|
||||
// let dev = list.next().expect("No device available");
|
||||
|
||||
let devh = dev.open().expect("Could not open device");
|
||||
|
||||
let format = devh
|
||||
.get_preferred_format(|x, y| {
|
||||
if x.fps >= y.fps && x.width * x.height >= y.width * y.height {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
println!("Best format found: {:?}", format);
|
||||
let mut streamh = devh.get_stream_handle_with_format(format).unwrap();
|
||||
|
||||
println!(
|
||||
"Scanning mode: {:?}\nAuto-exposure mode: {:?}\nAuto-exposure priority: {:?}\nAbsolute exposure: {:?}\nRelative exposure: {:?}\nAboslute focus: {:?}\nRelative focus: {:?}",
|
||||
devh.scanning_mode(),
|
||||
devh.ae_mode(),
|
||||
devh.ae_priority(),
|
||||
devh.exposure_abs(),
|
||||
devh.exposure_rel(),
|
||||
devh.focus_abs(),
|
||||
devh.focus_rel(),
|
||||
);
|
||||
|
||||
let frame = Arc::new(Mutex::new(None));
|
||||
let _stream = streamh
|
||||
.start_stream(callback_frame_to_image, frame.clone())
|
||||
.unwrap();
|
||||
|
||||
use glium::glutin;
|
||||
let events_loop = glutin::event_loop::EventLoop::new();
|
||||
let window = glutin::window::WindowBuilder::new().with_title("Mirror");
|
||||
let context = glutin::ContextBuilder::new();
|
||||
let display = glium::Display::new(window, context, &events_loop).unwrap();
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct QuadVertex {
|
||||
pos: (f32, f32),
|
||||
}
|
||||
|
||||
implement_vertex!(QuadVertex, pos);
|
||||
|
||||
let vertices: [QuadVertex; 4] = [
|
||||
QuadVertex { pos: (-1.0, -1.0) },
|
||||
QuadVertex { pos: (-1.0, 1.0) },
|
||||
QuadVertex { pos: (1.0, -1.0) },
|
||||
QuadVertex { pos: (1.0, 1.0) },
|
||||
];
|
||||
|
||||
let indices: [u8; 6] = [0, 1, 2, 1, 3, 2];
|
||||
|
||||
let vertex_shader_source = r#"
|
||||
#version 140
|
||||
in vec2 pos;
|
||||
out vec2 v_position;
|
||||
void main() {
|
||||
v_position = (pos + 1.0)/2.0;
|
||||
gl_Position = vec4(-pos.x, -pos.y, 0.0, 1.0);
|
||||
}
|
||||
"#;
|
||||
|
||||
let fragment_shader_source = r#"
|
||||
#version 140
|
||||
in vec2 v_position;
|
||||
out vec4 colour;
|
||||
uniform sampler2D u_image;
|
||||
void main() {
|
||||
vec2 pos = v_position;
|
||||
colour = texture(u_image, pos);
|
||||
}
|
||||
"#;
|
||||
|
||||
let vertices = glium::VertexBuffer::new(&display, &vertices).unwrap();
|
||||
let indices = glium::IndexBuffer::new(
|
||||
&display,
|
||||
glium::index::PrimitiveType::TrianglesList,
|
||||
&indices,
|
||||
)
|
||||
.unwrap();
|
||||
let program =
|
||||
glium::Program::from_source(&display, vertex_shader_source, fragment_shader_source, None)
|
||||
.unwrap();
|
||||
|
||||
let mut buffer: Option<glium::texture::SrgbTexture2d> = None;
|
||||
events_loop.run(move |event, _, control_flow| {
|
||||
if let glutin::event::Event::WindowEvent { event, .. } = event {
|
||||
if let glutin::event::WindowEvent::CloseRequested = event {
|
||||
*control_flow = glutin::event_loop::ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut target = display.draw();
|
||||
target.clear_color(0.0, 0.0, 1.0, 1.0);
|
||||
|
||||
let mut mutex = Mutex::lock(&frame).unwrap();
|
||||
|
||||
match mutex.take() {
|
||||
None => {
|
||||
// No new frame to render
|
||||
}
|
||||
Some(image) => {
|
||||
let image = glium::texture::SrgbTexture2d::new(&display, image)
|
||||
.expect("Could not use image");
|
||||
buffer = Some(image);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref b) = buffer {
|
||||
let uniforms = uniform! { u_image: b };
|
||||
target
|
||||
.draw(
|
||||
&vertices,
|
||||
&indices,
|
||||
&program,
|
||||
&uniforms,
|
||||
&Default::default(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
target.finish().unwrap();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user