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