Skip to main content

moq_vaapi/
lib.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Implements a lightweight and safe interface over `libva`.
6//!
7//! The starting point to using this crate is to open a [`Display`], from which a [`Context`] and
8//! [`Surface`]s can be allocated and used for doing actual work.
9
10// Most of this crate is derived from discord/cros-libva + discord/cros-codecs
11// (BSD-3-Clause). Don't subject upstream code to this workspace's strict lints;
12// the build script also emits custom `libva_*_or_higher` cfgs.
13#![allow(dead_code, unused_imports, unexpected_cfgs, mismatched_lifetime_syntaxes)]
14#![allow(clippy::all)]
15
16mod bindings;
17pub mod buffer;
18mod config;
19mod context;
20mod display;
21mod generic_value;
22mod image;
23mod picture;
24mod surface;
25mod usage_hint;
26
27// Vendored from discord/cros-codecs (BSD-3-Clause): the backend-agnostic H.264
28// bitstream layer (SPS/PPS/slice synthesis) plus a thin VA-API encode driver.
29pub mod bitstream_utils;
30pub mod codec;
31pub mod decode;
32pub mod encode;
33
34// Written for this crate: DMA-BUF import, the color space an encoder labels its
35// stream with, and the VA-API video post-processing entrypoint, which scales,
36// converts, and re-tiles surfaces on the GPU.
37pub mod color;
38pub mod dmabuf;
39pub mod vpp;
40
41pub use bindings::_VADRMPRIMESurfaceDescriptor__bindgen_ty_1 as VADRMPRIMESurfaceDescriptorObject;
42pub use bindings::_VADRMPRIMESurfaceDescriptor__bindgen_ty_2 as VADRMPRIMESurfaceDescriptorLayer;
43pub use bindings::*;
44pub use buffer::*;
45pub use color::{Color, Matrix};
46pub use config::*;
47pub use context::*;
48pub use display::*;
49pub use generic_value::*;
50pub use image::*;
51pub use picture::*;
52pub use surface::*;
53pub use usage_hint::*;
54
55/// A frame resolution in pixels. (Vendored from discord/cros-codecs, BSD-3-Clause.)
56#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
57pub struct Resolution {
58	pub width: u32,
59	pub height: u32,
60}
61
62impl Resolution {
63	/// Whether `self` can contain `other`.
64	pub fn can_contain(&self, other: Self) -> bool {
65		self.width >= other.width && self.height >= other.height
66	}
67
68	pub fn get_area(&self) -> usize {
69		(self.width as usize) * (self.height as usize)
70	}
71}
72
73impl From<(u32, u32)> for Resolution {
74	fn from(value: (u32, u32)) -> Self {
75		Self {
76			width: value.0,
77			height: value.1,
78		}
79	}
80}
81
82impl From<Resolution> for (u32, u32) {
83	fn from(value: Resolution) -> Self {
84		(value.width, value.height)
85	}
86}
87
88use std::num::NonZeroI32;
89
90/// A `VAStatus` that is guaranteed to not be `VA_STATUS_SUCCESS`.
91#[derive(Debug)]
92pub struct VaError(NonZeroI32);
93
94impl VaError {
95	/// Returns the `VAStatus` of this error.
96	pub fn va_status(&self) -> VAStatus {
97		self.0.get() as VAStatus
98	}
99}
100
101impl std::fmt::Display for VaError {
102	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103		use std::ffi::CStr;
104
105		// Safe because `vaErrorStr` will return a pointer to a statically allocated, null
106		// terminated C string. The pointer is guaranteed to never be null.
107		let err_str = unsafe { CStr::from_ptr(bindings::va().vaErrorStr(self.0.get())) }
108			.to_str()
109			.unwrap();
110		f.write_str(err_str)
111	}
112}
113
114impl std::error::Error for VaError {}
115
116/// Checks a VA return value and returns a `VaError` if it is not `VA_STATUS_SUCCESS`.
117///
118/// This can be used on the return value of any VA function returning `VAStatus` in order to
119/// convert it to a proper Rust `Result`.
120fn va_check(code: VAStatus) -> Result<(), VaError> {
121	match code as u32 {
122		bindings::VA_STATUS_SUCCESS => Ok(()),
123		_ => Err(VaError(unsafe { NonZeroI32::new_unchecked(code) })),
124	}
125}