1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, ptr};
4
5use glib::translate::{from_glib, from_glib_none, FromGlib, IntoGlib, IntoGlibPtr, ToGlibPtr};
6use gst::prelude::*;
7
8#[repr(transparent)]
9#[doc(alias = "GstVideoMeta")]
10pub struct VideoMeta(ffi::GstVideoMeta);
11
12unsafe impl Send for VideoMeta {}
13unsafe impl Sync for VideoMeta {}
14
15impl VideoMeta {
16 #[doc(alias = "gst_buffer_add_video_meta")]
17 pub fn add(
18 buffer: &mut gst::BufferRef,
19 video_frame_flags: crate::VideoFrameFlags,
20 format: crate::VideoFormat,
21 width: u32,
22 height: u32,
23 ) -> Result<gst::MetaRefMut<Self, gst::meta::Standalone>, glib::BoolError> {
24 skip_assert_initialized!();
25
26 if format == crate::VideoFormat::Unknown || format == crate::VideoFormat::Encoded {
27 return Err(glib::bool_error!("Unsupported video format {}", format));
28 }
29
30 let info = crate::VideoInfo::builder(format, width, height).build()?;
31
32 if !info.is_valid() {
33 return Err(glib::bool_error!("Invalid video info"));
34 }
35
36 if buffer.size() < info.size() {
37 return Err(glib::bool_error!(
38 "Buffer smaller than required frame size ({} < {})",
39 buffer.size(),
40 info.size()
41 ));
42 }
43
44 unsafe {
45 let meta = ffi::gst_buffer_add_video_meta(
46 buffer.as_mut_ptr(),
47 video_frame_flags.into_glib(),
48 format.into_glib(),
49 width,
50 height,
51 );
52
53 if meta.is_null() {
54 return Err(glib::bool_error!("Failed to add video meta"));
55 }
56
57 Ok(Self::from_mut_ptr(buffer, meta))
58 }
59 }
60
61 pub fn add_full<'a>(
62 buffer: &'a mut gst::BufferRef,
63 video_frame_flags: crate::VideoFrameFlags,
64 format: crate::VideoFormat,
65 width: u32,
66 height: u32,
67 offset: &[usize],
68 stride: &[i32],
69 ) -> Result<gst::MetaRefMut<'a, Self, gst::meta::Standalone>, glib::BoolError> {
70 skip_assert_initialized!();
71
72 if format == crate::VideoFormat::Unknown || format == crate::VideoFormat::Encoded {
73 return Err(glib::bool_error!("Unsupported video format {}", format));
74 }
75
76 let n_planes = offset.len() as u32;
77 let info = crate::VideoInfo::builder(format, width, height)
78 .offset(offset)
79 .stride(stride)
80 .build()?;
81
82 if !info.is_valid() {
83 return Err(glib::bool_error!("Invalid video info"));
84 }
85
86 if buffer.size() < info.size() {
87 return Err(glib::bool_error!(
88 "Buffer smaller than required frame size ({} < {})",
89 buffer.size(),
90 info.size()
91 ));
92 }
93
94 unsafe {
95 let meta = ffi::gst_buffer_add_video_meta_full(
96 buffer.as_mut_ptr(),
97 video_frame_flags.into_glib(),
98 format.into_glib(),
99 width,
100 height,
101 n_planes,
102 offset.as_ptr() as *mut _,
103 stride.as_ptr() as *mut _,
104 );
105
106 if meta.is_null() {
107 return Err(glib::bool_error!("Failed to add video meta"));
108 }
109
110 Ok(Self::from_mut_ptr(buffer, meta))
111 }
112 }
113
114 #[doc(alias = "get_flags")]
115 #[inline]
116 pub fn video_frame_flags(&self) -> crate::VideoFrameFlags {
117 unsafe { from_glib(self.0.flags) }
118 }
119
120 #[doc(alias = "get_format")]
121 #[inline]
122 pub fn format(&self) -> crate::VideoFormat {
123 unsafe { from_glib(self.0.format) }
124 }
125
126 #[doc(alias = "get_id")]
127 #[inline]
128 pub fn id(&self) -> i32 {
129 self.0.id
130 }
131
132 #[doc(alias = "get_width")]
133 #[inline]
134 pub fn width(&self) -> u32 {
135 self.0.width
136 }
137
138 #[doc(alias = "get_height")]
139 #[inline]
140 pub fn height(&self) -> u32 {
141 self.0.height
142 }
143
144 #[doc(alias = "get_n_planes")]
145 #[inline]
146 pub fn n_planes(&self) -> u32 {
147 self.0.n_planes
148 }
149
150 #[doc(alias = "get_offset")]
151 #[inline]
152 pub fn offset(&self) -> &[usize] {
153 &self.0.offset[0..(self.0.n_planes as usize)]
154 }
155
156 #[doc(alias = "get_stride")]
157 #[inline]
158 pub fn stride(&self) -> &[i32] {
159 &self.0.stride[0..(self.0.n_planes as usize)]
160 }
161
162 #[cfg(feature = "v1_18")]
163 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
164 #[doc(alias = "get_alignment")]
165 #[inline]
166 pub fn alignment(&self) -> crate::VideoAlignment {
167 crate::VideoAlignment::new(
168 self.0.alignment.padding_top,
169 self.0.alignment.padding_bottom,
170 self.0.alignment.padding_left,
171 self.0.alignment.padding_right,
172 &self.0.alignment.stride_align,
173 )
174 }
175
176 #[cfg(feature = "v1_18")]
177 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
178 #[doc(alias = "get_plane_size")]
179 #[doc(alias = "gst_video_meta_get_plane_size")]
180 pub fn plane_size(&self) -> Result<[usize; crate::VIDEO_MAX_PLANES], glib::BoolError> {
181 let mut plane_size = [0; crate::VIDEO_MAX_PLANES];
182
183 unsafe {
184 glib::result_from_gboolean!(
185 ffi::gst_video_meta_get_plane_size(
186 &self.0 as *const _ as usize as *mut _,
187 &mut plane_size,
188 ),
189 "Failed to get plane size"
190 )?;
191 }
192
193 Ok(plane_size)
194 }
195
196 #[cfg(feature = "v1_18")]
197 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
198 #[doc(alias = "get_plane_height")]
199 #[doc(alias = "gst_video_meta_get_plane_height")]
200 pub fn plane_height(&self) -> Result<[u32; crate::VIDEO_MAX_PLANES], glib::BoolError> {
201 let mut plane_height = [0; crate::VIDEO_MAX_PLANES];
202
203 unsafe {
204 glib::result_from_gboolean!(
205 ffi::gst_video_meta_get_plane_height(
206 &self.0 as *const _ as usize as *mut _,
207 &mut plane_height,
208 ),
209 "Failed to get plane height"
210 )?;
211 }
212
213 Ok(plane_height)
214 }
215
216 #[cfg(feature = "v1_18")]
217 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
218 #[doc(alias = "gst_video_meta_set_alignment")]
219 pub fn set_alignment(
220 &mut self,
221 alignment: &crate::VideoAlignment,
222 ) -> Result<(), glib::BoolError> {
223 unsafe {
224 glib::result_from_gboolean!(
225 ffi::gst_video_meta_set_alignment(&mut self.0, alignment.0),
226 "Failed to set alignment on VideoMeta"
227 )
228 }
229 }
230}
231
232unsafe impl MetaAPI for VideoMeta {
233 type GstType = ffi::GstVideoMeta;
234
235 #[doc(alias = "gst_video_meta_api_get_type")]
236 #[inline]
237 fn meta_api() -> glib::Type {
238 unsafe { from_glib(val:ffi::gst_video_meta_api_get_type()) }
239 }
240}
241
242impl fmt::Debug for VideoMeta {
243 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244 f&mut DebugStruct<'_, '_>.debug_struct("VideoMeta")
245 .field("id", &self.id())
246 .field("video_frame_flags", &self.video_frame_flags())
247 .field("format", &self.format())
248 .field("width", &self.width())
249 .field("height", &self.height())
250 .field("n_planes", &self.n_planes())
251 .field("offset", &self.offset())
252 .field(name:"stride", &self.stride())
253 .finish()
254 }
255}
256
257#[repr(transparent)]
258#[doc(alias = "GstVideoCropMeta")]
259pub struct VideoCropMeta(ffi::GstVideoCropMeta);
260
261unsafe impl Send for VideoCropMeta {}
262unsafe impl Sync for VideoCropMeta {}
263
264impl VideoCropMeta {
265 #[doc(alias = "gst_buffer_add_meta")]
266 pub fn add(
267 buffer: &mut gst::BufferRef,
268 rect: (u32, u32, u32, u32),
269 ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
270 skip_assert_initialized!();
271 unsafe {
272 let meta = gst::ffi::gst_buffer_add_meta(
273 buffer.as_mut_ptr(),
274 ffi::gst_video_crop_meta_get_info(),
275 ptr::null_mut(),
276 ) as *mut ffi::GstVideoCropMeta;
277
278 {
279 let meta = &mut *meta;
280 meta.x = rect.0;
281 meta.y = rect.1;
282 meta.width = rect.2;
283 meta.height = rect.3;
284 }
285
286 Self::from_mut_ptr(buffer, meta)
287 }
288 }
289
290 #[doc(alias = "get_rect")]
291 #[inline]
292 pub fn rect(&self) -> (u32, u32, u32, u32) {
293 (self.0.x, self.0.y, self.0.width, self.0.height)
294 }
295
296 #[inline]
297 pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) {
298 self.0.x = rect.0;
299 self.0.y = rect.1;
300 self.0.width = rect.2;
301 self.0.height = rect.3;
302 }
303}
304
305unsafe impl MetaAPI for VideoCropMeta {
306 type GstType = ffi::GstVideoCropMeta;
307
308 #[doc(alias = "gst_video_crop_meta_api_get_type")]
309 #[inline]
310 fn meta_api() -> glib::Type {
311 unsafe { from_glib(val:ffi::gst_video_crop_meta_api_get_type()) }
312 }
313}
314
315impl fmt::Debug for VideoCropMeta {
316 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317 f&mut DebugStruct<'_, '_>.debug_struct("VideoCropMeta")
318 .field(name:"rect", &self.rect())
319 .finish()
320 }
321}
322
323#[repr(transparent)]
324#[doc(alias = "GstVideoRegionOfInterestMeta")]
325pub struct VideoRegionOfInterestMeta(ffi::GstVideoRegionOfInterestMeta);
326
327unsafe impl Send for VideoRegionOfInterestMeta {}
328unsafe impl Sync for VideoRegionOfInterestMeta {}
329
330impl VideoRegionOfInterestMeta {
331 #[doc(alias = "gst_buffer_add_video_region_of_interest_meta")]
332 pub fn add<'a>(
333 buffer: &'a mut gst::BufferRef,
334 roi_type: &str,
335 rect: (u32, u32, u32, u32),
336 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
337 skip_assert_initialized!();
338 unsafe {
339 let meta = ffi::gst_buffer_add_video_region_of_interest_meta(
340 buffer.as_mut_ptr(),
341 roi_type.to_glib_none().0,
342 rect.0,
343 rect.1,
344 rect.2,
345 rect.3,
346 );
347
348 Self::from_mut_ptr(buffer, meta)
349 }
350 }
351
352 #[doc(alias = "get_rect")]
353 #[inline]
354 pub fn rect(&self) -> (u32, u32, u32, u32) {
355 (self.0.x, self.0.y, self.0.w, self.0.h)
356 }
357
358 #[doc(alias = "get_id")]
359 #[inline]
360 pub fn id(&self) -> i32 {
361 self.0.id
362 }
363
364 #[doc(alias = "get_parent_id")]
365 #[inline]
366 pub fn parent_id(&self) -> i32 {
367 self.0.parent_id
368 }
369
370 #[doc(alias = "get_roi_type")]
371 #[inline]
372 pub fn roi_type<'a>(&self) -> &'a str {
373 unsafe { glib::Quark::from_glib(self.0.roi_type).as_str() }
374 }
375
376 #[doc(alias = "get_params")]
377 pub fn params(&self) -> ParamsIter {
378 ParamsIter {
379 _meta: self,
380 list: ptr::NonNull::new(self.0.params),
381 }
382 }
383
384 #[doc(alias = "get_param")]
385 #[inline]
386 pub fn param<'b>(&'b self, name: &str) -> Option<&'b gst::StructureRef> {
387 self.params().find(|s| s.name() == name)
388 }
389
390 #[inline]
391 pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) {
392 self.0.x = rect.0;
393 self.0.y = rect.1;
394 self.0.w = rect.2;
395 self.0.h = rect.3;
396 }
397
398 #[inline]
399 pub fn set_id(&mut self, id: i32) {
400 self.0.id = id
401 }
402
403 #[inline]
404 pub fn set_parent_id(&mut self, id: i32) {
405 self.0.parent_id = id
406 }
407
408 #[doc(alias = "gst_video_region_of_interest_meta_add_param")]
409 pub fn add_param(&mut self, s: gst::Structure) {
410 unsafe {
411 ffi::gst_video_region_of_interest_meta_add_param(&mut self.0, s.into_glib_ptr());
412 }
413 }
414}
415
416pub struct ParamsIter<'a> {
417 _meta: &'a VideoRegionOfInterestMeta,
418 list: Option<ptr::NonNull<glib::ffi::GList>>,
419}
420
421impl<'a> Iterator for ParamsIter<'a> {
422 type Item = &'a gst::StructureRef;
423
424 fn next(&mut self) -> Option<&'a gst::StructureRef> {
425 match self.list {
426 None => None,
427 Some(list: NonNull) => unsafe {
428 self.list = ptr::NonNull::new(ptr:list.as_ref().next);
429 let data: *mut c_void = list.as_ref().data;
430
431 let s: &StructureRef = gst::StructureRef::from_glib_borrow(ptr:data as *const gst::ffi::GstStructure);
432
433 Some(s)
434 },
435 }
436 }
437}
438
439impl<'a> std::iter::FusedIterator for ParamsIter<'a> {}
440
441unsafe impl MetaAPI for VideoRegionOfInterestMeta {
442 type GstType = ffi::GstVideoRegionOfInterestMeta;
443
444 #[doc(alias = "gst_video_region_of_interest_meta_api_get_type")]
445 #[inline]
446 fn meta_api() -> glib::Type {
447 unsafe { from_glib(val:ffi::gst_video_region_of_interest_meta_api_get_type()) }
448 }
449}
450
451impl fmt::Debug for VideoRegionOfInterestMeta {
452 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
453 f&mut DebugStruct<'_, '_>.debug_struct("VideoRegionOfInterestMeta")
454 .field("roi_type", &self.roi_type())
455 .field("rect", &self.rect())
456 .field("id", &self.id())
457 .field("parent_id", &self.parent_id())
458 .field(name:"params", &self.params().collect::<Vec<_>>())
459 .finish()
460 }
461}
462
463#[repr(transparent)]
464#[doc(alias = "GstVideoAffineTransformationMeta")]
465pub struct VideoAffineTransformationMeta(ffi::GstVideoAffineTransformationMeta);
466
467unsafe impl Send for VideoAffineTransformationMeta {}
468unsafe impl Sync for VideoAffineTransformationMeta {}
469
470impl VideoAffineTransformationMeta {
471 #[doc(alias = "gst_buffer_add_meta")]
472 pub fn add<'a>(
473 buffer: &'a mut gst::BufferRef,
474 matrix: Option<&[[f32; 4]; 4]>,
475 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
476 skip_assert_initialized!();
477 unsafe {
478 let meta = gst::ffi::gst_buffer_add_meta(
479 buffer.as_mut_ptr(),
480 ffi::gst_video_affine_transformation_meta_get_info(),
481 ptr::null_mut(),
482 ) as *mut ffi::GstVideoAffineTransformationMeta;
483
484 if let Some(matrix) = matrix {
485 let meta = &mut *meta;
486 for (i, o) in Iterator::zip(matrix.iter().flatten(), meta.matrix.iter_mut()) {
487 *o = *i;
488 }
489 }
490
491 Self::from_mut_ptr(buffer, meta)
492 }
493 }
494
495 #[doc(alias = "get_matrix")]
496 #[inline]
497 pub fn matrix(&self) -> &[[f32; 4]; 4] {
498 unsafe { &*(&self.0.matrix as *const [f32; 16] as *const [[f32; 4]; 4]) }
499 }
500
501 #[inline]
502 pub fn set_matrix(&mut self, matrix: &[[f32; 4]; 4]) {
503 for (i, o) in Iterator::zip(matrix.iter().flatten(), self.0.matrix.iter_mut()) {
504 *o = *i;
505 }
506 }
507
508 #[doc(alias = "gst_video_affine_transformation_meta_apply_matrix")]
509 pub fn apply_matrix(&mut self, matrix: &[[f32; 4]; 4]) {
510 unsafe {
511 ffi::gst_video_affine_transformation_meta_apply_matrix(
512 &mut self.0,
513 matrix as *const [[f32; 4]; 4] as *const [f32; 16],
514 );
515 }
516 }
517}
518
519unsafe impl MetaAPI for VideoAffineTransformationMeta {
520 type GstType = ffi::GstVideoAffineTransformationMeta;
521
522 #[doc(alias = "gst_video_affine_transformation_meta_api_get_type")]
523 #[inline]
524 fn meta_api() -> glib::Type {
525 unsafe { from_glib(val:ffi::gst_video_affine_transformation_meta_api_get_type()) }
526 }
527}
528
529impl fmt::Debug for VideoAffineTransformationMeta {
530 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
531 f&mut DebugStruct<'_, '_>.debug_struct("VideoAffineTransformationMeta")
532 .field(name:"matrix", &self.matrix())
533 .finish()
534 }
535}
536
537#[repr(transparent)]
538#[doc(alias = "GstVideoOverlayCompositionMeta")]
539pub struct VideoOverlayCompositionMeta(ffi::GstVideoOverlayCompositionMeta);
540
541unsafe impl Send for VideoOverlayCompositionMeta {}
542unsafe impl Sync for VideoOverlayCompositionMeta {}
543
544impl VideoOverlayCompositionMeta {
545 #[doc(alias = "gst_buffer_add_video_overlay_composition_meta")]
546 pub fn add<'a>(
547 buffer: &'a mut gst::BufferRef,
548 overlay: &crate::VideoOverlayComposition,
549 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
550 skip_assert_initialized!();
551 unsafe {
552 let meta = ffi::gst_buffer_add_video_overlay_composition_meta(
553 buffer.as_mut_ptr(),
554 overlay.as_mut_ptr(),
555 );
556
557 Self::from_mut_ptr(buffer, meta)
558 }
559 }
560
561 #[doc(alias = "get_overlay")]
562 #[inline]
563 pub fn overlay(&self) -> &crate::VideoOverlayCompositionRef {
564 unsafe { crate::VideoOverlayCompositionRef::from_ptr(self.0.overlay) }
565 }
566
567 #[doc(alias = "get_overlay_owned")]
568 #[inline]
569 pub fn overlay_owned(&self) -> crate::VideoOverlayComposition {
570 unsafe { from_glib_none(self.overlay().as_ptr()) }
571 }
572
573 #[inline]
574 pub fn set_overlay(&mut self, overlay: &crate::VideoOverlayComposition) {
575 #![allow(clippy::cast_ptr_alignment)]
576 unsafe {
577 gst::ffi::gst_mini_object_unref(self.0.overlay as *mut _);
578 self.0.overlay =
579 gst::ffi::gst_mini_object_ref(overlay.as_mut_ptr() as *mut _) as *mut _;
580 }
581 }
582}
583
584unsafe impl MetaAPI for VideoOverlayCompositionMeta {
585 type GstType = ffi::GstVideoOverlayCompositionMeta;
586
587 #[doc(alias = "gst_video_overlay_composition_meta_api_get_type")]
588 #[inline]
589 fn meta_api() -> glib::Type {
590 unsafe { from_glib(val:ffi::gst_video_overlay_composition_meta_api_get_type()) }
591 }
592}
593
594impl fmt::Debug for VideoOverlayCompositionMeta {
595 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
596 f&mut DebugStruct<'_, '_>.debug_struct("VideoOverlayCompositionMeta")
597 .field(name:"overlay", &self.overlay())
598 .finish()
599 }
600}
601
602#[cfg(feature = "v1_16")]
603#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
604#[repr(transparent)]
605#[doc(alias = "GstVideoCaptionMeta")]
606pub struct VideoCaptionMeta(ffi::GstVideoCaptionMeta);
607
608#[cfg(feature = "v1_16")]
609#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
610unsafe impl Send for VideoCaptionMeta {}
611#[cfg(feature = "v1_16")]
612#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
613unsafe impl Sync for VideoCaptionMeta {}
614
615#[cfg(feature = "v1_16")]
616#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
617impl VideoCaptionMeta {
618 #[doc(alias = "gst_buffer_add_video_caption_meta")]
619 pub fn add<'a>(
620 buffer: &'a mut gst::BufferRef,
621 caption_type: crate::VideoCaptionType,
622 data: &[u8],
623 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
624 skip_assert_initialized!();
625 assert!(!data.is_empty());
626 unsafe {
627 let meta = ffi::gst_buffer_add_video_caption_meta(
628 buffer.as_mut_ptr(),
629 caption_type.into_glib(),
630 data.as_ptr(),
631 data.len(),
632 );
633
634 Self::from_mut_ptr(buffer, meta)
635 }
636 }
637
638 #[doc(alias = "get_caption_type")]
639 #[inline]
640 pub fn caption_type(&self) -> crate::VideoCaptionType {
641 unsafe { from_glib(self.0.caption_type) }
642 }
643
644 #[doc(alias = "get_data")]
645 #[inline]
646 pub fn data(&self) -> &[u8] {
647 if self.0.size == 0 {
648 return &[];
649 }
650 unsafe {
651 use std::slice;
652
653 slice::from_raw_parts(self.0.data, self.0.size)
654 }
655 }
656}
657
658#[cfg(feature = "v1_16")]
659#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
660unsafe impl MetaAPI for VideoCaptionMeta {
661 type GstType = ffi::GstVideoCaptionMeta;
662
663 #[doc(alias = "gst_video_caption_meta_api_get_type")]
664 #[inline]
665 fn meta_api() -> glib::Type {
666 unsafe { from_glib(ffi::gst_video_caption_meta_api_get_type()) }
667 }
668}
669
670#[cfg(feature = "v1_16")]
671#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
672impl fmt::Debug for VideoCaptionMeta {
673 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
674 f.debug_struct("VideoCaptionMeta")
675 .field("caption_type", &self.caption_type())
676 .field("data", &self.data())
677 .finish()
678 }
679}
680
681#[cfg(feature = "v1_18")]
682#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
683#[repr(transparent)]
684#[doc(alias = "GstVideoAFDMeta")]
685pub struct VideoAFDMeta(ffi::GstVideoAFDMeta);
686
687#[cfg(feature = "v1_18")]
688#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
689unsafe impl Send for VideoAFDMeta {}
690#[cfg(feature = "v1_18")]
691#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
692unsafe impl Sync for VideoAFDMeta {}
693
694#[cfg(feature = "v1_18")]
695#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
696impl VideoAFDMeta {
697 #[doc(alias = "gst_buffer_add_video_afd_meta")]
698 pub fn add(
699 buffer: &mut gst::BufferRef,
700 field: u8,
701 spec: crate::VideoAFDSpec,
702 afd: crate::VideoAFDValue,
703 ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
704 skip_assert_initialized!();
705
706 unsafe {
707 let meta = ffi::gst_buffer_add_video_afd_meta(
708 buffer.as_mut_ptr(),
709 field,
710 spec.into_glib(),
711 afd.into_glib(),
712 );
713
714 Self::from_mut_ptr(buffer, meta)
715 }
716 }
717
718 #[doc(alias = "get_field")]
719 #[inline]
720 pub fn field(&self) -> u8 {
721 self.0.field
722 }
723
724 #[doc(alias = "get_spec")]
725 #[inline]
726 pub fn spec(&self) -> crate::VideoAFDSpec {
727 unsafe { from_glib(self.0.spec) }
728 }
729
730 #[doc(alias = "get_afd")]
731 #[inline]
732 pub fn afd(&self) -> crate::VideoAFDValue {
733 unsafe { from_glib(self.0.afd) }
734 }
735}
736
737#[cfg(feature = "v1_18")]
738#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
739unsafe impl MetaAPI for VideoAFDMeta {
740 type GstType = ffi::GstVideoAFDMeta;
741
742 #[doc(alias = "gst_video_afd_meta_api_get_type")]
743 #[inline]
744 fn meta_api() -> glib::Type {
745 unsafe { from_glib(ffi::gst_video_afd_meta_api_get_type()) }
746 }
747}
748
749#[cfg(feature = "v1_18")]
750#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
751impl fmt::Debug for VideoAFDMeta {
752 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
753 f.debug_struct("VideoAFDMeta")
754 .field("field", &self.field())
755 .field("spec", &self.spec())
756 .field("afd", &self.afd())
757 .finish()
758 }
759}
760
761#[cfg(feature = "v1_18")]
762#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
763#[repr(transparent)]
764#[doc(alias = "GstVideoBarMeta")]
765pub struct VideoBarMeta(ffi::GstVideoBarMeta);
766
767#[cfg(feature = "v1_18")]
768#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
769unsafe impl Send for VideoBarMeta {}
770#[cfg(feature = "v1_18")]
771#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
772unsafe impl Sync for VideoBarMeta {}
773
774#[cfg(feature = "v1_18")]
775#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
776impl VideoBarMeta {
777 #[doc(alias = "gst_buffer_add_video_bar_meta")]
778 pub fn add(
779 buffer: &mut gst::BufferRef,
780 field: u8,
781 is_letterbox: bool,
782 bar_data1: u32,
783 bar_data2: u32,
784 ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
785 skip_assert_initialized!();
786
787 unsafe {
788 let meta = ffi::gst_buffer_add_video_bar_meta(
789 buffer.as_mut_ptr(),
790 field,
791 is_letterbox.into_glib(),
792 bar_data1,
793 bar_data2,
794 );
795
796 Self::from_mut_ptr(buffer, meta)
797 }
798 }
799
800 #[doc(alias = "get_field")]
801 #[inline]
802 pub fn field(&self) -> u8 {
803 self.0.field
804 }
805
806 #[inline]
807 pub fn is_letterbox(&self) -> bool {
808 unsafe { from_glib(self.0.is_letterbox) }
809 }
810
811 #[doc(alias = "get_bar_data1")]
812 #[inline]
813 pub fn bar_data1(&self) -> u32 {
814 self.0.bar_data1
815 }
816
817 #[doc(alias = "get_bar_data2")]
818 #[inline]
819 pub fn bar_data2(&self) -> u32 {
820 self.0.bar_data2
821 }
822}
823
824#[cfg(feature = "v1_18")]
825#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
826unsafe impl MetaAPI for VideoBarMeta {
827 type GstType = ffi::GstVideoBarMeta;
828
829 #[doc(alias = "gst_video_bar_meta_api_get_type")]
830 #[inline]
831 fn meta_api() -> glib::Type {
832 unsafe { from_glib(ffi::gst_video_bar_meta_api_get_type()) }
833 }
834}
835
836#[cfg(feature = "v1_18")]
837#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
838impl fmt::Debug for VideoBarMeta {
839 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
840 f.debug_struct("VideoBarMeta")
841 .field("field", &self.field())
842 .field("is_letterbox", &self.is_letterbox())
843 .field("bar_data1", &self.bar_data1())
844 .field("bar_data2", &self.bar_data2())
845 .finish()
846 }
847}
848
849#[cfg(feature = "v1_20")]
850#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
851#[repr(transparent)]
852#[doc(alias = "GstVideoCodecAlphaMeta")]
853pub struct VideoCodecAlphaMeta(ffi::GstVideoCodecAlphaMeta);
854
855#[cfg(feature = "v1_20")]
856#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
857unsafe impl Send for VideoCodecAlphaMeta {}
858#[cfg(feature = "v1_20")]
859#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
860unsafe impl Sync for VideoCodecAlphaMeta {}
861
862#[cfg(feature = "v1_20")]
863#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
864impl VideoCodecAlphaMeta {
865 #[doc(alias = "gst_buffer_add_video_codec_alpha_meta")]
866 pub fn add(
867 buffer: &mut gst::BufferRef,
868 alpha_buffer: gst::Buffer,
869 ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
870 skip_assert_initialized!();
871 unsafe {
872 let meta = ffi::gst_buffer_add_video_codec_alpha_meta(
873 buffer.as_mut_ptr(),
874 alpha_buffer.to_glib_none().0,
875 );
876
877 Self::from_mut_ptr(buffer, meta)
878 }
879 }
880
881 #[inline]
882 pub fn alpha_buffer(&self) -> &gst::BufferRef {
883 unsafe { gst::BufferRef::from_ptr(self.0.buffer) }
884 }
885
886 #[inline]
887 pub fn alpha_buffer_owned(&self) -> gst::Buffer {
888 unsafe { from_glib_none(self.0.buffer) }
889 }
890}
891
892#[cfg(feature = "v1_20")]
893#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
894unsafe impl MetaAPI for VideoCodecAlphaMeta {
895 type GstType = ffi::GstVideoCodecAlphaMeta;
896
897 #[doc(alias = "gst_video_codec_alpha_meta_api_get_type")]
898 #[inline]
899 fn meta_api() -> glib::Type {
900 unsafe { from_glib(ffi::gst_video_codec_alpha_meta_api_get_type()) }
901 }
902}
903
904#[cfg(feature = "v1_20")]
905#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
906impl fmt::Debug for VideoCodecAlphaMeta {
907 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
908 f.debug_struct("VideoCodecAlphaMeta")
909 .field("buffer", &self.alpha_buffer())
910 .finish()
911 }
912}
913
914#[cfg(test)]
915mod tests {
916 use super::*;
917
918 #[test]
919 fn test_add_get_meta() {
920 gst::init().unwrap();
921
922 let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
923 {
924 let meta = VideoMeta::add(
925 buffer.get_mut().unwrap(),
926 crate::VideoFrameFlags::empty(),
927 crate::VideoFormat::Argb,
928 320,
929 240,
930 )
931 .unwrap();
932 assert_eq!(meta.id(), 0);
933 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
934 assert_eq!(meta.format(), crate::VideoFormat::Argb);
935 assert_eq!(meta.width(), 320);
936 assert_eq!(meta.height(), 240);
937 assert_eq!(meta.n_planes(), 1);
938 assert_eq!(meta.offset(), &[0]);
939 assert_eq!(meta.stride(), &[320 * 4]);
940 }
941
942 {
943 let meta = buffer.meta::<VideoMeta>().unwrap();
944 assert_eq!(meta.id(), 0);
945 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
946 assert_eq!(meta.format(), crate::VideoFormat::Argb);
947 assert_eq!(meta.width(), 320);
948 assert_eq!(meta.height(), 240);
949 assert_eq!(meta.n_planes(), 1);
950 assert_eq!(meta.offset(), &[0]);
951 assert_eq!(meta.stride(), &[320 * 4]);
952 }
953 }
954
955 #[test]
956 fn test_add_full_get_meta() {
957 gst::init().unwrap();
958
959 let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
960 {
961 let meta = VideoMeta::add_full(
962 buffer.get_mut().unwrap(),
963 crate::VideoFrameFlags::empty(),
964 crate::VideoFormat::Argb,
965 320,
966 240,
967 &[0],
968 &[320 * 4],
969 )
970 .unwrap();
971 assert_eq!(meta.id(), 0);
972 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
973 assert_eq!(meta.format(), crate::VideoFormat::Argb);
974 assert_eq!(meta.width(), 320);
975 assert_eq!(meta.height(), 240);
976 assert_eq!(meta.n_planes(), 1);
977 assert_eq!(meta.offset(), &[0]);
978 assert_eq!(meta.stride(), &[320 * 4]);
979 }
980
981 {
982 let meta = buffer.meta::<VideoMeta>().unwrap();
983 assert_eq!(meta.id(), 0);
984 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
985 assert_eq!(meta.format(), crate::VideoFormat::Argb);
986 assert_eq!(meta.width(), 320);
987 assert_eq!(meta.height(), 240);
988 assert_eq!(meta.n_planes(), 1);
989 assert_eq!(meta.offset(), &[0]);
990 assert_eq!(meta.stride(), &[320 * 4]);
991 }
992 }
993
994 #[test]
995 #[cfg(feature = "v1_18")]
996 fn test_vide_meta_alignment() {
997 gst::init().unwrap();
998
999 let mut buffer = gst::Buffer::with_size(115200).unwrap();
1000 let meta = VideoMeta::add(
1001 buffer.get_mut().unwrap(),
1002 crate::VideoFrameFlags::empty(),
1003 crate::VideoFormat::Nv12,
1004 320,
1005 240,
1006 )
1007 .unwrap();
1008
1009 let alig = meta.alignment();
1010 assert_eq!(alig, crate::VideoAlignment::new(0, 0, 0, 0, &[0, 0, 0, 0]));
1011
1012 assert_eq!(meta.plane_size().unwrap(), [76800, 38400, 0, 0]);
1013 assert_eq!(meta.plane_height().unwrap(), [240, 120, 0, 0]);
1014
1015 /* horizontal padding */
1016 let mut info = crate::VideoInfo::builder(crate::VideoFormat::Nv12, 320, 240)
1017 .build()
1018 .expect("Failed to create VideoInfo");
1019 let mut alig = crate::VideoAlignment::new(0, 0, 2, 6, &[0, 0, 0, 0]);
1020 info.align(&mut alig).unwrap();
1021
1022 let mut meta = VideoMeta::add_full(
1023 buffer.get_mut().unwrap(),
1024 crate::VideoFrameFlags::empty(),
1025 crate::VideoFormat::Nv12,
1026 info.width(),
1027 info.height(),
1028 info.offset(),
1029 info.stride(),
1030 )
1031 .unwrap();
1032 meta.set_alignment(&alig).unwrap();
1033
1034 let alig = meta.alignment();
1035 assert_eq!(alig, crate::VideoAlignment::new(0, 0, 2, 6, &[0, 0, 0, 0]));
1036
1037 assert_eq!(meta.plane_size().unwrap(), [78720, 39360, 0, 0]);
1038 assert_eq!(meta.plane_height().unwrap(), [240, 120, 0, 0]);
1039
1040 /* vertical alignment */
1041 let mut info = crate::VideoInfo::builder(crate::VideoFormat::Nv12, 320, 240)
1042 .build()
1043 .expect("Failed to create VideoInfo");
1044 let mut alig = crate::VideoAlignment::new(2, 6, 0, 0, &[0, 0, 0, 0]);
1045 info.align(&mut alig).unwrap();
1046
1047 let mut meta = VideoMeta::add_full(
1048 buffer.get_mut().unwrap(),
1049 crate::VideoFrameFlags::empty(),
1050 crate::VideoFormat::Nv12,
1051 info.width(),
1052 info.height(),
1053 info.offset(),
1054 info.stride(),
1055 )
1056 .unwrap();
1057 meta.set_alignment(&alig).unwrap();
1058
1059 let alig = meta.alignment();
1060 assert_eq!(alig, crate::VideoAlignment::new(2, 6, 0, 0, &[0, 0, 0, 0]));
1061
1062 assert_eq!(meta.plane_size().unwrap(), [79360, 39680, 0, 0]);
1063 assert_eq!(meta.plane_height().unwrap(), [248, 124, 0, 0]);
1064 }
1065}
1066