use std::path::Path;
use unbundle::{FrameRange, FrameType, MediaFile};
fn sample_video_path() -> &'static str {
"tests/fixtures/sample_video.mp4"
}
#[test]
fn frame_and_metadata_returns_image_and_metadata() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open");
let (image, info) = unbundler
.video()
.frame_and_metadata(0)
.expect("Failed to extract frame with info");
assert!(image.width() > 0);
assert_eq!(info.frame_number, 0);
}
#[test]
fn frame_and_metadata_first_frame_is_keyframe() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open");
let (_image, info) = unbundler
.video()
.frame_and_metadata(0)
.expect("Failed to extract frame 0");
assert!(info.is_keyframe, "First frame should be a keyframe");
assert_eq!(
info.frame_type,
FrameType::I,
"First frame should be an I-frame"
);
}
#[test]
fn frame_and_metadata_has_timestamp() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open");
let (_image, info) = unbundler
.video()
.frame_and_metadata(30)
.expect("Failed to extract frame 30");
let timestamp_secs = info.timestamp.as_secs_f64();
assert!(
(timestamp_secs - 1.0).abs() < 0.1,
"Expected ~1.0s timestamp, got {timestamp_secs}"
);
}
#[test]
fn frame_and_metadata_has_pts() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open");
let (_image, info) = unbundler
.video()
.frame_and_metadata(0)
.expect("Failed to extract frame 0");
assert!(info.pts.is_some(), "Expected PTS to be present for frame 0");
}
#[test]
fn frames_and_metadata_returns_correct_count() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open");
let results = unbundler
.video()
.frames_and_metadata(FrameRange::Range(0, 4))
.expect("Failed to extract frames with info");
assert_eq!(results.len(), 5, "Expected 5 frames (0..=4)");
for (index, (_image, info)) in results.iter().enumerate() {
assert_eq!(
info.frame_number, index as u64,
"Frame number should match index"
);
}
}
#[test]
fn frame_type_debug_display() {
let frame_type = FrameType::I;
let debug = format!("{frame_type:?}");
assert_eq!(debug, "I");
}
#[test]
fn frame_and_metadata_out_of_range() {
let path = sample_video_path();
if !Path::new(path).exists() {
eprintln!("Skipping: fixture '{path}' not found.");
return;
}
let mut unbundler = MediaFile::open(path).expect("Failed to open");
let frame_count = unbundler.metadata().video.as_ref().unwrap().frame_count;
let result = unbundler.video().frame_and_metadata(frame_count + 100);
assert!(result.is_err(), "Should error on out-of-range frame");
}