#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::print_stderr,
reason = "test modules may unwrap / print"
)]
use super::*;
use mediaway_common::{CodecKind, Rational};
fn tiny_h264_cfg(width: u32, height: u32) -> VideoEncoderConfig {
VideoEncoderConfig {
codec: CodecKind::H264,
width,
height,
time_base: Rational::new(1, 30),
bitrate_bps: 500_000,
pixel_format: PixelFormat::Nv12,
color_range: mediaway_common::ColorRange::Video,
input: VideoInputPreference::CpuUploadOk,
gpu_device: None,
gop_size: 1,
rate_control: None,
intra_refresh_period: None,
}
}
#[test]
fn validate_accepts_h264_cpu_upload_config() {
assert!(validate(&tiny_h264_cfg(64, 64)).is_ok());
}
#[test]
fn validate_accepts_hevc_and_av1_cpu_upload_config() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.codec = CodecKind::Hevc;
assert!(validate(&cfg).is_ok());
cfg.codec = CodecKind::Av1;
assert!(validate(&cfg).is_ok());
}
#[test]
fn validate_rejects_vp9_codec() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.codec = CodecKind::Vp9;
assert_eq!(validate(&cfg), Err(EncodeError::Unsupported));
}
#[test]
fn validate_rejects_zero_dimensions() {
let cfg = tiny_h264_cfg(0, 64);
assert_eq!(validate(&cfg), Err(EncodeError::InvalidInput));
}
#[test]
fn validate_rejects_non_nv12_pixel_format() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.pixel_format = PixelFormat::Bgra8;
assert_eq!(validate(&cfg), Err(EncodeError::Unsupported));
}
#[test]
fn validate_rejects_zero_timebase_denominator() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.time_base = Rational::new(1, 0);
assert_eq!(validate(&cfg), Err(EncodeError::InvalidInput));
}
#[test]
fn validate_rejects_zero_gop_size() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.gop_size = 0;
assert_eq!(validate(&cfg), Err(EncodeError::InvalidInput));
}
#[test]
fn stream_info_from_config_carries_geometry_and_timebase() {
let cfg = tiny_h264_cfg(64, 32);
let info = stream_info_from(&cfg);
assert!(matches!(
info,
StreamInfo::Video {
codec: CodecKind::H264,
..
}
));
if let StreamInfo::Video {
time_base,
geometry,
..
} = info
{
assert_eq!(time_base, cfg.time_base);
assert_eq!(geometry.width, 64);
assert_eq!(geometry.height, 32);
}
}
#[test]
fn stream_info_from_carries_hevc_and_av1_codec() {
let mut cfg = tiny_h264_cfg(64, 32);
cfg.codec = CodecKind::Hevc;
let info = stream_info_from(&cfg);
assert!(matches!(
info,
StreamInfo::Video {
codec: CodecKind::Hevc,
..
}
));
cfg.codec = CodecKind::Av1;
let info = stream_info_from(&cfg);
assert!(matches!(
info,
StreamInfo::Video {
codec: CodecKind::Av1,
..
}
));
}
#[test]
fn codec_config_for_dispatches_h264_hevc_av1() {
assert!(matches!(
codec_config_for(CodecKind::H264),
Ok(CodecConfig::H264(_))
));
assert!(matches!(
codec_config_for(CodecKind::Hevc),
Ok(CodecConfig::Hevc(_))
));
assert!(matches!(
codec_config_for(CodecKind::Av1),
Ok(CodecConfig::Av1(_))
));
assert!(matches!(
codec_config_for(CodecKind::Vp9),
Err(EncodeError::Unsupported)
));
}
#[test]
fn amf_open_and_encode_or_skip_without_hw() {
open_encode_or_skip(&tiny_h264_cfg(64, 64), "h264");
}
#[test]
fn amf_open_and_encode_hevc_or_skip_without_hw() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.codec = CodecKind::Hevc;
open_encode_or_skip(&cfg, "hevc");
}
#[test]
fn amf_open_and_encode_av1_or_skip_without_hw() {
let mut cfg = tiny_h264_cfg(64, 64);
cfg.codec = CodecKind::Av1;
open_encode_or_skip(&cfg, "av1");
}
fn open_encode_or_skip(cfg: &VideoEncoderConfig, label: &str) {
let mut session = match AmfSession::open(cfg) {
Ok(s) => s,
Err(e) => {
eprintln!("skip: AmfSession::open failed ({e:?}) — no AMD AMF driver? ({label})");
return;
}
};
let nv12_len = 64 * 64 + (64 * 64) / 2;
let frame = VideoFrame {
pts: 0,
duration: 1,
width: 64,
height: 64,
format: PixelFormat::Nv12,
storage: VideoFrameStorage::Cpu {
data: Bytes::from(vec![0u8; nv12_len]),
},
};
if let Err(e) = session.push_frame(&frame) {
eprintln!("skip: push_frame failed ({e:?}) — no usable AMF encode session? ({label})");
return;
}
let _ = session.flush();
let mut packets = 0usize;
while let Ok(Some(p)) = session.poll_packet() {
assert!(!p.payload.is_empty());
packets += 1;
}
eprintln!("amf {label} cpu-upload packets={packets}");
}