use libva::{Display, VAEntrypoint};
use std::rc::Rc;
use vacc_core::codec::VideoCodec as CoreVideoCodec;
use super::{Error, Result};
pub struct VaapiEncoderDevice {
display: Rc<Display>,
}
impl VaapiEncoderDevice {
pub fn new() -> Result<Self> {
let display = match std::env::var("NVD_GPU")
.ok()
.and_then(|v| v.parse::<u32>().ok())
{
Some(idx) => {
let path = format!("/dev/dri/renderD{}", 128 + idx);
Display::open_drm_display(&path).map_err(|e| {
Error::VaApi(format!("Failed to open VA display on {}: {}", path, e))
})?
}
None => Display::open()
.ok_or_else(|| Error::VaApi("No VA display available".to_string()))?,
};
Ok(Self { display })
}
pub fn display(&self) -> &Rc<Display> {
&self.display
}
pub fn supports_h264_encode(&self) -> bool {
self.supports_profile(libva::VAProfile::VAProfileH264Main)
}
pub fn supports_profile(&self, profile: libva::VAProfile::Type) -> bool {
match self.display.query_config_entrypoints(profile) {
Ok(entrypoints) => entrypoints.contains(&VAEntrypoint::VAEntrypointEncSlice),
Err(_) => false,
}
}
pub fn supported_codecs(&self) -> Vec<CoreVideoCodec> {
let mut codecs = Vec::new();
if self.supports_h264_encode() {
codecs.push(CoreVideoCodec::EncodeH264);
}
codecs
}
pub fn backend_name(&self) -> &str {
"vaapi"
}
}