1use std::{fmt, ptr};
4
5use crate::ffi;
6use glib::translate::*;
7use gst::prelude::*;
8
9#[repr(transparent)]
33#[doc(alias = "GstVideoMeta")]
34pub struct VideoMeta(ffi::GstVideoMeta);
35
36unsafe impl Send for VideoMeta {}
37unsafe impl Sync for VideoMeta {}
38
39impl VideoMeta {
40 #[doc(alias = "gst_buffer_add_video_meta")]
41 pub fn add(
42 buffer: &mut gst::BufferRef,
43 video_frame_flags: crate::VideoFrameFlags,
44 format: crate::VideoFormat,
45 width: u32,
46 height: u32,
47 ) -> Result<gst::MetaRefMut<'_, Self, gst::meta::Standalone>, glib::BoolError> {
48 skip_assert_initialized!();
49
50 if format == crate::VideoFormat::Unknown || format == crate::VideoFormat::Encoded {
51 return Err(glib::bool_error!("Unsupported video format {}", format));
52 }
53
54 #[cfg(feature = "v1_24")]
55 if format == crate::VideoFormat::DmaDrm {
56 return Err(glib::bool_error!("Use `add_full()` for DMA_DRM formats"));
57 }
58
59 let info = crate::VideoInfo::builder(format, width, height).build()?;
60
61 if !info.is_valid() {
62 return Err(glib::bool_error!("Invalid video info"));
63 }
64
65 if buffer.size() < info.size() {
66 return Err(glib::bool_error!(
67 "Buffer smaller than required frame size ({} < {})",
68 buffer.size(),
69 info.size()
70 ));
71 }
72
73 unsafe {
74 let meta = ffi::gst_buffer_add_video_meta(
75 buffer.as_mut_ptr(),
76 video_frame_flags.into_glib(),
77 format.into_glib(),
78 width,
79 height,
80 );
81
82 if meta.is_null() {
83 return Err(glib::bool_error!("Failed to add video meta"));
84 }
85
86 Ok(Self::from_mut_ptr(buffer, meta))
87 }
88 }
89
90 pub fn add_full<'a>(
91 buffer: &'a mut gst::BufferRef,
92 video_frame_flags: crate::VideoFrameFlags,
93 format: crate::VideoFormat,
94 width: u32,
95 height: u32,
96 offset: &[usize],
97 stride: &[i32],
98 ) -> Result<gst::MetaRefMut<'a, Self, gst::meta::Standalone>, glib::BoolError> {
99 skip_assert_initialized!();
100
101 if format == crate::VideoFormat::Unknown || format == crate::VideoFormat::Encoded {
102 return Err(glib::bool_error!("Unsupported video format {}", format));
103 }
104
105 assert_eq!(offset.len(), stride.len());
106
107 unsafe {
108 let meta = ffi::gst_buffer_add_video_meta_full(
109 buffer.as_mut_ptr(),
110 video_frame_flags.into_glib(),
111 format.into_glib(),
112 width,
113 height,
114 offset.len() as u32,
115 offset.as_ptr() as *mut _,
116 stride.as_ptr() as *mut _,
117 );
118
119 if meta.is_null() {
120 return Err(glib::bool_error!("Failed to add video meta"));
121 }
122
123 Ok(Self::from_mut_ptr(buffer, meta))
124 }
125 }
126
127 pub fn add_from_info<'a>(
128 buffer: &'a mut gst::BufferRef,
129 video_frame_flags: crate::VideoFrameFlags,
130 info: &crate::VideoInfo,
131 ) -> Result<gst::MetaRefMut<'a, Self, gst::meta::Standalone>, glib::BoolError> {
132 skip_assert_initialized!();
133
134 if info.format() == crate::VideoFormat::Unknown
135 || info.format() == crate::VideoFormat::Encoded
136 {
137 return Err(glib::bool_error!(
138 "Unsupported video format {}",
139 info.format()
140 ));
141 }
142
143 #[cfg(feature = "v1_24")]
144 if info.format() == crate::VideoFormat::DmaDrm {
145 return Err(glib::bool_error!("Use `add_full()` for DMA_DRM formats"));
146 }
147
148 if !info.is_valid() {
149 return Err(glib::bool_error!("Invalid video info"));
150 }
151
152 if buffer.size() < info.size() {
153 return Err(glib::bool_error!(
154 "Buffer smaller than required frame size ({} < {})",
155 buffer.size(),
156 info.size()
157 ));
158 }
159
160 Self::add_full(
161 buffer,
162 video_frame_flags,
163 info.format(),
164 info.width(),
165 info.height(),
166 info.offset(),
167 info.stride(),
168 )
169 }
170
171 #[doc(alias = "get_flags")]
172 #[inline]
173 pub fn video_frame_flags(&self) -> crate::VideoFrameFlags {
174 unsafe { from_glib(self.0.flags) }
175 }
176
177 #[doc(alias = "get_format")]
178 #[inline]
179 pub fn format(&self) -> crate::VideoFormat {
180 unsafe { from_glib(self.0.format) }
181 }
182
183 #[doc(alias = "get_id")]
184 #[inline]
185 pub fn id(&self) -> i32 {
186 self.0.id
187 }
188
189 #[doc(alias = "get_width")]
190 #[inline]
191 pub fn width(&self) -> u32 {
192 self.0.width
193 }
194
195 #[doc(alias = "get_height")]
196 #[inline]
197 pub fn height(&self) -> u32 {
198 self.0.height
199 }
200
201 #[doc(alias = "get_n_planes")]
202 #[inline]
203 pub fn n_planes(&self) -> u32 {
204 self.0.n_planes
205 }
206
207 #[doc(alias = "get_offset")]
208 #[inline]
209 pub fn offset(&self) -> &[usize] {
210 &self.0.offset[0..(self.0.n_planes as usize)]
211 }
212
213 #[doc(alias = "get_stride")]
214 #[inline]
215 pub fn stride(&self) -> &[i32] {
216 &self.0.stride[0..(self.0.n_planes as usize)]
217 }
218
219 #[cfg(feature = "v1_18")]
220 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
221 #[doc(alias = "get_alignment")]
222 #[inline]
223 pub fn alignment(&self) -> crate::VideoAlignment {
224 crate::VideoAlignment::new(
225 self.0.alignment.padding_top,
226 self.0.alignment.padding_bottom,
227 self.0.alignment.padding_left,
228 self.0.alignment.padding_right,
229 &self.0.alignment.stride_align,
230 )
231 }
232
233 #[cfg(feature = "v1_18")]
243 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
244 #[doc(alias = "get_plane_size")]
245 #[doc(alias = "gst_video_meta_get_plane_size")]
246 pub fn plane_size(&self) -> Result<[usize; crate::VIDEO_MAX_PLANES], glib::BoolError> {
247 let mut plane_size = [0; crate::VIDEO_MAX_PLANES];
248
249 unsafe {
250 glib::result_from_gboolean!(
251 ffi::gst_video_meta_get_plane_size(mut_override(&self.0), &mut plane_size,),
252 "Failed to get plane size"
253 )?;
254 }
255
256 Ok(plane_size)
257 }
258
259 #[cfg(feature = "v1_18")]
273 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
274 #[doc(alias = "get_plane_height")]
275 #[doc(alias = "gst_video_meta_get_plane_height")]
276 pub fn plane_height(&self) -> Result<[u32; crate::VIDEO_MAX_PLANES], glib::BoolError> {
277 let mut plane_height = [0; crate::VIDEO_MAX_PLANES];
278
279 unsafe {
280 glib::result_from_gboolean!(
281 ffi::gst_video_meta_get_plane_height(mut_override(&self.0), &mut plane_height,),
282 "Failed to get plane height"
283 )?;
284 }
285
286 Ok(plane_height)
287 }
288
289 #[cfg(feature = "v1_18")]
303 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
304 #[doc(alias = "gst_video_meta_set_alignment")]
305 #[doc(alias = "gst_video_meta_set_alignment_full")]
306 pub fn set_alignment(
307 &mut self,
308 alignment: &crate::VideoAlignment,
309 ) -> Result<(), glib::BoolError> {
310 #[cfg(feature = "v1_28")]
311 unsafe {
312 glib::result_from_gboolean!(
313 ffi::gst_video_meta_set_alignment_full(&mut self.0, &alignment.0),
314 "Failed to set alignment on VideoMeta"
315 )
316 }
317 #[cfg(not(feature = "v1_28"))]
318 unsafe {
319 glib::result_from_gboolean!(
320 ffi::gst_video_meta_set_alignment(&mut self.0, alignment.0),
321 "Failed to set alignment on VideoMeta"
322 )
323 }
324 }
325}
326
327unsafe impl MetaAPI for VideoMeta {
328 type GstType = ffi::GstVideoMeta;
329
330 #[doc(alias = "gst_video_meta_api_get_type")]
331 #[inline]
332 fn meta_api() -> glib::Type {
333 unsafe { from_glib(ffi::gst_video_meta_api_get_type()) }
334 }
335}
336
337impl fmt::Debug for VideoMeta {
338 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339 f.debug_struct("VideoMeta")
340 .field("id", &self.id())
341 .field("video_frame_flags", &self.video_frame_flags())
342 .field("format", &self.format())
343 .field("width", &self.width())
344 .field("height", &self.height())
345 .field("n_planes", &self.n_planes())
346 .field("offset", &self.offset())
347 .field("stride", &self.stride())
348 .finish()
349 }
350}
351
352#[repr(transparent)]
353#[doc(alias = "GstVideoCropMeta")]
354pub struct VideoCropMeta(ffi::GstVideoCropMeta);
355
356unsafe impl Send for VideoCropMeta {}
357unsafe impl Sync for VideoCropMeta {}
358
359impl VideoCropMeta {
360 #[doc(alias = "gst_buffer_add_meta")]
361 pub fn add(
362 buffer: &mut gst::BufferRef,
363 rect: (u32, u32, u32, u32),
364 ) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
365 skip_assert_initialized!();
366 unsafe {
367 let meta = gst::ffi::gst_buffer_add_meta(
368 buffer.as_mut_ptr(),
369 ffi::gst_video_crop_meta_get_info(),
370 ptr::null_mut(),
371 ) as *mut ffi::GstVideoCropMeta;
372
373 {
374 let meta = &mut *meta;
375 meta.x = rect.0;
376 meta.y = rect.1;
377 meta.width = rect.2;
378 meta.height = rect.3;
379 }
380
381 Self::from_mut_ptr(buffer, meta)
382 }
383 }
384
385 #[doc(alias = "get_rect")]
386 #[inline]
387 pub fn rect(&self) -> (u32, u32, u32, u32) {
388 (self.0.x, self.0.y, self.0.width, self.0.height)
389 }
390
391 #[inline]
392 pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) {
393 self.0.x = rect.0;
394 self.0.y = rect.1;
395 self.0.width = rect.2;
396 self.0.height = rect.3;
397 }
398}
399
400unsafe impl MetaAPI for VideoCropMeta {
401 type GstType = ffi::GstVideoCropMeta;
402
403 #[doc(alias = "gst_video_crop_meta_api_get_type")]
404 #[inline]
405 fn meta_api() -> glib::Type {
406 unsafe { from_glib(ffi::gst_video_crop_meta_api_get_type()) }
407 }
408}
409
410impl fmt::Debug for VideoCropMeta {
411 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 f.debug_struct("VideoCropMeta")
413 .field("rect", &self.rect())
414 .finish()
415 }
416}
417
418#[repr(transparent)]
419#[doc(alias = "GstVideoRegionOfInterestMeta")]
420pub struct VideoRegionOfInterestMeta(ffi::GstVideoRegionOfInterestMeta);
421
422unsafe impl Send for VideoRegionOfInterestMeta {}
423unsafe impl Sync for VideoRegionOfInterestMeta {}
424
425impl VideoRegionOfInterestMeta {
426 #[doc(alias = "gst_buffer_add_video_region_of_interest_meta")]
427 pub fn add<'a>(
428 buffer: &'a mut gst::BufferRef,
429 roi_type: &str,
430 rect: (u32, u32, u32, u32),
431 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
432 skip_assert_initialized!();
433 unsafe {
434 let meta = ffi::gst_buffer_add_video_region_of_interest_meta(
435 buffer.as_mut_ptr(),
436 roi_type.to_glib_none().0,
437 rect.0,
438 rect.1,
439 rect.2,
440 rect.3,
441 );
442
443 Self::from_mut_ptr(buffer, meta)
444 }
445 }
446
447 #[doc(alias = "get_rect")]
448 #[inline]
449 pub fn rect(&self) -> (u32, u32, u32, u32) {
450 (self.0.x, self.0.y, self.0.w, self.0.h)
451 }
452
453 #[doc(alias = "get_id")]
454 #[inline]
455 pub fn id(&self) -> i32 {
456 self.0.id
457 }
458
459 #[doc(alias = "get_parent_id")]
460 #[inline]
461 pub fn parent_id(&self) -> i32 {
462 self.0.parent_id
463 }
464
465 #[doc(alias = "get_roi_type")]
466 #[inline]
467 pub fn roi_type<'a>(&self) -> &'a str {
468 unsafe { glib::Quark::from_glib(self.0.roi_type).as_str() }
469 }
470
471 #[doc(alias = "get_params")]
472 pub fn params(&self) -> ParamsIter<'_> {
473 ParamsIter {
474 _meta: self,
475 list: ptr::NonNull::new(self.0.params),
476 }
477 }
478
479 #[doc(alias = "get_param")]
480 #[inline]
481 pub fn param<'b>(&'b self, name: &str) -> Option<&'b gst::StructureRef> {
482 self.params().find(|s| s.name() == name)
483 }
484
485 #[inline]
486 pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) {
487 self.0.x = rect.0;
488 self.0.y = rect.1;
489 self.0.w = rect.2;
490 self.0.h = rect.3;
491 }
492
493 #[inline]
494 pub fn set_id(&mut self, id: i32) {
495 self.0.id = id
496 }
497
498 #[inline]
499 pub fn set_parent_id(&mut self, id: i32) {
500 self.0.parent_id = id
501 }
502
503 #[doc(alias = "gst_video_region_of_interest_meta_add_param")]
504 pub fn add_param(&mut self, s: gst::Structure) {
505 unsafe {
506 ffi::gst_video_region_of_interest_meta_add_param(&mut self.0, s.into_glib_ptr());
507 }
508 }
509}
510
511#[must_use = "iterators are lazy and do nothing unless consumed"]
512pub struct ParamsIter<'a> {
513 _meta: &'a VideoRegionOfInterestMeta,
514 list: Option<ptr::NonNull<glib::ffi::GList>>,
515}
516
517impl<'a> Iterator for ParamsIter<'a> {
518 type Item = &'a gst::StructureRef;
519
520 fn next(&mut self) -> Option<&'a gst::StructureRef> {
521 match self.list {
522 None => None,
523 Some(list) => unsafe {
524 self.list = ptr::NonNull::new(list.as_ref().next);
525 let data = list.as_ref().data;
526
527 let s = gst::StructureRef::from_glib_borrow(data as *const gst::ffi::GstStructure);
528
529 Some(s)
530 },
531 }
532 }
533}
534
535impl std::iter::FusedIterator for ParamsIter<'_> {}
536
537unsafe impl MetaAPI for VideoRegionOfInterestMeta {
538 type GstType = ffi::GstVideoRegionOfInterestMeta;
539
540 #[doc(alias = "gst_video_region_of_interest_meta_api_get_type")]
541 #[inline]
542 fn meta_api() -> glib::Type {
543 unsafe { from_glib(ffi::gst_video_region_of_interest_meta_api_get_type()) }
544 }
545}
546
547impl fmt::Debug for VideoRegionOfInterestMeta {
548 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
549 f.debug_struct("VideoRegionOfInterestMeta")
550 .field("roi_type", &self.roi_type())
551 .field("rect", &self.rect())
552 .field("id", &self.id())
553 .field("parent_id", &self.parent_id())
554 .field("params", &self.params().collect::<Vec<_>>())
555 .finish()
556 }
557}
558
559#[repr(transparent)]
560#[doc(alias = "GstVideoAffineTransformationMeta")]
561pub struct VideoAffineTransformationMeta(ffi::GstVideoAffineTransformationMeta);
562
563unsafe impl Send for VideoAffineTransformationMeta {}
564unsafe impl Sync for VideoAffineTransformationMeta {}
565
566impl VideoAffineTransformationMeta {
567 #[doc(alias = "gst_buffer_add_meta")]
568 pub fn add<'a>(
569 buffer: &'a mut gst::BufferRef,
570 matrix: Option<&[[f32; 4]; 4]>,
571 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
572 skip_assert_initialized!();
573 unsafe {
574 let meta = gst::ffi::gst_buffer_add_meta(
575 buffer.as_mut_ptr(),
576 ffi::gst_video_affine_transformation_meta_get_info(),
577 ptr::null_mut(),
578 ) as *mut ffi::GstVideoAffineTransformationMeta;
579
580 if let Some(matrix) = matrix {
581 let meta = &mut *meta;
582 for (i, o) in Iterator::zip(matrix.iter().flatten(), meta.matrix.iter_mut()) {
583 *o = *i;
584 }
585 }
586
587 Self::from_mut_ptr(buffer, meta)
588 }
589 }
590
591 #[doc(alias = "get_matrix")]
592 #[inline]
593 pub fn matrix(&self) -> &[[f32; 4]; 4] {
594 unsafe { &*(&self.0.matrix as *const [f32; 16] as *const [[f32; 4]; 4]) }
595 }
596
597 #[inline]
598 pub fn set_matrix(&mut self, matrix: &[[f32; 4]; 4]) {
599 for (i, o) in Iterator::zip(matrix.iter().flatten(), self.0.matrix.iter_mut()) {
600 *o = *i;
601 }
602 }
603
604 #[doc(alias = "gst_video_affine_transformation_meta_apply_matrix")]
605 pub fn apply_matrix(&mut self, matrix: &[[f32; 4]; 4]) {
606 unsafe {
607 ffi::gst_video_affine_transformation_meta_apply_matrix(
608 &mut self.0,
609 matrix as *const [[f32; 4]; 4] as *const [f32; 16],
610 );
611 }
612 }
613}
614
615unsafe impl MetaAPI for VideoAffineTransformationMeta {
616 type GstType = ffi::GstVideoAffineTransformationMeta;
617
618 #[doc(alias = "gst_video_affine_transformation_meta_api_get_type")]
619 #[inline]
620 fn meta_api() -> glib::Type {
621 unsafe { from_glib(ffi::gst_video_affine_transformation_meta_api_get_type()) }
622 }
623}
624
625impl fmt::Debug for VideoAffineTransformationMeta {
626 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
627 f.debug_struct("VideoAffineTransformationMeta")
628 .field("matrix", &self.matrix())
629 .finish()
630 }
631}
632
633#[repr(transparent)]
634#[doc(alias = "GstVideoOverlayCompositionMeta")]
635pub struct VideoOverlayCompositionMeta(ffi::GstVideoOverlayCompositionMeta);
636
637unsafe impl Send for VideoOverlayCompositionMeta {}
638unsafe impl Sync for VideoOverlayCompositionMeta {}
639
640impl VideoOverlayCompositionMeta {
641 #[doc(alias = "gst_buffer_add_video_overlay_composition_meta")]
642 pub fn add<'a>(
643 buffer: &'a mut gst::BufferRef,
644 overlay: &crate::VideoOverlayComposition,
645 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
646 skip_assert_initialized!();
647 unsafe {
648 let meta = ffi::gst_buffer_add_video_overlay_composition_meta(
649 buffer.as_mut_ptr(),
650 overlay.as_mut_ptr(),
651 );
652
653 Self::from_mut_ptr(buffer, meta)
654 }
655 }
656
657 #[doc(alias = "get_overlay")]
658 #[inline]
659 pub fn overlay(&self) -> &crate::VideoOverlayCompositionRef {
660 unsafe { crate::VideoOverlayCompositionRef::from_ptr(self.0.overlay) }
661 }
662
663 #[doc(alias = "get_overlay_owned")]
664 #[inline]
665 pub fn overlay_owned(&self) -> crate::VideoOverlayComposition {
666 unsafe { from_glib_none(self.overlay().as_ptr()) }
667 }
668
669 #[inline]
670 pub fn set_overlay(&mut self, overlay: &crate::VideoOverlayComposition) {
671 #![allow(clippy::cast_ptr_alignment)]
672 unsafe {
673 gst::ffi::gst_mini_object_unref(self.0.overlay as *mut _);
674 self.0.overlay =
675 gst::ffi::gst_mini_object_ref(overlay.as_mut_ptr() as *mut _) as *mut _;
676 }
677 }
678}
679
680unsafe impl MetaAPI for VideoOverlayCompositionMeta {
681 type GstType = ffi::GstVideoOverlayCompositionMeta;
682
683 #[doc(alias = "gst_video_overlay_composition_meta_api_get_type")]
684 #[inline]
685 fn meta_api() -> glib::Type {
686 unsafe { from_glib(ffi::gst_video_overlay_composition_meta_api_get_type()) }
687 }
688}
689
690impl fmt::Debug for VideoOverlayCompositionMeta {
691 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
692 f.debug_struct("VideoOverlayCompositionMeta")
693 .field("overlay", &self.overlay())
694 .finish()
695 }
696}
697
698#[cfg(feature = "v1_16")]
699#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
700#[repr(transparent)]
701#[doc(alias = "GstVideoCaptionMeta")]
702pub struct VideoCaptionMeta(ffi::GstVideoCaptionMeta);
703
704#[cfg(feature = "v1_16")]
705#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
706unsafe impl Send for VideoCaptionMeta {}
707#[cfg(feature = "v1_16")]
708#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
709unsafe impl Sync for VideoCaptionMeta {}
710
711#[cfg(feature = "v1_16")]
712#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
713impl VideoCaptionMeta {
714 #[doc(alias = "gst_buffer_add_video_caption_meta")]
715 pub fn add<'a>(
716 buffer: &'a mut gst::BufferRef,
717 caption_type: crate::VideoCaptionType,
718 data: &[u8],
719 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
720 skip_assert_initialized!();
721 assert!(!data.is_empty());
722 unsafe {
723 let meta = ffi::gst_buffer_add_video_caption_meta(
724 buffer.as_mut_ptr(),
725 caption_type.into_glib(),
726 data.as_ptr(),
727 data.len(),
728 );
729
730 Self::from_mut_ptr(buffer, meta)
731 }
732 }
733
734 #[doc(alias = "get_caption_type")]
735 #[inline]
736 pub fn caption_type(&self) -> crate::VideoCaptionType {
737 unsafe { from_glib(self.0.caption_type) }
738 }
739
740 #[doc(alias = "get_data")]
741 #[inline]
742 pub fn data(&self) -> &[u8] {
743 if self.0.size == 0 {
744 return &[];
745 }
746 unsafe {
747 use std::slice;
748
749 slice::from_raw_parts(self.0.data, self.0.size)
750 }
751 }
752}
753
754#[cfg(feature = "v1_16")]
755#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
756unsafe impl MetaAPI for VideoCaptionMeta {
757 type GstType = ffi::GstVideoCaptionMeta;
758
759 #[doc(alias = "gst_video_caption_meta_api_get_type")]
760 #[inline]
761 fn meta_api() -> glib::Type {
762 unsafe { from_glib(ffi::gst_video_caption_meta_api_get_type()) }
763 }
764}
765
766#[cfg(feature = "v1_16")]
767#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
768impl fmt::Debug for VideoCaptionMeta {
769 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
770 f.debug_struct("VideoCaptionMeta")
771 .field("caption_type", &self.caption_type())
772 .field("data", &self.data())
773 .finish()
774 }
775}
776
777#[cfg(feature = "v1_18")]
778#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
779#[repr(transparent)]
780#[doc(alias = "GstVideoAFDMeta")]
781pub struct VideoAFDMeta(ffi::GstVideoAFDMeta);
782
783#[cfg(feature = "v1_18")]
784#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
785unsafe impl Send for VideoAFDMeta {}
786#[cfg(feature = "v1_18")]
787#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
788unsafe impl Sync for VideoAFDMeta {}
789
790#[cfg(feature = "v1_18")]
791#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
792impl VideoAFDMeta {
793 #[doc(alias = "gst_buffer_add_video_afd_meta")]
794 pub fn add(
795 buffer: &mut gst::BufferRef,
796 field: u8,
797 spec: crate::VideoAFDSpec,
798 afd: crate::VideoAFDValue,
799 ) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
800 skip_assert_initialized!();
801
802 unsafe {
803 let meta = ffi::gst_buffer_add_video_afd_meta(
804 buffer.as_mut_ptr(),
805 field,
806 spec.into_glib(),
807 afd.into_glib(),
808 );
809
810 Self::from_mut_ptr(buffer, meta)
811 }
812 }
813
814 #[doc(alias = "get_field")]
815 #[inline]
816 pub fn field(&self) -> u8 {
817 self.0.field
818 }
819
820 #[doc(alias = "get_spec")]
821 #[inline]
822 pub fn spec(&self) -> crate::VideoAFDSpec {
823 unsafe { from_glib(self.0.spec) }
824 }
825
826 #[doc(alias = "get_afd")]
827 #[inline]
828 pub fn afd(&self) -> crate::VideoAFDValue {
829 unsafe { from_glib(self.0.afd) }
830 }
831}
832
833#[cfg(feature = "v1_18")]
834#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
835unsafe impl MetaAPI for VideoAFDMeta {
836 type GstType = ffi::GstVideoAFDMeta;
837
838 #[doc(alias = "gst_video_afd_meta_api_get_type")]
839 #[inline]
840 fn meta_api() -> glib::Type {
841 unsafe { from_glib(ffi::gst_video_afd_meta_api_get_type()) }
842 }
843}
844
845#[cfg(feature = "v1_18")]
846#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
847impl fmt::Debug for VideoAFDMeta {
848 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
849 f.debug_struct("VideoAFDMeta")
850 .field("field", &self.field())
851 .field("spec", &self.spec())
852 .field("afd", &self.afd())
853 .finish()
854 }
855}
856
857#[cfg(feature = "v1_18")]
858#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
859#[repr(transparent)]
860#[doc(alias = "GstVideoBarMeta")]
861pub struct VideoBarMeta(ffi::GstVideoBarMeta);
862
863#[cfg(feature = "v1_18")]
864#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
865unsafe impl Send for VideoBarMeta {}
866#[cfg(feature = "v1_18")]
867#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
868unsafe impl Sync for VideoBarMeta {}
869
870#[cfg(feature = "v1_18")]
871#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
872impl VideoBarMeta {
873 #[doc(alias = "gst_buffer_add_video_bar_meta")]
874 pub fn add(
875 buffer: &mut gst::BufferRef,
876 field: u8,
877 is_letterbox: bool,
878 bar_data1: u32,
879 bar_data2: u32,
880 ) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
881 skip_assert_initialized!();
882
883 unsafe {
884 let meta = ffi::gst_buffer_add_video_bar_meta(
885 buffer.as_mut_ptr(),
886 field,
887 is_letterbox.into_glib(),
888 bar_data1,
889 bar_data2,
890 );
891
892 Self::from_mut_ptr(buffer, meta)
893 }
894 }
895
896 #[doc(alias = "get_field")]
897 #[inline]
898 pub fn field(&self) -> u8 {
899 self.0.field
900 }
901
902 #[inline]
903 pub fn is_letterbox(&self) -> bool {
904 unsafe { from_glib(self.0.is_letterbox) }
905 }
906
907 #[doc(alias = "get_bar_data1")]
908 #[inline]
909 pub fn bar_data1(&self) -> u32 {
910 self.0.bar_data1
911 }
912
913 #[doc(alias = "get_bar_data2")]
914 #[inline]
915 pub fn bar_data2(&self) -> u32 {
916 self.0.bar_data2
917 }
918}
919
920#[cfg(feature = "v1_18")]
921#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
922unsafe impl MetaAPI for VideoBarMeta {
923 type GstType = ffi::GstVideoBarMeta;
924
925 #[doc(alias = "gst_video_bar_meta_api_get_type")]
926 #[inline]
927 fn meta_api() -> glib::Type {
928 unsafe { from_glib(ffi::gst_video_bar_meta_api_get_type()) }
929 }
930}
931
932#[cfg(feature = "v1_18")]
933#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
934impl fmt::Debug for VideoBarMeta {
935 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
936 f.debug_struct("VideoBarMeta")
937 .field("field", &self.field())
938 .field("is_letterbox", &self.is_letterbox())
939 .field("bar_data1", &self.bar_data1())
940 .field("bar_data2", &self.bar_data2())
941 .finish()
942 }
943}
944
945#[cfg(feature = "v1_20")]
946#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
947#[repr(transparent)]
948#[doc(alias = "GstVideoCodecAlphaMeta")]
949pub struct VideoCodecAlphaMeta(ffi::GstVideoCodecAlphaMeta);
950
951#[cfg(feature = "v1_20")]
952#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
953unsafe impl Send for VideoCodecAlphaMeta {}
954#[cfg(feature = "v1_20")]
955#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
956unsafe impl Sync for VideoCodecAlphaMeta {}
957
958#[cfg(feature = "v1_20")]
959#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
960impl VideoCodecAlphaMeta {
961 #[doc(alias = "gst_buffer_add_video_codec_alpha_meta")]
962 pub fn add(
963 buffer: &mut gst::BufferRef,
964 alpha_buffer: gst::Buffer,
965 ) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
966 skip_assert_initialized!();
967 unsafe {
968 let meta = ffi::gst_buffer_add_video_codec_alpha_meta(
969 buffer.as_mut_ptr(),
970 alpha_buffer.to_glib_none().0,
971 );
972
973 Self::from_mut_ptr(buffer, meta)
974 }
975 }
976
977 #[inline]
978 pub fn alpha_buffer(&self) -> &gst::BufferRef {
979 unsafe { gst::BufferRef::from_ptr(self.0.buffer) }
980 }
981
982 #[inline]
983 pub fn alpha_buffer_owned(&self) -> gst::Buffer {
984 unsafe { from_glib_none(self.0.buffer) }
985 }
986}
987
988#[cfg(feature = "v1_20")]
989#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
990unsafe impl MetaAPI for VideoCodecAlphaMeta {
991 type GstType = ffi::GstVideoCodecAlphaMeta;
992
993 #[doc(alias = "gst_video_codec_alpha_meta_api_get_type")]
994 #[inline]
995 fn meta_api() -> glib::Type {
996 unsafe { from_glib(ffi::gst_video_codec_alpha_meta_api_get_type()) }
997 }
998}
999
1000#[cfg(feature = "v1_20")]
1001#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1002impl fmt::Debug for VideoCodecAlphaMeta {
1003 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1004 f.debug_struct("VideoCodecAlphaMeta")
1005 .field("buffer", &self.alpha_buffer())
1006 .finish()
1007 }
1008}
1009
1010#[cfg(feature = "v1_22")]
1011#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1012#[repr(transparent)]
1013#[doc(alias = "GstVideoSEIUserDataUnregisteredMeta")]
1014pub struct VideoSeiUserDataUnregisteredMeta(ffi::GstVideoSEIUserDataUnregisteredMeta);
1015
1016#[cfg(feature = "v1_22")]
1017#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1018unsafe impl Send for VideoSeiUserDataUnregisteredMeta {}
1019#[cfg(feature = "v1_22")]
1020#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1021unsafe impl Sync for VideoSeiUserDataUnregisteredMeta {}
1022
1023#[cfg(feature = "v1_22")]
1024#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1025impl VideoSeiUserDataUnregisteredMeta {
1026 #[doc(alias = "gst_buffer_add_video_sei_user_data_unregistered_meta")]
1027 pub fn add<'a>(
1028 buffer: &'a mut gst::BufferRef,
1029 uuid: &[u8; 16],
1030 data: &[u8],
1031 ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
1032 skip_assert_initialized!();
1033 assert!(!data.is_empty());
1034 unsafe {
1035 let meta = ffi::gst_buffer_add_video_sei_user_data_unregistered_meta(
1036 buffer.as_mut_ptr(),
1037 mut_override(uuid as *const _),
1038 mut_override(data.as_ptr()),
1039 data.len(),
1040 );
1041
1042 Self::from_mut_ptr(buffer, meta)
1043 }
1044 }
1045
1046 #[doc(alias = "get_data")]
1047 #[inline]
1048 pub fn data(&self) -> &[u8] {
1049 if self.0.size == 0 {
1050 return &[];
1051 }
1052 unsafe {
1056 use std::slice;
1057 slice::from_raw_parts(self.0.data, self.0.size)
1058 }
1059 }
1060
1061 #[doc(alias = "get_uuid")]
1062 #[inline]
1063 pub fn uuid(&self) -> [u8; 16] {
1064 self.0.uuid
1065 }
1066}
1067
1068#[cfg(feature = "v1_22")]
1069#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1070impl fmt::Debug for VideoSeiUserDataUnregisteredMeta {
1071 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1072 f.debug_struct("VideoSeiUserDataUnregisteredMeta")
1073 .field(
1074 "uuid",
1075 &format!("0x{:032X}", u128::from_be_bytes(self.uuid())),
1076 )
1077 .field("data", &self.data())
1078 .finish()
1079 }
1080}
1081
1082#[cfg(feature = "v1_22")]
1083#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1084unsafe impl MetaAPI for VideoSeiUserDataUnregisteredMeta {
1085 type GstType = ffi::GstVideoSEIUserDataUnregisteredMeta;
1086
1087 #[doc(alias = "gst_video_sei_user_data_unregistered_meta_api_get_type")]
1088 fn meta_api() -> glib::Type {
1089 unsafe {
1090 glib::translate::from_glib(ffi::gst_video_sei_user_data_unregistered_meta_api_get_type())
1091 }
1092 }
1093}
1094
1095#[cfg(feature = "v1_24")]
1096#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1097#[repr(transparent)]
1098#[doc(alias = "GstAncillaryMeta")]
1099pub struct AncillaryMeta(ffi::GstAncillaryMeta);
1100
1101#[cfg(feature = "v1_24")]
1102#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1103unsafe impl Send for AncillaryMeta {}
1104#[cfg(feature = "v1_24")]
1105#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1106unsafe impl Sync for AncillaryMeta {}
1107
1108#[cfg(feature = "v1_24")]
1109#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1110impl AncillaryMeta {
1111 #[doc(alias = "gst_buffer_add_ancillary_meta")]
1112 pub fn add(buffer: &mut gst::BufferRef) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
1113 skip_assert_initialized!();
1114 unsafe {
1115 let meta = ffi::gst_buffer_add_ancillary_meta(buffer.as_mut_ptr());
1116
1117 Self::from_mut_ptr(buffer, meta)
1118 }
1119 }
1120
1121 #[inline]
1122 pub fn field(&self) -> crate::AncillaryMetaField {
1123 unsafe { from_glib(self.0.field) }
1124 }
1125
1126 #[inline]
1127 pub fn set_field(&mut self, field: crate::AncillaryMetaField) {
1128 self.0.field = field.into_glib();
1129 }
1130
1131 #[inline]
1132 pub fn c_not_y_channel(&self) -> bool {
1133 unsafe { from_glib(self.0.c_not_y_channel) }
1134 }
1135
1136 #[inline]
1137 pub fn set_c_not_y_channel(&mut self, c_not_y_channel: bool) {
1138 self.0.c_not_y_channel = c_not_y_channel.into_glib();
1139 }
1140
1141 #[inline]
1142 pub fn line(&self) -> u16 {
1143 self.0.line
1144 }
1145
1146 #[inline]
1147 pub fn set_line(&mut self, line: u16) {
1148 self.0.line = line;
1149 }
1150
1151 #[inline]
1152 pub fn offset(&self) -> u16 {
1153 self.0.offset
1154 }
1155
1156 #[inline]
1157 pub fn set_offset(&mut self, offset: u16) {
1158 self.0.offset = offset;
1159 }
1160
1161 #[inline]
1162 pub fn did(&self) -> u16 {
1163 self.0.DID
1164 }
1165
1166 #[inline]
1167 pub fn set_did(&mut self, did: u16) {
1168 self.0.DID = did;
1169 }
1170
1171 #[inline]
1172 pub fn sdid_block_number(&self) -> u16 {
1173 self.0.SDID_block_number
1174 }
1175
1176 #[inline]
1177 pub fn set_sdid_block_number(&mut self, sdid_block_number: u16) {
1178 self.0.SDID_block_number = sdid_block_number;
1179 }
1180
1181 #[inline]
1182 pub fn data_count(&self) -> u16 {
1183 self.0.data_count
1184 }
1185
1186 #[inline]
1187 pub fn checksum(&self) -> u16 {
1188 self.0.checksum
1189 }
1190
1191 #[inline]
1192 pub fn set_checksum(&mut self, checksum: u16) {
1193 self.0.checksum = checksum;
1194 }
1195
1196 #[inline]
1197 pub fn data(&self) -> &[u16] {
1198 if self.0.data_count & 0xff == 0 {
1199 return &[];
1200 }
1201 unsafe {
1202 use std::slice;
1203
1204 slice::from_raw_parts(self.0.data, (self.0.data_count & 0xff) as usize)
1205 }
1206 }
1207
1208 #[inline]
1209 pub fn data_mut(&mut self) -> &mut [u16] {
1210 if self.0.data_count & 0xff == 0 {
1211 return &mut [];
1212 }
1213 unsafe {
1214 use std::slice;
1215
1216 slice::from_raw_parts_mut(self.0.data, (self.0.data_count & 0xff) as usize)
1217 }
1218 }
1219
1220 #[inline]
1221 pub fn set_data(&mut self, data: glib::Slice<u16>) {
1222 assert!(data.len() < 256);
1223 self.0.data_count = data.len() as u16;
1224 self.0.data = data.into_glib_ptr();
1225 }
1226
1227 #[inline]
1228 pub fn set_data_count_upper_two_bits(&mut self, upper_two_bits: u8) {
1229 assert!(upper_two_bits & !0x03 == 0);
1230 self.0.data_count = ((upper_two_bits as u16) << 8) | self.0.data_count & 0xff;
1231 }
1232}
1233
1234#[cfg(feature = "v1_24")]
1235#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1236unsafe impl MetaAPI for AncillaryMeta {
1237 type GstType = ffi::GstAncillaryMeta;
1238
1239 #[doc(alias = "gst_ancillary_meta_api_get_type")]
1240 #[inline]
1241 fn meta_api() -> glib::Type {
1242 unsafe { from_glib(ffi::gst_ancillary_meta_api_get_type()) }
1243 }
1244}
1245
1246#[cfg(feature = "v1_24")]
1247#[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1248impl fmt::Debug for AncillaryMeta {
1249 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1250 f.debug_struct("AncillaryMeta")
1251 .field("field", &self.field())
1252 .field("c_not_y_channel", &self.c_not_y_channel())
1253 .field("line", &self.line())
1254 .field("offset", &self.offset())
1255 .field("did", &self.did())
1256 .field("sdid_block_number", &self.sdid_block_number())
1257 .field("data_count", &self.data_count())
1258 .field("data", &self.data())
1259 .field("checksum", &self.checksum())
1260 .finish()
1261 }
1262}
1263
1264pub mod tags {
1265 gst::impl_meta_tag!(Video, crate::ffi::GST_META_TAG_VIDEO_STR);
1266 gst::impl_meta_tag!(Size, crate::ffi::GST_META_TAG_VIDEO_SIZE_STR);
1267 gst::impl_meta_tag!(Orientation, crate::ffi::GST_META_TAG_VIDEO_ORIENTATION_STR);
1268 gst::impl_meta_tag!(Colorspace, crate::ffi::GST_META_TAG_VIDEO_COLORSPACE_STR);
1269}
1270
1271#[repr(transparent)]
1272#[doc(alias = "GstVideoMetaTransform")]
1273pub struct VideoMetaTransformScale(ffi::GstVideoMetaTransform);
1274
1275unsafe impl Sync for VideoMetaTransformScale {}
1276unsafe impl Send for VideoMetaTransformScale {}
1277
1278impl VideoMetaTransformScale {
1279 pub fn new(in_info: &crate::VideoInfo, out_info: &crate::VideoInfo) -> Self {
1280 skip_assert_initialized!();
1281 Self(ffi::GstVideoMetaTransform {
1282 in_info: mut_override(in_info.to_glib_none().0),
1283 out_info: mut_override(out_info.to_glib_none().0),
1284 })
1285 }
1286
1287 pub fn in_info(&self) -> &crate::VideoInfo {
1288 unsafe { &*(self.0.in_info as *const crate::VideoInfo) }
1289 }
1290
1291 pub fn out_info(&self) -> &crate::VideoInfo {
1292 unsafe { &*(self.0.out_info as *const crate::VideoInfo) }
1293 }
1294}
1295
1296unsafe impl gst::meta::MetaTransform for VideoMetaTransformScale {
1297 type GLibType = ffi::GstVideoMetaTransform;
1298
1299 #[doc(alias = "gst_video_meta_transform_scale_get_quark")]
1300 fn quark() -> glib::Quark {
1301 unsafe { from_glib(ffi::gst_video_meta_transform_scale_get_quark()) }
1302 }
1303
1304 fn as_ptr(&self) -> *const ffi::GstVideoMetaTransform {
1305 &self.0
1306 }
1307}
1308
1309#[cfg(feature = "v1_28")]
1310#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
1311mod video_meta_transform_matrix {
1312 use super::*;
1313
1314 use std::mem;
1315
1316 #[repr(transparent)]
1317 #[doc(alias = "GstVideoMetaTransformMatrix")]
1318 pub struct VideoMetaTransformMatrix(ffi::GstVideoMetaTransformMatrix);
1319
1320 unsafe impl Sync for VideoMetaTransformMatrix {}
1321 unsafe impl Send for VideoMetaTransformMatrix {}
1322
1323 impl VideoMetaTransformMatrix {
1324 #[doc(alias = "gst_video_meta_transform_matrix_init")]
1325 pub fn new(
1326 in_info: &crate::VideoInfo,
1327 in_rectangle: &crate::VideoRectangle,
1328 out_info: &crate::VideoInfo,
1329 out_rectangle: &crate::VideoRectangle,
1330 ) -> Self {
1331 skip_assert_initialized!();
1332
1333 unsafe {
1334 let mut trans = mem::MaybeUninit::uninit();
1335
1336 ffi::gst_video_meta_transform_matrix_init(
1337 trans.as_mut_ptr(),
1338 in_info.to_glib_none().0,
1339 in_rectangle.to_glib_none().0,
1340 out_info.to_glib_none().0,
1341 out_rectangle.to_glib_none().0,
1342 );
1343
1344 Self(trans.assume_init())
1345 }
1346 }
1347
1348 pub fn in_info(&self) -> &crate::VideoInfo {
1349 unsafe { &*(self.0.in_info as *const crate::VideoInfo) }
1350 }
1351
1352 pub fn in_rectangle(&self) -> &crate::VideoRectangle {
1353 unsafe { &*(&self.0.in_rectangle as *const _ as *const crate::VideoRectangle) }
1354 }
1355
1356 pub fn out_info(&self) -> &crate::VideoInfo {
1357 unsafe { &*(self.0.out_info as *const crate::VideoInfo) }
1358 }
1359
1360 pub fn out_rectangle(&self) -> &crate::VideoRectangle {
1361 unsafe { &*(&self.0.out_rectangle as *const _ as *const crate::VideoRectangle) }
1362 }
1363
1364 #[doc(alias = "gst_video_meta_transform_matrix_point")]
1365 pub fn point(&self, x: i32, y: i32) -> Option<(i32, i32)> {
1366 unsafe {
1367 let mut x = x;
1368 let mut y = y;
1369 let res = from_glib(ffi::gst_video_meta_transform_matrix_point(
1370 &self.0, &mut x, &mut y,
1371 ));
1372 if res { Some((x, y)) } else { None }
1373 }
1374 }
1375
1376 #[doc(alias = "gst_video_meta_transform_matrix_point_clipped")]
1377 pub fn point_clipped(&self, x: i32, y: i32) -> Option<(i32, i32)> {
1378 unsafe {
1379 let mut x = x;
1380 let mut y = y;
1381 let res = from_glib(ffi::gst_video_meta_transform_matrix_point_clipped(
1382 &self.0, &mut x, &mut y,
1383 ));
1384 if res { Some((x, y)) } else { None }
1385 }
1386 }
1387
1388 #[doc(alias = "gst_video_meta_transform_matrix_rectangle")]
1389 pub fn rectangle(
1390 &self,
1391 rectangle: &crate::VideoRectangle,
1392 ) -> Option<crate::VideoRectangle> {
1393 unsafe {
1394 let mut rectangle = rectangle.clone();
1395 let res = from_glib(ffi::gst_video_meta_transform_matrix_rectangle(
1396 &self.0,
1397 rectangle.to_glib_none_mut().0,
1398 ));
1399 if res { Some(rectangle) } else { None }
1400 }
1401 }
1402
1403 #[doc(alias = "gst_video_meta_transform_matrix_rectangle_clipped")]
1404 pub fn rectangle_clipped(
1405 &self,
1406 rectangle: &crate::VideoRectangle,
1407 ) -> Option<crate::VideoRectangle> {
1408 unsafe {
1409 let mut rectangle = rectangle.clone();
1410 let res = from_glib(ffi::gst_video_meta_transform_matrix_rectangle_clipped(
1411 &self.0,
1412 rectangle.to_glib_none_mut().0,
1413 ));
1414 if res { Some(rectangle) } else { None }
1415 }
1416 }
1417 }
1418
1419 unsafe impl gst::meta::MetaTransform for VideoMetaTransformMatrix {
1420 type GLibType = ffi::GstVideoMetaTransformMatrix;
1421
1422 #[doc(alias = "gst_video_meta_transform_matrix_get_quark")]
1423 fn quark() -> glib::Quark {
1424 unsafe { from_glib(ffi::gst_video_meta_transform_matrix_get_quark()) }
1425 }
1426
1427 fn as_ptr(&self) -> *const ffi::GstVideoMetaTransformMatrix {
1428 &self.0
1429 }
1430 }
1431}
1432
1433#[cfg(feature = "v1_28")]
1434#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
1435pub use video_meta_transform_matrix::*;
1436
1437#[cfg(test)]
1438mod tests {
1439 use super::*;
1440
1441 #[test]
1442 fn test_add_get_meta() {
1443 gst::init().unwrap();
1444
1445 let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
1446 {
1447 let meta = VideoMeta::add(
1448 buffer.get_mut().unwrap(),
1449 crate::VideoFrameFlags::empty(),
1450 crate::VideoFormat::Argb,
1451 320,
1452 240,
1453 )
1454 .unwrap();
1455 assert_eq!(meta.id(), 0);
1456 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
1457 assert_eq!(meta.format(), crate::VideoFormat::Argb);
1458 assert_eq!(meta.width(), 320);
1459 assert_eq!(meta.height(), 240);
1460 assert_eq!(meta.n_planes(), 1);
1461 assert_eq!(meta.offset(), &[0]);
1462 assert_eq!(meta.stride(), &[320 * 4]);
1463 assert!(meta.has_tag::<gst::meta::tags::Memory>());
1464 assert!(meta.has_tag::<tags::Video>());
1465 assert!(meta.has_tag::<tags::Colorspace>());
1466 assert!(meta.has_tag::<tags::Size>());
1467 }
1468
1469 {
1470 let meta = buffer.meta::<VideoMeta>().unwrap();
1471 assert_eq!(meta.id(), 0);
1472 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
1473 assert_eq!(meta.format(), crate::VideoFormat::Argb);
1474 assert_eq!(meta.width(), 320);
1475 assert_eq!(meta.height(), 240);
1476 assert_eq!(meta.n_planes(), 1);
1477 assert_eq!(meta.offset(), &[0]);
1478 assert_eq!(meta.stride(), &[320 * 4]);
1479 }
1480 }
1481
1482 #[test]
1483 fn test_add_full_get_meta() {
1484 gst::init().unwrap();
1485
1486 let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
1487 {
1488 let meta = VideoMeta::add_full(
1489 buffer.get_mut().unwrap(),
1490 crate::VideoFrameFlags::empty(),
1491 crate::VideoFormat::Argb,
1492 320,
1493 240,
1494 &[0],
1495 &[320 * 4],
1496 )
1497 .unwrap();
1498 assert_eq!(meta.id(), 0);
1499 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
1500 assert_eq!(meta.format(), crate::VideoFormat::Argb);
1501 assert_eq!(meta.width(), 320);
1502 assert_eq!(meta.height(), 240);
1503 assert_eq!(meta.n_planes(), 1);
1504 assert_eq!(meta.offset(), &[0]);
1505 assert_eq!(meta.stride(), &[320 * 4]);
1506 }
1507
1508 {
1509 let meta = buffer.meta::<VideoMeta>().unwrap();
1510 assert_eq!(meta.id(), 0);
1511 assert_eq!(meta.video_frame_flags(), crate::VideoFrameFlags::empty());
1512 assert_eq!(meta.format(), crate::VideoFormat::Argb);
1513 assert_eq!(meta.width(), 320);
1514 assert_eq!(meta.height(), 240);
1515 assert_eq!(meta.n_planes(), 1);
1516 assert_eq!(meta.offset(), &[0]);
1517 assert_eq!(meta.stride(), &[320 * 4]);
1518 }
1519 }
1520
1521 #[test]
1522 #[cfg(feature = "v1_16")]
1523 fn test_add_full_alternate_interlacing() {
1524 gst::init().unwrap();
1525 let mut buffer = gst::Buffer::with_size(320 * 120 * 4).unwrap();
1526 VideoMeta::add_full(
1527 buffer.get_mut().unwrap(),
1528 crate::VideoFrameFlags::TOP_FIELD,
1529 crate::VideoFormat::Argb,
1530 320,
1531 240,
1532 &[0],
1533 &[320 * 4],
1534 )
1535 .unwrap();
1536 }
1537
1538 #[test]
1539 #[cfg(feature = "v1_18")]
1540 fn test_video_meta_alignment() {
1541 gst::init().unwrap();
1542
1543 let mut buffer = gst::Buffer::with_size(115200).unwrap();
1544 let meta = VideoMeta::add(
1545 buffer.get_mut().unwrap(),
1546 crate::VideoFrameFlags::empty(),
1547 crate::VideoFormat::Nv12,
1548 320,
1549 240,
1550 )
1551 .unwrap();
1552
1553 let alig = meta.alignment();
1554 assert_eq!(alig, crate::VideoAlignment::new(0, 0, 0, 0, &[0, 0, 0, 0]));
1555
1556 assert_eq!(meta.plane_size().unwrap(), [76800, 38400, 0, 0]);
1557 assert_eq!(meta.plane_height().unwrap(), [240, 120, 0, 0]);
1558
1559 let mut info = crate::VideoInfo::builder(crate::VideoFormat::Nv12, 320, 240)
1561 .build()
1562 .expect("Failed to create VideoInfo");
1563 let mut alig = crate::VideoAlignment::new(0, 0, 2, 6, &[0, 0, 0, 0]);
1564 info.align(&mut alig).unwrap();
1565
1566 let mut meta = VideoMeta::add_full(
1567 buffer.get_mut().unwrap(),
1568 crate::VideoFrameFlags::empty(),
1569 crate::VideoFormat::Nv12,
1570 info.width(),
1571 info.height(),
1572 info.offset(),
1573 info.stride(),
1574 )
1575 .unwrap();
1576 meta.set_alignment(&alig).unwrap();
1577
1578 let alig = meta.alignment();
1579 assert_eq!(alig, crate::VideoAlignment::new(0, 0, 2, 6, &[0, 0, 0, 0]));
1580
1581 assert_eq!(meta.plane_size().unwrap(), [78720, 39360, 0, 0]);
1582 assert_eq!(meta.plane_height().unwrap(), [240, 120, 0, 0]);
1583
1584 let mut info = crate::VideoInfo::builder(crate::VideoFormat::Nv12, 320, 240)
1586 .build()
1587 .expect("Failed to create VideoInfo");
1588 let mut alig = crate::VideoAlignment::new(2, 6, 0, 0, &[0, 0, 0, 0]);
1589 info.align(&mut alig).unwrap();
1590
1591 let mut meta = VideoMeta::add_full(
1592 buffer.get_mut().unwrap(),
1593 crate::VideoFrameFlags::empty(),
1594 crate::VideoFormat::Nv12,
1595 info.width(),
1596 info.height(),
1597 info.offset(),
1598 info.stride(),
1599 )
1600 .unwrap();
1601 meta.set_alignment(&alig).unwrap();
1602
1603 let alig = meta.alignment();
1604 assert_eq!(alig, crate::VideoAlignment::new(2, 6, 0, 0, &[0, 0, 0, 0]));
1605
1606 assert_eq!(meta.plane_size().unwrap(), [79360, 39680, 0, 0]);
1607 assert_eq!(meta.plane_height().unwrap(), [248, 124, 0, 0]);
1608 }
1609
1610 #[test]
1611 #[cfg(feature = "v1_22")]
1612 fn test_get_video_sei_user_data_unregistered_meta() {
1613 gst::init().unwrap();
1614
1615 const META_UUID: &[u8; 16] = &[
1616 0x4D, 0x49, 0x53, 0x50, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x74, 0x69,
1617 0x6D, 0x65,
1618 ];
1619
1620 const META_DATA: &[u8] = &[
1621 0x1f, 0x00, 0x05, 0xff, 0x21, 0x7e, 0xff, 0x29, 0xb5, 0xff, 0xdc, 0x13,
1622 ];
1623
1624 let buffer_data = &[
1625 &[0x00, 0x00, 0x00, 0x20, 0x06, 0x05, 0x1c],
1626 META_UUID as &[u8],
1627 META_DATA,
1628 &[
1629 0x80, 0x00, 0x00, 0x00, 0x14, 0x65, 0x88, 0x84, 0x00, 0x10, 0xff, 0xfe, 0xf6, 0xf0,
1630 0xfe, 0x05, 0x36, 0x56, 0x04, 0x50, 0x96, 0x7b, 0x3f, 0x53, 0xe1,
1631 ],
1632 ]
1633 .concat();
1634
1635 let mut harness = gst_check::Harness::new("h264parse");
1636 harness.set_src_caps_str(r#"
1637 video/x-h264, stream-format=(string)avc,
1638 width=(int)1920, height=(int)1080, framerate=(fraction)25/1,
1639 bit-depth-chroma=(uint)8, parsed=(boolean)true,
1640 alignment=(string)au, profile=(string)high, level=(string)4,
1641 codec_data=(buffer)01640028ffe1001a67640028acb200f0044fcb080000030008000003019478c1924001000568ebccb22c
1642 "#);
1643 let buffer = gst::Buffer::from_slice(buffer_data.clone());
1644 let buffer = harness.push_and_pull(buffer).unwrap();
1645
1646 let meta = buffer.meta::<VideoSeiUserDataUnregisteredMeta>().unwrap();
1647 assert_eq!(meta.uuid(), *META_UUID);
1648 assert_eq!(meta.data(), META_DATA);
1649 assert_eq!(meta.data().len(), META_DATA.len());
1650 }
1651
1652 #[test]
1653 fn test_meta_video_transform() {
1654 gst::init().unwrap();
1655
1656 let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
1657 let meta = VideoCropMeta::add(buffer.get_mut().unwrap(), (10, 10, 20, 20));
1658
1659 let mut buffer2 = gst::Buffer::with_size(640 * 480 * 4).unwrap();
1660
1661 let in_video_info = crate::VideoInfo::builder(crate::VideoFormat::Rgba, 320, 240)
1662 .build()
1663 .unwrap();
1664 let out_video_info = crate::VideoInfo::builder(crate::VideoFormat::Rgba, 640, 480)
1665 .build()
1666 .unwrap();
1667
1668 meta.transform(
1669 buffer2.get_mut().unwrap(),
1670 &VideoMetaTransformScale::new(&in_video_info, &out_video_info),
1671 )
1672 .unwrap();
1673
1674 let meta2 = buffer2.meta::<VideoCropMeta>().unwrap();
1675
1676 assert_eq!(meta2.rect(), (20, 20, 40, 40));
1677 }
1678}