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