mod fixtures;
use fixtures::*;
use ff_decode::{DecodeError, HardwareAccel, VideoDecoder};
use ff_format::PixelFormat;
#[test]
fn output_size_should_scale_frame_to_exact_dimensions() {
let path = test_video_path();
let mut decoder = VideoDecoder::open(&path)
.output_size(320, 240)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let frame = decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
assert_eq!(frame.width(), 320, "Width should be 320");
assert_eq!(frame.height(), 240, "Height should be 240");
}
#[test]
fn output_size_combined_with_output_format_should_convert_and_scale() {
let path = test_video_path();
let mut decoder = VideoDecoder::open(&path)
.output_format(PixelFormat::Rgb24)
.output_size(160, 120)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let frame = decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
assert_eq!(frame.width(), 160);
assert_eq!(frame.height(), 120);
assert_eq!(frame.format(), PixelFormat::Rgb24);
}
#[test]
fn output_width_should_scale_to_given_width_and_preserve_aspect_ratio() {
let path = test_video_path();
let mut src_decoder = VideoDecoder::open(&path)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let src_frame = src_decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
let src_w = src_frame.width() as f64;
let src_h = src_frame.height() as f64;
let src_ratio = src_w / src_h;
let target_w = 640u32;
let mut decoder = VideoDecoder::open(&path)
.output_width(target_w)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let frame = decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
assert_eq!(frame.width(), target_w, "Width should match target");
assert_eq!(frame.height() % 2, 0, "Height must be even");
let dst_ratio = frame.width() as f64 / frame.height() as f64;
let tolerance = 1.0 / frame.height() as f64;
assert!(
(dst_ratio - src_ratio).abs() < tolerance + 0.02,
"Aspect ratio should be preserved: src={src_ratio:.3} dst={dst_ratio:.3}"
);
}
#[test]
fn output_height_should_scale_to_given_height_and_preserve_aspect_ratio() {
let path = test_video_path();
let mut src_decoder = VideoDecoder::open(&path)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let src_frame = src_decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
let src_w = src_frame.width() as f64;
let src_h = src_frame.height() as f64;
let src_ratio = src_w / src_h;
let target_h = 360u32;
let mut decoder = VideoDecoder::open(&path)
.output_height(target_h)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let frame = decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
assert_eq!(frame.height(), target_h, "Height should match target");
assert_eq!(frame.width() % 2, 0, "Width must be even");
let dst_ratio = frame.width() as f64 / frame.height() as f64;
let tolerance = 1.0 / frame.width() as f64;
assert!(
(dst_ratio - src_ratio).abs() < tolerance + 0.02,
"Aspect ratio should be preserved: src={src_ratio:.3} dst={dst_ratio:.3}"
);
}
#[test]
fn output_size_after_output_width_should_win() {
let path = test_video_path();
let mut decoder = VideoDecoder::open(&path)
.output_width(9999) .output_size(160, 90)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
let frame = decoder
.decode_one()
.expect("Failed to decode")
.expect("First frame should exist");
assert_eq!(frame.width(), 160);
assert_eq!(frame.height(), 90);
}
#[test]
fn output_size_zero_width_should_return_invalid_dimensions_error() {
let result = VideoDecoder::open("nonexistent_file.mp4")
.output_size(0, 240)
.build();
assert!(
matches!(result, Err(DecodeError::InvalidOutputDimensions { .. })),
"Expected InvalidOutputDimensions"
);
}
#[test]
fn output_size_zero_height_should_return_invalid_dimensions_error() {
let result = VideoDecoder::open("nonexistent_file.mp4")
.output_size(320, 0)
.build();
assert!(
matches!(result, Err(DecodeError::InvalidOutputDimensions { .. })),
"Expected InvalidOutputDimensions"
);
}
#[test]
fn output_width_zero_should_return_invalid_dimensions_error() {
let result = VideoDecoder::open("nonexistent_file.mp4")
.output_width(0)
.build();
assert!(
matches!(result, Err(DecodeError::InvalidOutputDimensions { .. })),
"Expected InvalidOutputDimensions"
);
}
#[test]
fn output_height_zero_should_return_invalid_dimensions_error() {
let result = VideoDecoder::open("nonexistent_file.mp4")
.output_height(0)
.build();
assert!(
matches!(result, Err(DecodeError::InvalidOutputDimensions { .. })),
"Expected InvalidOutputDimensions"
);
}
#[test]
fn output_size_should_produce_correct_dimensions_across_multiple_frames() {
let path = test_video_path();
let mut decoder = VideoDecoder::open(&path)
.output_size(320, 240)
.hardware_accel(HardwareAccel::None)
.build()
.expect("Failed to create decoder");
for i in 0..5 {
let frame = decoder
.decode_one()
.unwrap_or_else(|e| panic!("Frame {i} decode error: {e}"))
.unwrap_or_else(|| panic!("Frame {i} should exist"));
assert_eq!(frame.width(), 320, "Frame {i}: width should be 320");
assert_eq!(frame.height(), 240, "Frame {i}: height should be 240");
}
}