From f3d93d1b84fb2273b8dbc17dc95335feee8d06b6 Mon Sep 17 00:00:00 2001 From: Dominik Winecki Date: Thu, 8 Jan 2026 22:10:57 +0000 Subject: [PATCH 1/3] Bump opendal version --- vidformer/Cargo.toml | 2 +- vidformer/src/av/demuxer.rs | 4 ++-- vidformer/src/service.rs | 13 +++++-------- vidformer/src/source.rs | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/vidformer/Cargo.toml b/vidformer/Cargo.toml index 4b3b86fb..c7355cd2 100644 --- a/vidformer/Cargo.toml +++ b/vidformer/Cargo.toml @@ -24,6 +24,6 @@ thiserror = "2.0.3" opencv = { version = "0.98.0", default-features = false, features = ["clang-runtime", "imgproc"] } crossbeam-channel = "0.5" parking_lot = "0.12.2" -opendal = { version = "0.52", features = ["layers-blocking", "services-fs", "services-http"] } +opendal = { version = "0.55", features = ["blocking", "services-fs", "services-http"] } tokio = { version = "1", features = ["full"] } flate2 = "1.0" diff --git a/vidformer/src/av/demuxer.rs b/vidformer/src/av/demuxer.rs index b26762f7..b98f2039 100644 --- a/vidformer/src/av/demuxer.rs +++ b/vidformer/src/av/demuxer.rs @@ -107,7 +107,7 @@ impl Demuxer { let op = service.blocking_operator(io_runtime_handle)?; - let reader: opendal::BlockingReader = op.reader(file_path).map_err(|e| { + let reader: opendal::blocking::Reader = op.reader(file_path).map_err(|e| { if e.kind() == opendal::ErrorKind::NotFound { crate::Error::IOError(format!("File `{}` not found", file_path)) } else { @@ -115,7 +115,7 @@ impl Demuxer { } })?; - let reader: opendal::StdReader = match reader.into_std_read(0..file_size) { + let reader: opendal::blocking::StdReader = match reader.into_std_read(0..file_size) { Ok(reader) => reader, Err(err) => { return Err(crate::Error::IOError(format!( diff --git a/vidformer/src/service.rs b/vidformer/src/service.rs index 09beff29..c370ee01 100644 --- a/vidformer/src/service.rs +++ b/vidformer/src/service.rs @@ -61,16 +61,13 @@ impl Service { pub(crate) fn blocking_operator( &self, io_runtime: &tokio::runtime::Handle, - ) -> Result { + ) -> Result { let op = self.operator()?; - let bop = if op.info().full_capability().blocking { - op.blocking() - } else { - let _x = io_runtime.enter(); - op.layer(opendal::layers::BlockingLayer::create().unwrap()) - .blocking() - }; + let _guard = io_runtime.enter(); + let bop = opendal::blocking::Operator::new(op).map_err(|e| { + crate::Error::AVError(format!("failed to create blocking operator: {}", e)) + })?; Ok(bop) } diff --git a/vidformer/src/source.rs b/vidformer/src/source.rs index 65d4c9db..25bd38c2 100644 --- a/vidformer/src/source.rs +++ b/vidformer/src/source.rs @@ -46,7 +46,7 @@ impl SourceVideoStreamMeta { let file_size = { let op = service.blocking_operator(io_runtime.handle())?; - let file_stat = op.stat(vid_path); + let file_stat: Result = op.stat(vid_path); let file_stat = match file_stat { Ok(stat) => stat, From 7cdf4a9297ffa1fe40b6870cbdd4e05b1460ca5a Mon Sep 17 00:00:00 2001 From: Dominik Winecki Date: Thu, 8 Jan 2026 23:12:32 +0000 Subject: [PATCH 2/3] Add VideoWriter.isOpened() --- snake-pit/test_cv2.py | 1 + vidformer-py/vidformer/cv2/__init__.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/snake-pit/test_cv2.py b/snake-pit/test_cv2.py index f1c352f6..faadac53 100644 --- a/snake-pit/test_cv2.py +++ b/snake-pit/test_cv2.py @@ -126,6 +126,7 @@ def rw(cv2): path = tmp_path("mp4") out = cv2.VideoWriter(path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height)) + assert out.isOpened() count = 0 while True: diff --git a/vidformer-py/vidformer/cv2/__init__.py b/vidformer-py/vidformer/cv2/__init__.py index 72f1b28d..aeb2e548 100644 --- a/vidformer-py/vidformer/cv2/__init__.py +++ b/vidformer-py/vidformer/cv2/__init__.py @@ -503,6 +503,9 @@ def write(self, frame): if len(self._feb) >= self._batch_size: self._flush() + def isOpened(self): + return True + def release(self): self._flush(True) if self._path is not None: From e4b5a7e9aec39d97f95319a25eeda32f6ebbb042 Mon Sep 17 00:00:00 2001 From: Dominik Winecki Date: Sun, 25 Jan 2026 01:51:00 +0000 Subject: [PATCH 3/3] Add opendal false leak valgrind exception --- scripts/valgrind_test.sh | 4 +++- scripts/vidformer.supp | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 scripts/vidformer.supp diff --git a/scripts/valgrind_test.sh b/scripts/valgrind_test.sh index 489b3e96..629d8fff 100755 --- a/scripts/valgrind_test.sh +++ b/scripts/valgrind_test.sh @@ -4,4 +4,6 @@ set -e ./ffmpeg/build/bin/ffmpeg -y -i tos_720p.mp4 -c:v copy -c:a copy -t 30 tos_720p_short.mp4 -valgrind --error-exitcode=1 --leak-check=full target/debug/vidformer-cli validate --name tos_720p_short --vid-path tos_720p_short.mp4 --stream 0 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +valgrind --error-exitcode=1 --leak-check=full --suppressions="$SCRIPT_DIR/vidformer.supp" target/debug/vidformer-cli validate --name tos_720p_short --vid-path tos_720p_short.mp4 --stream 0 +rm tos_720p_short.mp4 diff --git a/scripts/vidformer.supp b/scripts/vidformer.supp new file mode 100644 index 00000000..adf170d0 --- /dev/null +++ b/scripts/vidformer.supp @@ -0,0 +1,23 @@ +# Rustls TLS session cache - uses lazy_static/once_cell pattern +# This is intentionally never freed as the OS cleans up on exit +{ + rustls-session-cache + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:*hashbrown* + ... + fun:*rustls*ClientSessionMemoryCache* +} + +{ + rustls-session-cache-2 + Memcheck:Leak + match-leak-kinds: possible + fun:malloc + ... + fun:*LimitedCache* + ... + fun:*ClientSessionMemoryCache* +}