use std::time::Duration;
mod fixtures;
use fixtures::*;
use ff_decode::SeekMode;
#[test]
fn test_seek_keyframe_mode() {
let mut decoder = create_decoder().expect("Failed to create decoder");
for _ in 0..5 {
let _ = decoder.decode_one().expect("Failed to decode");
}
let target = Duration::from_secs(2);
let result = decoder.seek(target, SeekMode::Keyframe);
assert!(
result.is_ok(),
"Keyframe seek should succeed: {:?}",
result.err()
);
let frame = decoder
.decode_one()
.expect("Failed to decode after seek")
.expect("Frame should exist after seek");
let frame_time = frame.timestamp().as_duration();
assert!(
frame_time >= Duration::from_secs(1),
"Frame after keyframe seek should be past 1s: frame_time={:?}, target={:?}",
frame_time,
target
);
assert!(
frame_time <= Duration::from_secs(4),
"Frame after keyframe seek should be before 4s: frame_time={:?}, target={:?}",
frame_time,
target
);
}
#[test]
fn test_seek_exact_mode() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let target = Duration::from_secs(3);
let result = decoder.seek(target, SeekMode::Exact);
assert!(
result.is_ok(),
"Exact seek should succeed: {:?}",
result.err()
);
let frame = decoder
.decode_one()
.expect("Failed to decode after seek")
.expect("Frame should exist after seek");
let frame_time = frame.timestamp().as_duration();
assert!(
frame_time >= target,
"Frame timestamp should be at or after target for exact seek: target={:?}, frame_time={:?}",
target,
frame_time
);
let diff = frame_time - target;
assert!(
diff < Duration::from_millis(500),
"Frame timestamp should be close to target: diff={:?}",
diff
);
}
#[test]
fn test_seek_backward_mode() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let target = Duration::from_secs(2);
let result = decoder.seek(target, SeekMode::Backward);
assert!(
result.is_ok(),
"Backward seek should succeed: {:?}",
result.err()
);
let frame = decoder
.decode_one()
.expect("Failed to decode after seek")
.expect("Frame should exist after seek");
let frame_time = frame.timestamp().as_duration();
assert!(
frame_time <= target || (frame_time - target) < Duration::from_millis(100),
"Frame timestamp should be at or slightly after target for backward seek: target={:?}, frame_time={:?}",
target,
frame_time
);
}
#[test]
fn test_seek_to_beginning() {
let mut decoder = create_decoder().expect("Failed to create decoder");
for _ in 0..10 {
let _ = decoder.decode_one().expect("Failed to decode");
}
let result = decoder.seek(Duration::ZERO, SeekMode::Keyframe);
assert!(
result.is_ok(),
"Seek to beginning should succeed: {:?}",
result.err()
);
let frame = decoder
.decode_one()
.expect("Failed to decode after seek to beginning")
.expect("First frame should exist");
let frame_time = frame.timestamp().as_duration();
assert!(
frame_time < Duration::from_secs(1),
"Frame after seek to beginning should be near start: frame_time={:?}",
frame_time
);
}
#[test]
fn test_seek_multiple_times() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let positions = [
Duration::from_secs(5),
Duration::from_secs(2),
Duration::from_secs(8),
Duration::from_secs(1),
];
for (i, &pos) in positions.iter().enumerate() {
let result = decoder.seek(pos, SeekMode::Keyframe);
assert!(
result.is_ok(),
"Seek #{} to {:?} should succeed: {:?}",
i,
pos,
result.err()
);
let frame = decoder
.decode_one()
.unwrap_or_else(|e| panic!("Failed to decode after seek #{}: {:?}", i, e))
.unwrap_or_else(|| panic!("Frame should exist after seek #{}", i));
let frame_time = frame.timestamp().as_duration();
assert!(
frame_time >= Duration::ZERO,
"Frame time should be valid after seek #{}",
i
);
}
}
#[test]
fn test_seek_and_decode_multiple_frames() {
let mut decoder = create_decoder().expect("Failed to create decoder");
decoder
.seek(Duration::from_secs(4), SeekMode::Keyframe)
.expect("Seek should succeed");
let mut frame_count = 0;
for i in 0..5 {
let frame = decoder
.decode_one()
.unwrap_or_else(|e| panic!("Failed to decode frame {} after seek: {:?}", i, e))
.unwrap_or_else(|| panic!("Frame {} should exist after seek", i));
frame_count += 1;
assert!(frame.width() > 0, "Frame {} should be valid", i);
assert!(frame.height() > 0, "Frame {} should be valid", i);
}
assert_eq!(frame_count, 5, "Should decode 5 frames after seeking");
}
#[test]
fn test_seek_beyond_duration() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let far_position = Duration::from_secs(10000);
let result = decoder.seek(far_position, SeekMode::Keyframe);
if result.is_ok() {
let frame = decoder.decode_one().expect("decode_one should not error");
if let Some(f) = frame {
let duration = decoder.duration();
let frame_time = f.timestamp().as_duration();
assert!(
frame_time <= duration,
"Frame time should not exceed duration"
);
}
}
}
#[test]
fn test_position_updates_after_seek() {
let mut decoder = create_decoder().expect("Failed to create decoder");
for _ in 0..5 {
let _ = decoder.decode_one().expect("Failed to decode");
}
let initial_pos = decoder.position();
assert!(
initial_pos < Duration::from_secs(1),
"Initial position should be less than 1s after 5 frames"
);
let target = Duration::from_secs(2);
decoder
.seek(target, SeekMode::Keyframe)
.expect("Seek should succeed");
let frame = decoder
.decode_one()
.expect("Failed to decode after seek")
.expect("Frame should exist after seek");
let pos_after_seek = decoder.position();
let frame_time = frame.timestamp().as_duration();
assert!(
pos_after_seek >= Duration::from_secs(1),
"Position after seek and decode should be close to target: pos={:?}, frame_time={:?}, target={:?}",
pos_after_seek,
frame_time,
target
);
}
#[test]
fn test_frame_iterator_basic() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let frames: Vec<_> = decoder.by_ref().take(10).collect();
assert_eq!(frames.len(), 10, "Should collect 10 frames");
for (i, frame_result) in frames.iter().enumerate() {
assert!(
frame_result.is_ok(),
"Frame {} should be Ok: {:?}",
i,
frame_result
);
}
}
#[test]
fn test_frame_iterator_timestamps_increase() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let mut last_pts = None;
for (i, frame_result) in decoder.by_ref().take(20).enumerate() {
let frame =
frame_result.unwrap_or_else(|e| panic!("Failed to decode frame {}: {:?}", i, e));
let pts = frame.timestamp().pts();
if let Some(last) = last_pts {
assert!(
pts > last,
"Frame {} pts should increase: current={}, last={}",
i,
pts,
last
);
}
last_pts = Some(pts);
}
}
#[test]
fn test_frame_iterator_with_filter() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let target = Duration::from_secs(2);
let late_frames: Vec<_> = decoder
.by_ref()
.filter_map(|r: Result<_, _>| r.ok())
.filter(|f| f.timestamp().as_duration() >= target)
.take(5)
.collect();
assert_eq!(late_frames.len(), 5, "Should collect 5 frames after 2s");
for frame in late_frames {
assert!(
frame.timestamp().as_duration() >= target,
"Frame should be at or after target"
);
}
}
#[test]
fn test_frame_iterator_early_break() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let mut count = 0;
for frame_result in &mut decoder {
let _ = frame_result.expect("Frame should decode successfully");
count += 1;
if count >= 3 {
break;
}
}
assert_eq!(count, 3, "Should decode exactly 3 frames before breaking");
let next_frame = decoder
.decode_one()
.expect("decode_one should work after iterator break")
.expect("Next frame should exist");
assert!(next_frame.width() > 0, "Next frame should be valid");
}
#[test]
fn test_frame_iterator_multiple_iterations() {
let mut decoder = create_decoder().expect("Failed to create decoder");
let first_batch: Vec<_> = decoder.by_ref().take(5).collect();
assert_eq!(first_batch.len(), 5, "First batch should have 5 frames");
decoder
.seek(Duration::ZERO, SeekMode::Keyframe)
.expect("Seek should succeed");
let second_batch: Vec<_> = decoder.by_ref().take(5).collect();
assert_eq!(second_batch.len(), 5, "Second batch should have 5 frames");
}