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