pub struct Decoder { /* private fields */ }Expand description
A VA-API H.264 decoder. Built once, fed Annex-B access units, emits NV12.
§Examples
use moq_vaapi::decode::{Config, Decoder};
let mut decoder = Decoder::new(Config::new())?;
let mut pictures = Vec::new();
for (index, access_unit) in access_units.iter().enumerate() {
pictures.extend(decoder.decode(access_unit, index as u64)?);
}
// Output trails input, so the tail of the stream only arrives here.
pictures.extend(decoder.flush()?);Implementations§
Source§impl Decoder
impl Decoder
Sourcepub fn new(config: Config) -> Result<Self>
pub fn new(config: Config) -> Result<Self>
Opens Config::device, or the first render node that decodes H.264,
and checks that the driver exposes an H.264 decode entrypoint.
The VA config, context, and surface pool are built later, from the first SPS, since their profile and size come from the stream. This still fails early enough for a caller to fall back to another decoder when libva is missing, the node cannot be opened, or the driver decodes no H.264. A named node is never swapped for another.
Sourcepub fn decode(
&mut self,
access_unit: &[u8],
timestamp: u64,
) -> Result<Vec<Frame>>
pub fn decode( &mut self, access_unit: &[u8], timestamp: u64, ) -> Result<Vec<Frame>>
Decodes one Annex-B access unit, returning the pictures that came due, in output order.
timestamp is opaque and travels with the picture coded in this access
unit, so it survives DPB reordering. Parameter sets are read from the
stream, so an access unit carrying only an SPS and a PPS decodes to no
frames.
Sourcepub fn decode_exported(
&mut self,
access_unit: &[u8],
timestamp: u64,
) -> Result<Vec<ExportedFrame>>
pub fn decode_exported( &mut self, access_unit: &[u8], timestamp: u64, ) -> Result<Vec<ExportedFrame>>
Decodes one Annex-B access unit, leaving the pictures that came due on the GPU.
The same decode as Decoder::decode, differing only in what the caller
gets back: a DRM PRIME descriptor for each picture’s surface instead of a
copy of its pixels. For a consumer that draws on the GPU that is the
whole picture never touching system memory.
An exported surface stays out of the recycling pool until the
ExportedFrame drops, since the next picture would otherwise be decoded
over pixels the consumer still holds a descriptor for. A consumer that
lets each picture go once it has drawn it therefore costs no allocation
per picture; one that holds on to pictures costs one surface per picture
held.
A consumer that turns out to want bytes after all is not stuck: the
surface travels with the descriptor, and ExportedFrame::download reads
it back.
Sourcepub fn flush(&mut self) -> Result<Vec<Frame>>
pub fn flush(&mut self) -> Result<Vec<Frame>>
Returns every picture still held in the DPB, in output order.
C.4.5.3 bumps the DPB only when a new picture needs the slot, so a stream that simply stops leaves its tail sitting there. This releases that tail and empties the DPB, so a second call returns nothing.
The parsed parameter sets survive, and nothing here waits for an IDR: a stream picked up part way through decodes against an empty DPB, which gives distorted pictures until its next IDR rather than an error.
Sourcepub fn flush_exported(&mut self) -> Result<Vec<ExportedFrame>>
pub fn flush_exported(&mut self) -> Result<Vec<ExportedFrame>>
Decoder::flush for a caller taking its pictures on the GPU.