libspa/buffer/
meta.rs

1use crate::param::video::VideoFormat;
2use crate::utils::{Point, Rectangle, Region};
3
4use std::fmt::Debug;
5
6pub trait Metadata {
7    const META_TYPE: u32;
8}
9
10bitflags::bitflags! {
11    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
12    pub struct MetaHeaderFlags: u32 {
13        /// Buffer is discontinuous
14        const DISCONT = spa_sys::SPA_META_HEADER_FLAG_DISCONT;
15        /// Buffer data is corrupted
16        const CORRUPTED = spa_sys::SPA_META_HEADER_FLAG_CORRUPTED;
17        /// Buffer contains a codec config marker
18        const MARKER = spa_sys::SPA_META_HEADER_FLAG_MARKER;
19        /// Buffer contains header data
20        const HEADER = spa_sys::SPA_META_HEADER_FLAG_HEADER;
21        /// Buffer represents a gap in the stream
22        const GAP = spa_sys::SPA_META_HEADER_FLAG_GAP;
23        /// Buffer is a delta unit (not self-contained)
24        const DELTA_UNIT = spa_sys::SPA_META_HEADER_FLAG_DELTA_UNIT;
25    }
26}
27
28#[derive(Clone)]
29#[repr(transparent)]
30pub struct MetaHeader(spa_sys::spa_meta_header);
31
32impl MetaHeader {
33    pub fn as_raw(&self) -> &spa_sys::spa_meta_header {
34        &self.0
35    }
36
37    pub fn offset(&self) -> u32 {
38        self.0.offset
39    }
40
41    pub fn flags(&self) -> MetaHeaderFlags {
42        MetaHeaderFlags::from_bits_retain(self.0.flags)
43    }
44
45    pub fn pts(&self) -> i64 {
46        self.0.pts
47    }
48
49    pub fn dts_offset(&self) -> i64 {
50        self.0.dts_offset
51    }
52
53    pub fn seq(&self) -> u64 {
54        self.0.seq
55    }
56}
57
58impl Debug for MetaHeader {
59    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60        f.debug_struct("MetaHeader")
61            .field("flags", &self.flags())
62            .field("offset", &self.offset())
63            .field("pts", &self.pts())
64            .field("dts_offset", &self.dts_offset())
65            .field("seq", &self.seq())
66            .finish()
67    }
68}
69
70impl Metadata for MetaHeader {
71    const META_TYPE: u32 = spa_sys::SPA_META_Header;
72}
73
74#[derive(Clone)]
75#[repr(transparent)]
76pub struct MetaRegion(spa_sys::spa_meta_region);
77
78impl MetaRegion {
79    pub fn as_raw(&self) -> &spa_sys::spa_meta_region {
80        &self.0
81    }
82
83    pub fn region(&self) -> &Region {
84        &self.0.region
85    }
86
87    pub fn position(&self) -> Point {
88        self.0.region.position
89    }
90
91    pub fn size(&self) -> Rectangle {
92        self.0.region.size
93    }
94
95    pub fn is_valid(&self) -> bool {
96        unsafe { spa_sys::spa_meta_region_is_valid(self.as_raw()) }
97    }
98}
99
100impl Debug for MetaRegion {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        f.debug_struct("MetaRegion")
103            .field("region", &self.region())
104            .finish()
105    }
106}
107
108#[derive(Clone, Debug)]
109#[repr(transparent)]
110pub struct MetaVideoCrop(MetaRegion);
111
112impl MetaVideoCrop {
113    pub fn meta_region(&self) -> &MetaRegion {
114        &self.0
115    }
116}
117
118impl Metadata for MetaVideoCrop {
119    const META_TYPE: u32 = spa_sys::SPA_META_VideoCrop;
120}
121
122#[repr(transparent)]
123pub struct MetaVideoDamage(spa_sys::spa_meta);
124
125impl MetaVideoDamage {
126    pub fn as_raw(&self) -> &spa_sys::spa_meta {
127        &self.0
128    }
129
130    pub fn iter(&self) -> VideoDamageIter<'_> {
131        VideoDamageIter::new(self)
132    }
133}
134
135pub struct VideoDamageIter<'a> {
136    video_damage: &'a MetaVideoDamage,
137    pos: *const spa_sys::spa_meta_region,
138}
139
140impl<'a> VideoDamageIter<'a> {
141    fn new(video_damage: &'a MetaVideoDamage) -> Self {
142        Self {
143            video_damage,
144            pos: unsafe { spa_sys::spa_meta_first(video_damage.as_raw()) }.cast(),
145        }
146    }
147}
148
149impl<'a> Iterator for VideoDamageIter<'a> {
150    type Item = &'a MetaRegion;
151
152    fn next(&mut self) -> Option<Self::Item> {
153        if !unsafe { spa_sys::spa_meta_check(self.pos.cast(), self.video_damage.as_raw()) } {
154            return None;
155        }
156
157        let region = unsafe { self.pos.cast::<MetaRegion>().as_ref()? };
158        if !region.is_valid() {
159            return None;
160        }
161
162        self.pos = unsafe { self.pos.add(1) };
163
164        Some(region)
165    }
166}
167
168impl Metadata for MetaVideoDamage {
169    const META_TYPE: u32 = spa_sys::SPA_META_VideoDamage;
170}
171
172#[repr(transparent)]
173pub struct MetaBitmap(spa_sys::spa_meta_bitmap);
174
175impl MetaBitmap {
176    pub fn as_raw(&self) -> &spa_sys::spa_meta_bitmap {
177        &self.0
178    }
179
180    pub fn format(&self) -> VideoFormat {
181        VideoFormat(self.0.format)
182    }
183
184    pub fn size(&self) -> Rectangle {
185        self.0.size
186    }
187
188    pub fn stride(&self) -> i32 {
189        self.0.stride
190    }
191
192    pub fn offset(&self) -> u32 {
193        self.0.offset
194    }
195
196    pub fn is_valid(&self) -> bool {
197        unsafe { spa_sys::spa_meta_bitmap_is_valid(self.as_raw()) }
198    }
199
200    pub fn bitmap_data(&self) -> Option<&[u8]> {
201        if !self.is_valid()
202            || (self.0.offset as usize) < std::mem::size_of::<spa_sys::spa_meta_bitmap>()
203        {
204            return None;
205        }
206
207        let height = self.0.size.height as usize;
208        let stride = self.0.stride.unsigned_abs() as usize;
209        let data_size = height * stride;
210
211        unsafe {
212            let base_ptr = self as *const _ as *const u8;
213            let data_ptr = base_ptr.add(self.0.offset as usize);
214            Some(std::slice::from_raw_parts(data_ptr, data_size))
215        }
216    }
217}
218
219impl Debug for MetaBitmap {
220    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221        f.debug_struct("MetaBitmap")
222            .field("format", &self.format())
223            .field("size", &self.size())
224            .field("stride", &self.stride())
225            .field("offset", &self.offset())
226            .finish()
227    }
228}
229
230impl Metadata for MetaBitmap {
231    const META_TYPE: u32 = spa_sys::SPA_META_Bitmap;
232}
233
234#[repr(transparent)]
235pub struct MetaCursor(spa_sys::spa_meta_cursor);
236
237impl MetaCursor {
238    pub fn as_raw(&self) -> &spa_sys::spa_meta_cursor {
239        &self.0
240    }
241
242    pub fn id(&self) -> u32 {
243        self.0.id
244    }
245
246    pub fn flags(&self) -> u32 {
247        self.0.flags
248    }
249
250    pub fn position(&self) -> Point {
251        self.0.position
252    }
253
254    /// This field has no meaning  when there is no valid bitmap.
255    pub fn hotspot(&self) -> Point {
256        self.0.hotspot
257    }
258
259    pub fn bitmap_offset(&self) -> u32 {
260        self.0.bitmap_offset
261    }
262
263    pub fn is_valid(&self) -> bool {
264        unsafe { spa_sys::spa_meta_cursor_is_valid(self.as_raw()) }
265    }
266
267    pub fn bitmap(&self) -> Option<&MetaBitmap> {
268        if !self.is_valid()
269            || (self.0.bitmap_offset as usize) < std::mem::size_of::<spa_sys::spa_meta_cursor>()
270        {
271            return None;
272        }
273
274        unsafe {
275            let base_ptr = self as *const _ as *const u8;
276            let bitmap_ptr = base_ptr.add(self.0.bitmap_offset as usize);
277            let bitmap_ptr = bitmap_ptr as *const MetaBitmap;
278            bitmap_ptr.as_ref()
279        }
280    }
281}
282
283impl Debug for MetaCursor {
284    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285        f.debug_struct("MetaCursor")
286            .field("id", &self.id())
287            .field("flags", &self.flags())
288            .field("position", &self.position())
289            .field("hotspot", &self.hotspot())
290            .field("bitmap_offset", &self.bitmap_offset())
291            .finish()
292    }
293}
294
295impl Metadata for MetaCursor {
296    const META_TYPE: u32 = spa_sys::SPA_META_Cursor;
297}
298
299#[repr(transparent)]
300pub struct MetaControl(spa_sys::spa_meta_control);
301
302impl MetaControl {
303    pub fn as_raw(&self) -> &spa_sys::spa_meta_control {
304        &self.0
305    }
306
307    pub fn sequence(&self) -> &spa_sys::spa_pod_sequence {
308        &self.0.sequence
309    }
310}
311
312impl Metadata for MetaControl {
313    const META_TYPE: u32 = spa_sys::SPA_META_Control;
314}
315
316#[cfg(feature = "v0_3_21")]
317#[derive(Clone)]
318#[repr(transparent)]
319pub struct MetaBusy(spa_sys::spa_meta_busy);
320
321#[cfg(feature = "v0_3_21")]
322impl MetaBusy {
323    pub fn as_raw(&self) -> &spa_sys::spa_meta_busy {
324        &self.0
325    }
326
327    pub fn flags(&self) -> u32 {
328        self.0.flags
329    }
330
331    pub fn count(&self) -> u32 {
332        self.0.count
333    }
334}
335
336#[cfg(feature = "v0_3_21")]
337impl Debug for MetaBusy {
338    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
339        f.debug_struct("MetaBusy")
340            .field("flags", &self.flags())
341            .field("count", &self.count())
342            .finish()
343    }
344}
345
346#[cfg(feature = "v0_3_21")]
347impl Metadata for MetaBusy {
348    const META_TYPE: u32 = spa_sys::SPA_META_Busy;
349}
350
351#[cfg(feature = "v0_3_62")]
352#[derive(Copy, Clone, PartialEq, Eq)]
353#[repr(transparent)]
354pub struct MetaVideoTransformValue(spa_sys::spa_meta_videotransform_value);
355
356#[cfg(feature = "v0_3_62")]
357impl MetaVideoTransformValue {
358    pub const NONE: Self = Self(spa_sys::SPA_META_TRANSFORMATION_None);
359    pub const ROTATED90: Self = Self(spa_sys::SPA_META_TRANSFORMATION_90);
360    pub const ROTATED180: Self = Self(spa_sys::SPA_META_TRANSFORMATION_180);
361    pub const ROTATED270: Self = Self(spa_sys::SPA_META_TRANSFORMATION_270);
362    pub const FLIPPED: Self = Self(spa_sys::SPA_META_TRANSFORMATION_Flipped);
363    pub const FLIPPED90: Self = Self(spa_sys::SPA_META_TRANSFORMATION_Flipped90);
364    pub const FLIPPED180: Self = Self(spa_sys::SPA_META_TRANSFORMATION_Flipped180);
365    pub const FLIPPED270: Self = Self(spa_sys::SPA_META_TRANSFORMATION_Flipped270);
366
367    pub fn from_raw(raw: spa_sys::spa_meta_videotransform_value) -> Self {
368        Self(raw)
369    }
370
371    pub fn as_raw(&self) -> spa_sys::spa_meta_videotransform_value {
372        self.0
373    }
374}
375
376#[cfg(feature = "v0_3_62")]
377impl Debug for MetaVideoTransformValue {
378    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379        write!(
380            f,
381            "MetaVideoTransformValue::{}",
382            match *self {
383                Self::NONE => "None",
384                Self::ROTATED90 => "ROTATED90",
385                Self::ROTATED180 => "ROTATED180",
386                Self::ROTATED270 => "ROTATED270",
387                Self::FLIPPED => "FLIPPED",
388                Self::FLIPPED90 => "FLIPPED90",
389                Self::FLIPPED180 => "FLIPPED180",
390                Self::FLIPPED270 => "FLIPPED270",
391                _ => "Unknown",
392            }
393        )
394    }
395}
396
397#[cfg(feature = "v0_3_62")]
398#[repr(transparent)]
399pub struct MetaVideoTransform(spa_sys::spa_meta_videotransform);
400
401#[cfg(feature = "v0_3_62")]
402impl MetaVideoTransform {
403    pub fn as_raw(&self) -> &spa_sys::spa_meta_videotransform {
404        &self.0
405    }
406
407    pub fn transform(&self) -> MetaVideoTransformValue {
408        MetaVideoTransformValue::from_raw(self.0.transform)
409    }
410}
411
412#[cfg(feature = "v0_3_62")]
413impl Debug for MetaVideoTransform {
414    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
415        f.debug_struct("MetaVideoTransform")
416            .field("transform", &self.transform())
417            .finish()
418    }
419}
420
421#[cfg(feature = "v0_3_62")]
422impl Metadata for MetaVideoTransform {
423    const META_TYPE: u32 = spa_sys::SPA_META_VideoTransform;
424}
425
426#[cfg(feature = "v1_2_0")]
427bitflags::bitflags! {
428    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
429    pub struct SyncTimelineFlags: u32 {
430        /// This flag is set by the producer and cleared by the consumer
431        /// when it promises to signal the release point
432        #[cfg(feature = "v1_6_0")]
433        const UNSCHEDULED_RELEASE = spa_sys::SPA_META_SYNC_TIMELINE_UNSCHEDULED_RELEASE;
434
435    }
436}
437
438#[cfg(feature = "v1_2_0")]
439#[repr(transparent)]
440pub struct MetaSyncTimeline(spa_sys::spa_meta_sync_timeline);
441
442#[cfg(feature = "v1_2_0")]
443impl MetaSyncTimeline {
444    pub fn as_raw(&self) -> &spa_sys::spa_meta_sync_timeline {
445        &self.0
446    }
447
448    pub fn flags(&self) -> SyncTimelineFlags {
449        SyncTimelineFlags::from_bits_retain(self.0.flags)
450    }
451
452    pub fn padding(&self) -> u32 {
453        self.0.padding
454    }
455
456    /// The timeline acquire point - when the data can be accessed
457    pub fn acquire_point(&self) -> u64 {
458        self.0.acquire_point
459    }
460
461    /// The timeline release point - should be signaled when data is no longer accessed
462    pub fn release_point(&self) -> u64 {
463        self.0.release_point
464    }
465}
466
467#[cfg(feature = "v1_2_0")]
468impl Debug for MetaSyncTimeline {
469    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470        f.debug_struct("MetaSyncTimeline")
471            .field("flags", &self.flags())
472            .field("padding", &self.padding())
473            .field("acquire_point", &self.acquire_point())
474            .field("release_point", &self.release_point())
475            .finish()
476    }
477}
478
479#[cfg(feature = "v1_2_0")]
480impl Metadata for MetaSyncTimeline {
481    const META_TYPE: u32 = spa_sys::SPA_META_SyncTimeline;
482}