Skip to content

Commit 124371d

Browse files
author
GP
committed
stream reader class
1 parent 3614dd0 commit 124371d

File tree

2 files changed

+99
-8
lines changed

2 files changed

+99
-8
lines changed

cptv-codec-rs/src/decode/mod.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,58 @@ impl<R: Read> CptvDecoder<R> {
289289
}
290290
}
291291
}
292+
293+
#[cfg(feature = "std")]
294+
pub struct CptvStreamDecoder {
295+
prev_frame: Option<CptvFrame>,
296+
sequence: Vec<usize>,
297+
}
298+
299+
#[cfg(feature = "std")]
300+
impl CptvStreamDecoder {
301+
pub fn new() -> CptvStreamDecoder {
302+
CptvStreamDecoder {
303+
prev_frame: None,
304+
sequence: (0..WIDTH)
305+
.chain((0..WIDTH).rev())
306+
.cycle()
307+
.take(WIDTH * HEIGHT)
308+
.enumerate()
309+
.map(|(index, i)| ((index / WIDTH) * WIDTH) + i)
310+
.skip(1)
311+
.collect(),
312+
}
313+
}
314+
315+
/// Decodes the next frame if any, and returns a reference to the latest decoded frame.
316+
/// If the file header has not yet been decoded, also decodes and stores the Cptv2Header.
317+
pub fn next_frame_from_data(&mut self, data: &[u8]) -> io::Result<(&CptvFrame, usize)> {
318+
let is_tc2 = true;
319+
// Get each frame. The decoder will need to hold onto the previous frame in order
320+
// to decode the next.
321+
let cptv_frame: CptvFrame;
322+
let used;
323+
let initial_len = data.len();
324+
match CptvFrame::from_bytes(data, &self.prev_frame, &self.sequence, is_tc2) {
325+
Ok((remaining, frame)) => {
326+
println!(
327+
"remaining da ta is {:?} total data is {}",
328+
remaining.len(),
329+
data.len()
330+
);
331+
332+
cptv_frame = frame;
333+
self.prev_frame = Some(cptv_frame);
334+
used = initial_len - remaining.len();
335+
}
336+
337+
Err(e) => {
338+
return Err(Error::new(
339+
ErrorKind::Other,
340+
"Unexpected input, CPTV file may be corrupt?",
341+
));
342+
}
343+
}
344+
Ok((self.prev_frame.as_ref().unwrap(), used))
345+
}
346+
}

python-bindings/src/lib.rs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@ use std::fs::File;
22
use std::path::Path;
33

44
use numpy::ndarray::Array;
5-
use numpy::{IntoPyArray, PyArray2};
5+
use numpy::{IntoPyArray, PyArray1, PyArray2, PyArrayMethods, PyReadonlyArrayDyn};
66
use pyo3::prelude::*;
77

8-
use codec::decode::CptvDecoder;
8+
use codec::decode::{CptvDecoder, CptvStreamDecoder};
99

1010
#[pyclass]
1111
struct CptvReader {
1212
inner: CptvDecoder<File>,
1313
}
14+
#[pyclass]
15+
struct CptvStreamReader {
16+
inner: CptvStreamDecoder,
17+
}
1418

1519
#[pyclass(frozen)]
1620
struct CptvHeader {
@@ -77,15 +81,46 @@ struct CptvFrame {
7781
}
7882

7983
#[pymethods]
80-
impl CptvReader {
81-
#[staticmethod]
82-
pub fn new_optional_header(path: String, has_header: bool) -> CptvReader {
83-
CptvReader {
84-
inner: CptvDecoder::<File>::from_path_optional_header(Path::new(&path), has_header)
85-
.unwrap(),
84+
impl CptvStreamReader {
85+
#[new]
86+
pub fn new() -> CptvStreamReader {
87+
CptvStreamReader {
88+
inner: CptvStreamDecoder::new(),
8689
}
8790
}
8891

92+
pub fn next_frame_from_data<'py>(
93+
&mut self,
94+
py: Python<'py>,
95+
data: &Bound<'py, PyArray1<u8>>,
96+
) -> Option<(CptvFrame, usize)> {
97+
let slice: &[u8] = unsafe { data.as_slice().unwrap() };
98+
99+
if let Ok((frame_ref, data_used)) = self.inner.next_frame_from_data(slice) {
100+
let chunk: numpy::ndarray::ArrayBase<
101+
numpy::ndarray::OwnedRepr<u16>,
102+
numpy::ndarray::Dim<[usize; 2]>,
103+
> = Array::from_shape_vec((120, 160), frame_ref.image_data.data().to_vec()).unwrap();
104+
105+
Some((
106+
CptvFrame {
107+
time_on: frame_ref.time_on,
108+
last_ffc_time: frame_ref.last_ffc_time,
109+
temp_c: frame_ref.frame_temp_c,
110+
last_ffc_temp_c: frame_ref.last_ffc_temp_c,
111+
background_frame: frame_ref.is_background_frame,
112+
pix: Bound::unbind(chunk.into_pyarray_bound(py)),
113+
},
114+
data_used,
115+
))
116+
} else {
117+
None
118+
}
119+
}
120+
}
121+
122+
#[pymethods]
123+
impl CptvReader {
89124
#[new]
90125
pub fn new(path: String) -> CptvReader {
91126
CptvReader {
@@ -148,5 +183,6 @@ impl CptvReader {
148183
#[pymodule]
149184
fn cptv_rs_python_bindings(_py: Python, m: &PyModule) -> PyResult<()> {
150185
m.add_class::<CptvReader>()?;
186+
m.add_class::<CptvStreamReader>()?;
151187
Ok(())
152188
}

0 commit comments

Comments
 (0)