Skip to main content

zencodec_media/
frame.rs

1//! Decoded frames and owned software planes.
2//!
3//! Shared frame owners and mapping contracts live in [`zencodec::frame`]. The
4//! existing media import paths name those exact types. Software plane storage
5//! stays here because accounted allocations use `zencodec-io`.
6
7use alloc::{boxed::Box, vec::Vec};
8
9pub use zencodec::frame::{
10    ChromaSiting, ColorClaim, Crop, Frame, FrameGeometry, FrameInterpretation, FrameTiming,
11    MapError, MappedPlanes, Picture, PlaneError, PlaneRole, PlaneSamples, PlaneView, Presentation,
12    SampleEncoding, SampleEncodingError, Subsampling,
13};
14
15/// Words of one owned plane.
16#[derive(Clone, Debug)]
17pub enum PlaneData {
18    /// 8-bit words.
19    U8(Vec<u8>),
20    /// 16-bit words.
21    U16(Vec<u16>),
22    /// Shared 8-bit storage admitted before allocation. A frame, plane clone
23    /// or retained view keeps the entire backing allocation charged.
24    AccountedU8(zencodec_io::storage::SharedStorage<u8>),
25    /// Shared 16-bit storage, preserving native word alignment and encoding.
26    AccountedU16(zencodec_io::storage::SharedStorage<u16>),
27}
28
29/// One owned plane.
30#[derive(Clone, Debug)]
31pub struct OwnedPlane {
32    /// The words.
33    pub data: PlaneData,
34    /// Width in samples.
35    pub width: usize,
36    /// Height in rows.
37    pub height: usize,
38    /// Distance between rows, in bytes.
39    pub stride_bytes: usize,
40}
41
42/// Owned planes in their native words: the [`Picture`] of a software
43/// decoder.
44#[derive(Clone, Debug)]
45pub struct OwnedPlanes {
46    planes: Vec<OwnedPlane>,
47    encoding: SampleEncoding,
48}
49
50impl OwnedPlanes {
51    /// Planes sharing one sample encoding.
52    ///
53    /// # Errors
54    ///
55    /// A [`PlaneError`] when a plane's storage does not fit its geometry.
56    pub fn new(planes: Vec<OwnedPlane>, encoding: SampleEncoding) -> Result<Self, PlaneError> {
57        let me = Self { planes, encoding };
58        for i in 0..me.planes.len() {
59            me.view(i)?;
60        }
61        Ok(me)
62    }
63
64    fn view(&self, i: usize) -> Result<PlaneView<'_>, PlaneError> {
65        let p = &self.planes[i];
66        let samples = match &p.data {
67            PlaneData::U8(v) => PlaneSamples::U8(v),
68            PlaneData::U16(v) => PlaneSamples::U16(v),
69            PlaneData::AccountedU8(v) => PlaneSamples::U8(v.as_slice()),
70            PlaneData::AccountedU16(v) => PlaneSamples::U16(v.as_slice()),
71        };
72        PlaneView::new(samples, p.width, p.height, p.stride_bytes, self.encoding)
73    }
74}
75
76struct OwnedMapped<'a>(&'a OwnedPlanes);
77
78impl MappedPlanes for OwnedMapped<'_> {
79    fn plane_count(&self) -> usize {
80        self.0.planes.len()
81    }
82
83    fn plane(&self, index: usize) -> Option<PlaneView<'_>> {
84        if index >= self.0.planes.len() {
85            return None;
86        }
87        self.0.view(index).ok()
88    }
89}
90
91impl Picture for OwnedPlanes {
92    fn map(&self) -> Result<Box<dyn MappedPlanes + '_>, MapError> {
93        Ok(Box::new(OwnedMapped(self)))
94    }
95}