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