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