#![allow(clippy::unwrap_used, reason = "allow in test files")]
use std::num::{NonZeroU8, NonZeroUsize};
use crate::{
analysis::MVAnalysisData,
filters::{
analyse::{Analyse, AnalyseOptions, SuperClipInfo},
recalculate::{Recalculate, RecalculateOptions},
},
frame::{Frame, FramePlane},
params::{DivideMode, MVPlaneSet, MotionFlags, SearchType, Subpel},
video::{ColorFamily, Resolution, SampleType, VideoFormat, VideoInfo},
};
fn yuv420p8_super_info() -> (VideoInfo, SuperClipInfo) {
let format = VideoFormat {
color_family: ColorFamily::Yuv,
sample_type: SampleType::Integer,
bits_per_sample: NonZeroU8::new(8).unwrap(),
bytes_per_sample: NonZeroU8::new(1).unwrap(),
sub_sampling_w: 1,
sub_sampling_h: 1,
};
let info = VideoInfo {
format,
resolution: Resolution {
width: 672,
height: 2750,
},
num_frames: 10,
};
let super_info = SuperClipInfo {
height: NonZeroUsize::new(480).unwrap(),
hpad: 16,
vpad: 16,
pel: Subpel::Half,
mode_yuv: MVPlaneSet::YUVPLANES,
levels: 8,
};
(info, super_info)
}
fn gray8_super_info() -> (VideoInfo, SuperClipInfo) {
let format = VideoFormat {
color_family: ColorFamily::Gray,
sample_type: SampleType::Integer,
bits_per_sample: NonZeroU8::new(8).unwrap(),
bytes_per_sample: NonZeroU8::new(1).unwrap(),
sub_sampling_w: 0,
sub_sampling_h: 0,
};
let info = VideoInfo {
format,
resolution: Resolution {
width: 672,
height: 2750,
},
num_frames: 10,
};
let super_info = SuperClipInfo {
height: NonZeroUsize::new(480).unwrap(),
hpad: 16,
vpad: 16,
pel: Subpel::Half,
mode_yuv: MVPlaneSet::YPLANE,
levels: 8,
};
(info, super_info)
}
fn sample_vectors_data(
x_ratio_uv: NonZeroU8,
y_ratio_uv: NonZeroU8,
motion_flags: MotionFlags,
) -> MVAnalysisData {
MVAnalysisData {
blk_size_x: NonZeroUsize::new(8).unwrap(),
blk_size_y: NonZeroUsize::new(8).unwrap(),
pel: Subpel::Half,
level_count: 1,
delta_frame: 1,
is_backward: false,
motion_flags,
width: NonZeroUsize::new(640).unwrap(),
height: NonZeroUsize::new(480).unwrap(),
overlap_x: 0,
overlap_y: 0,
blk_x: NonZeroUsize::new(80).unwrap(),
blk_y: NonZeroUsize::new(60).unwrap(),
bits_per_sample: NonZeroU8::new(8).unwrap(),
y_ratio_uv,
x_ratio_uv,
h_padding: 16,
v_padding: 16,
}
}
fn tiny_super_frame() -> Frame<u8> {
let y = FramePlane::new(
vec![0u8; 672 * 2750].into_boxed_slice(),
NonZeroUsize::new(672).unwrap(),
NonZeroUsize::new(2750).unwrap(),
NonZeroUsize::new(672).unwrap(),
)
.unwrap();
let u = FramePlane::new(
vec![0u8; 336 * 1375].into_boxed_slice(),
NonZeroUsize::new(336).unwrap(),
NonZeroUsize::new(1375).unwrap(),
NonZeroUsize::new(336).unwrap(),
)
.unwrap();
let v = FramePlane::new(
vec![0u8; 336 * 1375].into_boxed_slice(),
NonZeroUsize::new(336).unwrap(),
NonZeroUsize::new(1375).unwrap(),
NonZeroUsize::new(336).unwrap(),
)
.unwrap();
Frame::new([Some(y), Some(u), Some(v)])
}
#[test]
fn recalculate_new_defaults_match_vapoursynth_filter_defaults() {
let (info, super_info) = yuv420p8_super_info();
let recalculate = Recalculate::new(
info,
super_info,
sample_vectors_data(
NonZeroU8::new(2).unwrap(),
NonZeroU8::new(2).unwrap(),
MotionFlags::USE_CHROMA_MOTION,
),
RecalculateOptions::default(),
)
.unwrap();
assert_eq!(recalculate.search_type(), SearchType::Hex2);
assert_eq!(recalculate.search_param(), 2);
assert_eq!(recalculate.lambda(), 1000);
assert_eq!(recalculate.penalty_new(), 50);
assert_eq!(recalculate.dct_mode(), crate::params::DctMode::Spatial);
assert_eq!(recalculate.divide_extra(), DivideMode::None);
assert!(recalculate.smooth());
assert!(recalculate.meander());
assert!(!recalculate.fields());
let data = recalculate.analysis_data();
assert_eq!(data.blk_size_x.get(), 8);
assert_eq!(data.blk_size_y.get(), 8);
assert_eq!(data.motion_flags, MotionFlags::USE_CHROMA_MOTION);
assert_eq!(data.width.get(), 640);
assert_eq!(data.height.get(), 480);
assert!(recalculate.analysis_data_divided().is_none());
}
#[test]
fn recalculate_new_rejects_gray_when_chroma_requested() {
let (info, super_info) = gray8_super_info();
let err = Recalculate::new(
info,
super_info,
sample_vectors_data(
NonZeroU8::new(1).unwrap(),
NonZeroU8::new(1).unwrap(),
MotionFlags::empty(),
),
RecalculateOptions {
chroma: Some(true),
..RecalculateOptions::default()
},
)
.unwrap_err();
assert_eq!(
err.to_string(),
"Recalculate: super clip does not contain needed colour data."
);
}
#[test]
fn recalculate_frame_with_divide_emits_divided_analysis_data() {
let (info, super_info) = yuv420p8_super_info();
let analyse = Analyse::new(info, super_info, AnalyseOptions::default()).unwrap();
let recalculate = Recalculate::new(
info,
super_info,
analyse.analysis_data(),
RecalculateOptions {
divide_extra: Some(DivideMode::Original),
..RecalculateOptions::default()
},
)
.unwrap();
let src = tiny_super_frame();
let reference = tiny_super_frame();
let src_view = src.as_view().unwrap();
let reference_view = reference.as_view().unwrap();
let analysed = analyse
.analyse_frame(
1,
&src_view,
Some(&reference_view),
Some(false),
Some(false),
)
.unwrap();
let output = recalculate
.recalculate_frame(
&src_view,
Some(&reference_view),
&analysed.vectors.block_data,
Some(false),
Some(false),
)
.unwrap();
assert_eq!(
output.analysis_data,
recalculate.analysis_data_divided().unwrap()
);
}
#[test]
fn recalculate_frame_with_borrowed_views_returns_valid_vectors() {
let (info, super_info) = yuv420p8_super_info();
let analyse = Analyse::new(info, super_info, AnalyseOptions::default()).unwrap();
let recalculate = Recalculate::new(
info,
super_info,
analyse.analysis_data(),
RecalculateOptions::default(),
)
.unwrap();
let src = tiny_super_frame();
let reference = tiny_super_frame();
let src_view = src.as_view().unwrap();
let reference_view = reference.as_view().unwrap();
let analysed = analyse
.analyse_frame(
1,
&src_view,
Some(&reference_view),
Some(false),
Some(false),
)
.unwrap();
let output = recalculate
.recalculate_frame(
&src_view,
Some(&reference_view),
&analysed.vectors.block_data,
Some(false),
Some(false),
)
.unwrap();
assert_eq!(output.analysis_data, recalculate.analysis_data());
assert!(output.vectors.validity);
}
#[test]
fn recalculate_frame_without_reference_returns_default_vectors() {
let (info, super_info) = yuv420p8_super_info();
let analyse = Analyse::new(info, super_info, AnalyseOptions::default()).unwrap();
let recalculate = Recalculate::new(
info,
super_info,
analyse.analysis_data(),
RecalculateOptions::default(),
)
.unwrap();
let src = tiny_super_frame();
let reference = tiny_super_frame();
let src_view = src.as_view().unwrap();
let reference_view = reference.as_view().unwrap();
let analysed = analyse
.analyse_frame(
1,
&src_view,
Some(&reference_view),
Some(false),
Some(false),
)
.unwrap();
let output = recalculate
.recalculate_frame(
&src_view,
None,
&analysed.vectors.block_data,
Some(false),
None,
)
.unwrap();
assert_eq!(output.analysis_data, recalculate.analysis_data());
assert!(!output.vectors.validity);
}