diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0008cfa..3d1d663 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,10 +1,10 @@ -FROM mcr.microsoft.com/devcontainers/rust:0-1-bullseye +FROM mcr.microsoft.com/devcontainers/rust:latest RUN apt-get update && \ apt-get install -y cmake llvm-dev libclang-dev clang && \ apt-get clean -RUN git clone --depth 1 -b v2.0.0 https://github.com/fraunhoferhhi/vvdec.git && \ +RUN git clone --depth 1 -b v2.1.0 https://github.com/fraunhoferhhi/vvdec.git && \ cd vvdec && \ make install-release-shared install-vvdecapp=1 install-prefix=/usr && \ rm -rf vvdec diff --git a/src/lib.rs b/src/lib.rs index 978b2c6..1e5f406 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,11 +41,12 @@ impl Decoder { pub fn decode( &mut self, - data: &[u8], + data: impl AsRef<[u8]>, cts: Option, dts: Option, is_random_access_point: bool, ) -> Result, Error> { + let data = data.as_ref(); let mut au = vvdecAccessUnit { payload: data.as_ptr() as *mut u8, payloadSize: data.len() as i32, @@ -94,6 +95,9 @@ impl Decoder { } } +unsafe impl Sync for Decoder {} +unsafe impl Send for Decoder {} + pub struct Params { params: vvdecParams, } @@ -249,6 +253,9 @@ impl Display for Frame { } } +unsafe impl Send for Frame {} +unsafe impl Sync for Frame {} + #[derive(Debug)] pub struct InnerFrame { decoder: Decoder, @@ -349,7 +356,10 @@ impl Deref for Plane { } } -#[derive(Debug)] +unsafe impl Send for Plane {} +unsafe impl Sync for Plane {} + +#[derive(Debug, Clone, Copy)] pub enum PlaneComponent { Y, U, @@ -367,6 +377,16 @@ impl PlaneComponent { } } +impl From for usize { + fn from(value: PlaneComponent) -> Self { + match value { + PlaneComponent::Y => 0, + PlaneComponent::U => 1, + PlaneComponent::V => 2, + } + } +} + #[derive(Debug)] pub struct PictureAttributes { pub nal_type: NalType, diff --git a/tests/basic.rs b/tests/basic.rs index a219155..cf2fcb2 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -40,10 +40,7 @@ fn basic() -> Result<(), Error> { Ok(()) } -#[test] -fn split_data() -> Result<(), Error> { - let mut decoder = Decoder::new().unwrap(); - +fn split_data(data: &[u8]) -> Vec<&[u8]> { const ANNEX_B_START_CODE: &[u8] = &[0, 0, 0, 1]; let mut indices: Vec<_> = DATA .windows(4) @@ -52,9 +49,19 @@ fn split_data() -> Result<(), Error> { .map(|(i, _)| i) .collect(); indices.push(DATA.len()); - for pair in indices.windows(2) { - let sub_slice = &DATA[pair[0]..pair[1]]; - let _ = decoder.decode(sub_slice, Some(0), Some(0), false); + + indices + .windows(2) + .map(|pair| &data[pair[0]..pair[1]]) + .collect() +} + +#[test] +fn test_split_data() -> Result<(), Error> { + let mut decoder = Decoder::new().unwrap(); + + for slice in split_data(DATA) { + let _ = decoder.decode(slice, Some(0), Some(0), false); } let frame1 = decoder.flush()?; @@ -77,3 +84,54 @@ fn split_data() -> Result<(), Error> { Ok(()) } + +#[test] +fn test_decode_after_flush() -> Result<(), Error> { + let mut decoder = Decoder::new().unwrap(); + + let mut slices = split_data(DATA).into_iter(); + let sps = slices.next().unwrap(); + let pps = slices.next().unwrap(); + let frame1 = slices.next().unwrap(); + let frame2 = slices.next().unwrap(); + let frame3 = slices.next().unwrap(); + + let _ = decoder.decode(sps, None, None, false); + let _ = decoder.decode(pps, None, None, false); + let _ = decoder.decode(frame1, None, None, false); + let _ = decoder.decode(frame2, None, None, false); + + assert!(decoder.flush().is_ok()); + assert!(decoder.flush().is_ok()); + assert_eq!(decoder.flush().unwrap_err(), Error::Eof); + + let _ = decoder.decode(sps, None, None, false); + let _ = decoder.decode(pps, None, None, false); + let _ = decoder.decode(frame1, None, None, false); + let _ = decoder.decode(frame2, None, None, false); + let _ = decoder.decode(frame3, None, None, false); + assert!(decoder.flush().is_ok()); + assert!(decoder.flush().is_ok()); + assert!(decoder.flush().is_ok()); + assert_eq!(decoder.flush().unwrap_err(), Error::Eof); + + Ok(()) +} + +#[test] +fn test_change_resolution() -> Result<(), Error> { + let mut decoder = Decoder::new().unwrap(); + + let _ = decoder.decode(DATA, None, None, false); + let first_frame = decoder.flush().unwrap(); + assert_eq!(first_frame.width(), 320); + assert_eq!(first_frame.height(), 240); + + const SECOND_DATA: &[u8] = include_bytes!("../tests/short2.vvc"); + let _ = decoder.decode(SECOND_DATA, None, None, false); + let first_frame = decoder.flush().unwrap(); + assert_eq!(first_frame.width(), 160); + assert_eq!(first_frame.height(), 120); + + Ok(()) +} diff --git a/tests/short2.vvc b/tests/short2.vvc new file mode 100644 index 0000000..12c50b3 Binary files /dev/null and b/tests/short2.vvc differ diff --git a/vvdec-sys/build.rs b/vvdec-sys/build.rs index 7092789..16e45da 100644 --- a/vvdec-sys/build.rs +++ b/vvdec-sys/build.rs @@ -1,7 +1,7 @@ use std::env; use std::path::PathBuf; -const VVDEC_VERSION: &str = "2.0.0"; +const VVDEC_VERSION: &str = "2.1.0"; mod build { use super::*;