#![forbid(unsafe_code)]
#![allow(dead_code)]
#![allow(clippy::doc_markdown)]
pub mod cache;
pub mod diamond;
pub mod hierarchical;
pub mod partition;
pub mod predictor;
pub mod search;
pub mod subpel;
pub mod types;
pub use cache::{CacheManager, CoLocatedMvLookup, MvCache, MvCacheEntry, RefFrameMvs};
pub use diamond::{
AdaptiveDiamond, CrossDiamond, ExtendedDiamond, HexagonalSearch, LargeDiamond,
PredictorDiamond, SmallDiamond, UMHexSearch,
};
pub use hierarchical::{
CoarseToFineRefiner, HierarchicalConfig, HierarchicalSearch, ImagePyramid, PyramidLevel,
};
pub use partition::{
InterMode, MergeCandidate, MergeCandidateList, PartitionContext, PartitionDecider,
PartitionDecision, PartitionType, SkipDetector, SplitDecision,
};
pub use predictor::{
MvCandidate, MvCostCalculator, MvPredContext, MvPredictor, MvPredictorList, MvpMode,
NeighborInfo, NeighborPosition, SpatialPredictor, TemporalPredictor,
};
pub use search::{
AdaptiveSearch, DiamondSearch, FullSearch, HexagonSearch, MotionSearch, SearchConfig,
SearchContext, ThreeStepSearch, UmhSearch,
};
pub use subpel::{
HadamardTransform, HalfPelFilter, HalfPelInterpolator, QuarterPelFilter,
QuarterPelInterpolator, SatdCalculator, SubpelConfig, SubpelPatterns, SubpelRefiner,
};
pub use types::{BlockMatch, BlockSize, MotionVector, MvCost, MvPrecision, SearchRange};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_module_imports() {
let mv = MotionVector::new(10, 20);
assert_eq!(mv.dx, 10);
assert_eq!(mv.dy, 20);
let range = SearchRange::symmetric(32);
assert_eq!(range.horizontal, 32);
let block_match = BlockMatch::zero_mv(100);
assert_eq!(block_match.sad, 100);
}
#[test]
fn test_search_algorithm_creation() {
let _full = FullSearch::new();
let _diamond = DiamondSearch::new();
let _hexagon = HexagonSearch::new();
let _umh = UmhSearch::new();
let _adaptive = AdaptiveSearch::new();
let _three_step = ThreeStepSearch::new();
}
#[test]
fn test_diamond_patterns() {
let small = SmallDiamond::new();
let large = LargeDiamond::new();
assert_eq!(small.size(), 4);
assert_eq!(large.size(), 8);
}
#[test]
fn test_predictor_creation() {
let predictor = MvPredictor::new();
let mvp = predictor.best_mvp();
assert!(mvp.is_zero());
}
#[test]
fn test_cache_creation() {
let cache = MvCache::new();
assert_eq!(cache.mi_cols(), 0);
assert_eq!(cache.mi_rows(), 0);
}
#[test]
fn test_partition_types() {
assert_eq!(PartitionType::None.num_parts(), 1);
assert_eq!(PartitionType::Split.num_parts(), 4);
}
#[test]
fn test_subpel_components() {
let _satd = SatdCalculator::new();
let identical = vec![128u8; 16];
let result = SatdCalculator::satd_4x4(&identical, 4, &identical, 4);
assert_eq!(result, 0);
}
#[test]
fn test_hierarchical_components() {
let pyramid = ImagePyramid::new();
assert_eq!(pyramid.num_levels(), 0);
let config = HierarchicalConfig::new(3);
assert_eq!(config.levels, 3);
}
#[test]
fn test_mv_precision() {
assert_eq!(MvPrecision::FullPel.fractional_bits(), 0);
assert_eq!(MvPrecision::HalfPel.fractional_bits(), 1);
assert_eq!(MvPrecision::QuarterPel.fractional_bits(), 2);
assert_eq!(MvPrecision::EighthPel.fractional_bits(), 3);
}
#[test]
fn test_block_sizes() {
assert_eq!(BlockSize::Block4x4.width(), 4);
assert_eq!(BlockSize::Block8x8.width(), 8);
assert_eq!(BlockSize::Block16x16.width(), 16);
assert_eq!(BlockSize::Block64x64.width(), 64);
assert_eq!(BlockSize::Block128x128.width(), 128);
}
#[test]
fn test_integration_search_workflow() {
let src = vec![100u8; 64]; let mut reference = vec![50u8; 256];
for row in 0..8 {
for col in 0..8 {
reference[(row + 4) * 16 + col + 4] = 100;
}
}
let ctx = SearchContext::new(&src, 8, &reference, 16, BlockSize::Block8x8, 0, 0, 16, 16);
let config = SearchConfig::default().range(SearchRange::symmetric(8));
let full_result = FullSearch::new().search(&ctx, &config);
let diamond_result = DiamondSearch::new().search(&ctx, &config);
let hex_result = HexagonSearch::new().search(&ctx, &config);
assert!(full_result.sad < 1000);
assert!(diamond_result.sad < 1000);
assert!(hex_result.sad < 1000);
assert_eq!(full_result.mv.full_pel_x(), 4);
assert_eq!(full_result.mv.full_pel_y(), 4);
}
}