use anyhow::{bail, Result};
use std::ffi::c_void;
use crate::frame::{PixelFormat, TransferFn};
use super::{
AMF_AV1_COLOR_BIT_DEPTH_8, AMF_AV1_COLOR_BIT_DEPTH_10, AMF_OK, AMF_SURFACE_NV12,
AMF_SURFACE_P010, AmfComponentVtbl, AmfVariant,
};
pub(super) fn wide(s: &str) -> Vec<u16> {
let mut out: Vec<u16> = s.encode_utf16().collect();
out.push(0);
out
}
pub(super) fn prop(s: &str) -> Vec<u16> {
wide(s)
}
pub(super) fn amf_surface_format_for(fmt: PixelFormat) -> Result<i32> {
match fmt {
PixelFormat::Yuv420p => Ok(AMF_SURFACE_NV12),
PixelFormat::Yuv420p10le => Ok(AMF_SURFACE_P010),
other => bail!("AMF AV1 expects Yuv420p or Yuv420p10le, got {other:?}"),
}
}
pub(super) const fn amf_color_bit_depth_for(fmt: PixelFormat) -> i64 {
match fmt {
PixelFormat::Yuv420p10le => AMF_AV1_COLOR_BIT_DEPTH_10,
_ => AMF_AV1_COLOR_BIT_DEPTH_8,
}
}
const _: () = assert!(amf_color_bit_depth_for(PixelFormat::Yuv420p10le) == 2);
const _: () = assert!(amf_color_bit_depth_for(PixelFormat::Yuv420p) == 1);
pub(super) fn transfer_to_h273(tf: TransferFn) -> i64 {
match tf {
TransferFn::Bt709 => 1,
TransferFn::Bt470Bg => 4,
TransferFn::Linear => 8,
TransferFn::St2084 => 16,
TransferFn::AribStdB67 => 18,
TransferFn::Unspecified => 1,
}
}
pub(super) fn amf_quality_preset_i64(preset: super::tuning::AmfQualityPreset) -> i64 {
use super::tuning::AmfQualityPreset;
match preset {
AmfQualityPreset::HighQuality => 10,
AmfQualityPreset::Quality => 30,
AmfQualityPreset::Balanced => 50,
AmfQualityPreset::Speed => 70,
}
}
pub(super) unsafe fn set_int_property(
obj: *mut c_void,
vt: &AmfComponentVtbl,
name: &str,
value: i64,
) -> Result<()> {
unsafe {
let wname = wide(name);
let rc = (vt.set_property)(obj, wname.as_ptr(), AmfVariant::int64(value));
if rc != AMF_OK {
bail!("AMF SetProperty({}, {}) failed: {rc}", name, value);
}
Ok(())
}
}