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 const DISCONT = spa_sys::SPA_META_HEADER_FLAG_DISCONT;
15 const CORRUPTED = spa_sys::SPA_META_HEADER_FLAG_CORRUPTED;
17 const MARKER = spa_sys::SPA_META_HEADER_FLAG_MARKER;
19 const HEADER = spa_sys::SPA_META_HEADER_FLAG_HEADER;
21 const GAP = spa_sys::SPA_META_HEADER_FLAG_GAP;
23 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 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 #[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 pub fn acquire_point(&self) -> u64 {
458 self.0.acquire_point
459 }
460
461 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}