diff --git a/thermal.mp4 b/thermal.mp4 index 6c6c400..4665d9b 100644 Binary files a/thermal.mp4 and b/thermal.mp4 differ diff --git a/thermalcamdecoder/Cargo.lock b/thermalcamdecoder/Cargo.lock index 43be2af..051cdc5 100644 --- a/thermalcamdecoder/Cargo.lock +++ b/thermalcamdecoder/Cargo.lock @@ -400,7 +400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] -name = "thermalcamdecoder" +name = "thermaldecoder" version = "0.1.0" dependencies = [ "anyhow", diff --git a/thermalcamdecoder/Cargo.toml b/thermalcamdecoder/Cargo.toml index 3a25422..1a2d8ee 100644 --- a/thermalcamdecoder/Cargo.toml +++ b/thermalcamdecoder/Cargo.toml @@ -1,14 +1,18 @@ [package] -name = "thermalcamdecoder" +name = "thermaldecoder" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "thermaldecoder" +crate-type = ["cdylib"] + [dependencies] anyhow = "1.0.77" indicatif = "0.17.7" pcap-parser = { version = "0.14.1", features = ["data"] } png = "0.17.10" -pyo3 = "0.20.0" +pyo3 = { version = "0.20.0", "features" = ["extension-module"] } serde = { version = "1.0.193", features = ["derive", "serde_derive", "alloc"] } diff --git a/thermalcamdecoder/src/lib.rs b/thermalcamdecoder/src/lib.rs index ac054e5..14a1ce9 100644 --- a/thermalcamdecoder/src/lib.rs +++ b/thermalcamdecoder/src/lib.rs @@ -1,5 +1,6 @@ use indicatif::{ProgressBar, ProgressIterator}; use png; +use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use std::fs::File; use std::io::BufWriter; @@ -9,8 +10,8 @@ use std::path::Path; use pcap_parser::traits::PcapReaderIterator; use pcap_parser::*; -fn get_packets_without_udp_header() -> anyhow::Result<(Vec>, usize, usize)> { - let file = File::open("in.pcap")?; +fn get_packets_without_udp_header(filename: &str) -> anyhow::Result<(Vec>, usize, usize)> { + let file = File::open(filename)?; let mut cap = PcapNGReader::new(65535, file)?; let mut i = 0; let mut size = 0; @@ -103,20 +104,19 @@ impl Header { const HDR_SIZE: usize = std::mem::size_of::
(); -fn main() -> anyhow::Result<()> { - decode_raw("dump.bin")?; -} - -fn decode(filename: &str) -> PyResult>> { - let res = decode_raw(filename)?; +#[pyfunction] +fn decode(filename: &str, frames_root: &str) -> PyResult>> { + let res = + decode_raw(filename, frames_root).map_err(|_| PyValueError::new_err("failed to read"))?; Ok(res.into()) } -fn decode_raw(filename: &str) -> anyhow::Result>> { - let (data, i, size) = get_packets_without_udp_header()?; +fn decode_raw(filename: &str, frames_root: &str) -> anyhow::Result>> { + let (data, i, size) = get_packets_without_udp_header(filename)?; println!("found {} packets, saved {}, {} size", i, data.len(), size); - let mut dump = File::create_new("dump.bin"); + let dump_filename = format!("{}/dump.bin", filename); + let mut dump = File::create_new(dump_filename); let mut frames = vec![]; let mut parts = vec![]; for packet in data.iter() { @@ -135,7 +135,7 @@ fn decode_raw(filename: &str) -> anyhow::Result>> { println!("writing raw pngs"); let pb = ProgressBar::new(frames.len() as u64); for (i, frame) in frames.iter().enumerate().progress_with(pb) { - let name = format!("{:03}.png", i); + let name = format!("{}/{:04}.png", frames_root, i); let path = Path::new(&name); let file = File::create(path).unwrap(); let ref mut w = BufWriter::new(file); @@ -150,7 +150,7 @@ fn decode_raw(filename: &str) -> anyhow::Result>> { let pb = ProgressBar::new(frames.len() as u64); let mut framesu16 = vec![]; for (i, frame) in frames.iter().enumerate().progress_with(pb) { - let name = format!("temp_{:03}.png", i); + let name = format!("{}/temp_{:04}.png", frames_root, i); let path = Path::new(&name); let file = File::create(path).unwrap(); let ref mut w = BufWriter::new(file); @@ -158,8 +158,11 @@ fn decode_raw(filename: &str) -> anyhow::Result>> { encoder.set_color(png::ColorType::Grayscale); encoder.set_depth(png::BitDepth::Eight); let mut writer = encoder.write_header()?; - let p = frame.as_ptr(); - let samples: &[u16] = unsafe { std::slice::from_raw_parts(p.cast(), frame.len() / 2) }; + //let samples: &[u16] = unsafe { std::slice::from_raw_parts(p.cast(), frame.len() / 2) }; + let samples: Vec = (0..frame.len()) + .step_by(2) + .map(|i| u16::from_be_bytes([frame[i], frame[i + 1]])) + .collect(); framesu16.push(samples.clone()); let frame = samples .iter() diff --git a/thermalcamdecoder/src/main.rs b/thermalcamdecoder/src/main.rs index 4aae5b0..196019e 100644 --- a/thermalcamdecoder/src/main.rs +++ b/thermalcamdecoder/src/main.rs @@ -1,168 +1,4 @@ -use indicatif::{ProgressBar, ProgressIterator}; -use png; -use std::fs::File; -use std::io::BufWriter; -use std::io::Write; -use std::path::Path; - -use pcap_parser::traits::PcapReaderIterator; -use pcap_parser::*; - -fn get_packets_without_udp_header() -> anyhow::Result<(Vec>, usize, usize)> { - let file = File::open("in.pcap")?; - let mut cap = PcapNGReader::new(65535, file)?; - let mut i = 0; - let mut size = 0; - let mut data = vec![]; - loop { - match cap.next() { - Ok((offset, packet)) => { - i += 1; - size += offset; - match packet { - PcapBlockOwned::Legacy(_block) => { - println!("dunno"); - } - PcapBlockOwned::LegacyHeader(_block) => { - println!("dunnoheader"); - } - PcapBlockOwned::NG(block) => { - if block.is_data_block() { - match block { - Block::EnhancedPacket(ref epb) => { - if epb.origlen == 6972 { - // remove udp header - data.push(epb.data[0x2a..].to_vec()); - } - } - Block::SimplePacket(ref ep) => { - if ep.origlen == 6972 { - println!("found one regular"); - } - } - _ => { - println!("unsupported packet"); - } - } - } - } - } - cap.consume(offset) - } - Err(PcapError::Eof) => break, - Err(PcapError::Incomplete) => { - cap.refill().unwrap(); - } - Err(_) => { - println!("unexpected error"); - break; - } - } - } - Ok((data, i, size)) -} - -#[repr(C, packed)] -#[derive(Clone, Debug)] -struct Header { - c1: u32, - c2: u16, - part: u16, - a: u16, - ffaa: u16, - b: u16, - c: u16, - d: u16, -} - -impl Header { - fn read(data: &[u8]) -> anyhow::Result { - Ok(Header { - c1: u32::from_be_bytes([data[0], data[1], data[2], data[3]]), - c2: u16::from_be_bytes([data[4], data[5]]), - part: u16::from_be_bytes([data[6], data[7]]), - a: u16::from_be_bytes([data[8], data[9]]), - ffaa: u16::from_be_bytes([data[10], data[11]]), - b: u16::from_be_bytes([data[12], data[13]]), - c: u16::from_be_bytes([data[14], data[15]]), - d: u16::from_be_bytes([data[16], data[17]]), - }) - } - - #[allow(dead_code)] - fn read_via_cast(data: &[u8]) -> anyhow::Result<&Self> { - let size = std::mem::size_of::(); - if data.len() < size { - return Err(anyhow::anyhow!("not large enough")); - } - let mem = &data[..size].as_ptr(); - Ok(unsafe { &*mem.cast() }) - } -} - -const HDR_SIZE: usize = std::mem::size_of::
(); - -fn main() -> anyhow::Result<()> { - let (data, i, size) = get_packets_without_udp_header()?; - - println!("found {} packets, saved {}, {} size", i, data.len(), size); - let mut dump = File::create_new("dump.bin"); - let mut frames = vec![]; - let mut parts = vec![]; - for packet in data.iter() { - if let Ok(ref mut dump) = dump { - dump.write_all(&packet)?; - } - let hdr = Header::read(packet)?; - let data = packet[HDR_SIZE..].to_vec(); - if hdr.part == 0 && parts.len() > 0 { - frames.push(parts.concat()); - parts.clear(); - } - parts.push(data); - } - println!("found {} frames", frames.len()); - println!("writing raw pngs"); - let pb = ProgressBar::new(frames.len() as u64); - for (i, frame) in frames.iter().enumerate().progress_with(pb) { - let name = format!("{:03}.png", i); - let path = Path::new(&name); - let file = File::create(path).unwrap(); - let ref mut w = BufWriter::new(file); - let mut encoder = png::Encoder::new(w, 288, 384); - encoder.set_color(png::ColorType::Grayscale); - encoder.set_depth(png::BitDepth::Sixteen); - let mut writer = encoder.write_header()?; - writer.write_image_data(&frame)?; - } - - println!("writing calibrated (value is temperature)"); - let pb = ProgressBar::new(frames.len() as u64); - for (i, frame) in frames.iter().enumerate().progress_with(pb) { - let name = format!("temp_{:03}.png", i); - let path = Path::new(&name); - let file = File::create(path).unwrap(); - let ref mut w = BufWriter::new(file); - let mut encoder = png::Encoder::new(w, 288, 384); - encoder.set_color(png::ColorType::Grayscale); - encoder.set_depth(png::BitDepth::Eight); - let mut writer = encoder.write_header()?; - let p = frame.as_ptr(); - let samples: &[u16] = unsafe { std::slice::from_raw_parts(p.cast(), frame.len() / 2) }; - let frame = samples - .iter() - .copied() - .map(|x| { - let x: f64 = x.into(); - ((-1.665884e-08) * x.powf(4.) - + (1.347094e-05) * x.powf(3.) - + (-4.396264e-03) * x.powf(2.) - + (9.506939e-01) * x - + (-6.353247e+01)) as u8 - }) - .collect::>(); - writer.write_image_data(&frame)?; - } - - Ok(()) -} +//fn main() -> anyhow::Result<()> { +// decode_raw("dump.bin")?; +// Ok(()) +//}