use std::path::PathBuf;
use std::time::Duration;
use ff_preview::{DecodeBuffer, FrameResult};
fn test_file_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../assets/test/av_sync_test_60s.mp4")
}
#[test]
#[ignore = "requires assets/test/av_sync_test_60s.mp4; run with -- --include-ignored"]
fn seek_to_30s_should_deliver_frame_within_one_frame_period() {
let path = test_file_path();
if !path.exists() {
println!("skipping: reference file not found at {}", path.display());
return;
}
let mut buf = match DecodeBuffer::open(&path).build() {
Ok(b) => b,
Err(e) => {
println!("skipping: {e}");
return;
}
};
let target = Duration::from_secs(30);
if let Err(e) = buf.seek(target) {
println!("skipping: seek not supported: {e}");
return;
}
let frame = loop {
match buf.pop_frame() {
FrameResult::Frame(f) => break f,
FrameResult::Seeking(_) => std::thread::sleep(Duration::from_millis(5)),
FrameResult::Eof => {
panic!("EOF reached before any frame was delivered after seek to {target:?}");
}
}
};
let one_frame = Duration::from_millis(34);
let pts = frame.timestamp().as_duration();
assert!(
pts >= target.saturating_sub(one_frame),
"post-seek frame PTS must be ≥ (target − 1 frame); \
target={target:?} pts={pts:?}"
);
assert!(
pts <= target + one_frame,
"post-seek frame PTS must be ≤ (target + 1 frame); \
target={target:?} pts={pts:?}"
);
}