1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use std::fmt;
4 use std::ptr;
5 
6 use glib::translate::{from_glib, from_glib_none, FromGlib, IntoGlib, ToGlibPtr};
7 use gst::prelude::*;
8 
9 #[repr(transparent)]
10 #[doc(alias = "GstVideoMeta")]
11 pub struct VideoMeta(ffi::GstVideoMeta);
12 
13 unsafe impl Send for VideoMeta {}
14 unsafe impl Sync for VideoMeta {}
15 
16 impl VideoMeta {
17     #[doc(alias = "gst_buffer_add_video_meta")]
add( buffer: &mut gst::BufferRef, flags: crate::VideoFrameFlags, format: crate::VideoFormat, width: u32, height: u32, ) -> Result<gst::MetaRefMut<Self, gst::meta::Standalone>, glib::BoolError>18     pub fn add(
19         buffer: &mut gst::BufferRef,
20         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                 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 
add_full<'a>( buffer: &'a mut gst::BufferRef, flags: crate::VideoFrameFlags, format: crate::VideoFormat, width: u32, height: u32, offset: &[usize], stride: &[i32], ) -> Result<gst::MetaRefMut<'a, Self, gst::meta::Standalone>, glib::BoolError>62     pub fn add_full<'a>(
63         buffer: &'a mut gst::BufferRef,
64         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 n_planes = offset.len() as u32;
78         let info = crate::VideoInfo::builder(format, width, height)
79             .offset(offset)
80             .stride(stride)
81             .build()?;
82 
83         if !info.is_valid() {
84             return Err(glib::bool_error!("Invalid video info"));
85         }
86 
87         if buffer.size() < info.size() {
88             return Err(glib::bool_error!(
89                 "Buffer smaller than required frame size ({} < {})",
90                 buffer.size(),
91                 info.size()
92             ));
93         }
94 
95         unsafe {
96             let meta = ffi::gst_buffer_add_video_meta_full(
97                 buffer.as_mut_ptr(),
98                 flags.into_glib(),
99                 format.into_glib(),
100                 width,
101                 height,
102                 n_planes,
103                 offset.as_ptr() as *mut _,
104                 stride.as_ptr() as *mut _,
105             );
106 
107             if meta.is_null() {
108                 return Err(glib::bool_error!("Failed to add video meta"));
109             }
110 
111             Ok(Self::from_mut_ptr(buffer, meta))
112         }
113     }
114 
115     #[doc(alias = "get_flags")]
flags(&self) -> crate::VideoFrameFlags116     pub fn flags(&self) -> crate::VideoFrameFlags {
117         unsafe { from_glib(self.0.flags) }
118     }
119 
120     #[doc(alias = "get_format")]
format(&self) -> crate::VideoFormat121     pub fn format(&self) -> crate::VideoFormat {
122         unsafe { from_glib(self.0.format) }
123     }
124 
125     #[doc(alias = "get_id")]
id(&self) -> i32126     pub fn id(&self) -> i32 {
127         self.0.id
128     }
129 
130     #[doc(alias = "get_width")]
width(&self) -> u32131     pub fn width(&self) -> u32 {
132         self.0.width
133     }
134 
135     #[doc(alias = "get_height")]
height(&self) -> u32136     pub fn height(&self) -> u32 {
137         self.0.height
138     }
139 
140     #[doc(alias = "get_n_planes")]
n_planes(&self) -> u32141     pub fn n_planes(&self) -> u32 {
142         self.0.n_planes
143     }
144 
145     #[doc(alias = "get_offset")]
offset(&self) -> &[usize]146     pub fn offset(&self) -> &[usize] {
147         &self.0.offset[0..(self.0.n_planes as usize)]
148     }
149 
150     #[doc(alias = "get_stride")]
stride(&self) -> &[i32]151     pub fn stride(&self) -> &[i32] {
152         &self.0.stride[0..(self.0.n_planes as usize)]
153     }
154 
155     #[cfg(any(feature = "v1_18", feature = "dox"))]
156     #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
157     #[doc(alias = "get_alignment")]
alignment(&self) -> crate::VideoAlignment158     pub fn alignment(&self) -> crate::VideoAlignment {
159         crate::VideoAlignment::new(
160             self.0.alignment.padding_top,
161             self.0.alignment.padding_bottom,
162             self.0.alignment.padding_left,
163             self.0.alignment.padding_right,
164             &self.0.alignment.stride_align,
165         )
166     }
167 
168     #[cfg(any(feature = "v1_18", feature = "dox"))]
169     #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
170     #[doc(alias = "get_plane_size")]
171     #[doc(alias = "gst_video_meta_get_plane_size")]
plane_size(&self) -> Result<[usize; crate::VIDEO_MAX_PLANES], glib::BoolError>172     pub fn plane_size(&self) -> Result<[usize; crate::VIDEO_MAX_PLANES], glib::BoolError> {
173         let mut plane_size = [0; crate::VIDEO_MAX_PLANES];
174 
175         unsafe {
176             glib::result_from_gboolean!(
177                 ffi::gst_video_meta_get_plane_size(
178                     &self.0 as *const _ as usize as *mut _,
179                     &mut plane_size,
180                 ),
181                 "Failed to get plane size"
182             )?;
183         }
184 
185         Ok(plane_size)
186     }
187 
188     #[cfg(any(feature = "v1_18", feature = "dox"))]
189     #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
190     #[doc(alias = "get_plane_height")]
191     #[doc(alias = "gst_video_meta_get_plane_height")]
plane_height(&self) -> Result<[u32; crate::VIDEO_MAX_PLANES], glib::BoolError>192     pub fn plane_height(&self) -> Result<[u32; crate::VIDEO_MAX_PLANES], glib::BoolError> {
193         let mut plane_height = [0; crate::VIDEO_MAX_PLANES];
194 
195         unsafe {
196             glib::result_from_gboolean!(
197                 ffi::gst_video_meta_get_plane_height(
198                     &self.0 as *const _ as usize as *mut _,
199                     &mut plane_height,
200                 ),
201                 "Failed to get plane height"
202             )?;
203         }
204 
205         Ok(plane_height)
206     }
207 
208     #[cfg(any(feature = "v1_18", feature = "dox"))]
209     #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
210     #[doc(alias = "gst_video_meta_set_alignment")]
set_alignment( &mut self, alignment: &crate::VideoAlignment, ) -> Result<(), glib::BoolError>211     pub fn set_alignment(
212         &mut self,
213         alignment: &crate::VideoAlignment,
214     ) -> Result<(), glib::BoolError> {
215         unsafe {
216             glib::result_from_gboolean!(
217                 ffi::gst_video_meta_set_alignment(&mut self.0, alignment.0),
218                 "Failed to set alignment on VideoMeta"
219             )
220         }
221     }
222 }
223 
224 unsafe impl MetaAPI for VideoMeta {
225     type GstType = ffi::GstVideoMeta;
226 
227     #[doc(alias = "gst_video_meta_api_get_type")]
meta_api() -> glib::Type228     fn meta_api() -> glib::Type {
229         unsafe { from_glib(ffi::gst_video_meta_api_get_type()) }
230     }
231 }
232 
233 impl fmt::Debug for VideoMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result234     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
235         f.debug_struct("VideoMeta")
236             .field("id", &self.id())
237             .field("flags", &self.flags())
238             .field("format", &self.format())
239             .field("width", &self.width())
240             .field("height", &self.height())
241             .field("n_planes", &self.n_planes())
242             .field("offset", &self.offset())
243             .field("stride", &self.stride())
244             .finish()
245     }
246 }
247 
248 #[repr(transparent)]
249 #[doc(alias = "GstVideoCropMeta")]
250 pub struct VideoCropMeta(ffi::GstVideoCropMeta);
251 
252 unsafe impl Send for VideoCropMeta {}
253 unsafe impl Sync for VideoCropMeta {}
254 
255 impl VideoCropMeta {
256     #[doc(alias = "gst_buffer_add_meta")]
add( buffer: &mut gst::BufferRef, rect: (u32, u32, u32, u32), ) -> gst::MetaRefMut<Self, gst::meta::Standalone>257     pub fn add(
258         buffer: &mut gst::BufferRef,
259         rect: (u32, u32, u32, u32),
260     ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
261         skip_assert_initialized!();
262         unsafe {
263             let meta = gst::ffi::gst_buffer_add_meta(
264                 buffer.as_mut_ptr(),
265                 ffi::gst_video_crop_meta_get_info(),
266                 ptr::null_mut(),
267             ) as *mut ffi::GstVideoCropMeta;
268 
269             {
270                 let meta = &mut *meta;
271                 meta.x = rect.0;
272                 meta.y = rect.1;
273                 meta.width = rect.2;
274                 meta.height = rect.3;
275             }
276 
277             Self::from_mut_ptr(buffer, meta)
278         }
279     }
280 
281     #[doc(alias = "get_rect")]
rect(&self) -> (u32, u32, u32, u32)282     pub fn rect(&self) -> (u32, u32, u32, u32) {
283         (self.0.x, self.0.y, self.0.width, self.0.height)
284     }
285 
set_rect(&mut self, rect: (u32, u32, u32, u32))286     pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) {
287         self.0.x = rect.0;
288         self.0.y = rect.1;
289         self.0.width = rect.2;
290         self.0.height = rect.3;
291     }
292 }
293 
294 unsafe impl MetaAPI for VideoCropMeta {
295     type GstType = ffi::GstVideoCropMeta;
296 
297     #[doc(alias = "gst_video_crop_meta_api_get_type")]
meta_api() -> glib::Type298     fn meta_api() -> glib::Type {
299         unsafe { from_glib(ffi::gst_video_crop_meta_api_get_type()) }
300     }
301 }
302 
303 impl fmt::Debug for VideoCropMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result304     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
305         f.debug_struct("VideoCropMeta")
306             .field("rect", &self.rect())
307             .finish()
308     }
309 }
310 
311 #[repr(transparent)]
312 #[doc(alias = "GstVideoRegionOfInterestMeta")]
313 pub struct VideoRegionOfInterestMeta(ffi::GstVideoRegionOfInterestMeta);
314 
315 unsafe impl Send for VideoRegionOfInterestMeta {}
316 unsafe impl Sync for VideoRegionOfInterestMeta {}
317 
318 impl VideoRegionOfInterestMeta {
319     #[doc(alias = "gst_buffer_add_video_region_of_interest_meta")]
add<'a>( buffer: &'a mut gst::BufferRef, roi_type: &str, rect: (u32, u32, u32, u32), ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone>320     pub fn add<'a>(
321         buffer: &'a mut gst::BufferRef,
322         roi_type: &str,
323         rect: (u32, u32, u32, u32),
324     ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
325         skip_assert_initialized!();
326         unsafe {
327             let meta = ffi::gst_buffer_add_video_region_of_interest_meta(
328                 buffer.as_mut_ptr(),
329                 roi_type.to_glib_none().0,
330                 rect.0,
331                 rect.1,
332                 rect.2,
333                 rect.3,
334             );
335 
336             Self::from_mut_ptr(buffer, meta)
337         }
338     }
339 
340     #[doc(alias = "get_rect")]
rect(&self) -> (u32, u32, u32, u32)341     pub fn rect(&self) -> (u32, u32, u32, u32) {
342         (self.0.x, self.0.y, self.0.w, self.0.h)
343     }
344 
345     #[doc(alias = "get_id")]
id(&self) -> i32346     pub fn id(&self) -> i32 {
347         self.0.id
348     }
349 
350     #[doc(alias = "get_parent_id")]
parent_id(&self) -> i32351     pub fn parent_id(&self) -> i32 {
352         self.0.parent_id
353     }
354 
355     #[doc(alias = "get_roi_type")]
roi_type<'a>(&self) -> &'a str356     pub fn roi_type<'a>(&self) -> &'a str {
357         unsafe { glib::Quark::from_glib(self.0.roi_type).to_string() }
358     }
359 
360     #[cfg(feature = "v1_14")]
361     #[doc(alias = "get_params")]
params(&self) -> ParamsIter362     pub fn params(&self) -> ParamsIter {
363         ParamsIter {
364             _meta: self,
365             list: self.0.params,
366         }
367     }
368 
369     #[cfg(feature = "v1_14")]
370     #[doc(alias = "get_param")]
param<'b>(&self, name: &'b str) -> Option<&gst::StructureRef>371     pub fn param<'b>(&self, name: &'b str) -> Option<&gst::StructureRef> {
372         self.params().find(|s| s.name() == name)
373     }
374 
set_rect(&mut self, rect: (u32, u32, u32, u32))375     pub fn set_rect(&mut self, rect: (u32, u32, u32, u32)) {
376         self.0.x = rect.0;
377         self.0.y = rect.1;
378         self.0.w = rect.2;
379         self.0.h = rect.3;
380     }
381 
set_id(&mut self, id: i32)382     pub fn set_id(&mut self, id: i32) {
383         self.0.id = id
384     }
385 
set_parent_id(&mut self, id: i32)386     pub fn set_parent_id(&mut self, id: i32) {
387         self.0.parent_id = id
388     }
389 
390     #[cfg(feature = "v1_14")]
391     #[doc(alias = "gst_video_region_of_interest_meta_add_param")]
add_param(&mut self, s: gst::Structure)392     pub fn add_param(&mut self, s: gst::Structure) {
393         unsafe {
394             ffi::gst_video_region_of_interest_meta_add_param(&mut self.0, s.into_ptr());
395         }
396     }
397 }
398 
399 #[cfg(feature = "v1_14")]
400 pub struct ParamsIter<'a> {
401     _meta: &'a VideoRegionOfInterestMeta,
402     list: *const glib::ffi::GList,
403 }
404 
405 #[cfg(feature = "v1_14")]
406 impl<'a> Iterator for ParamsIter<'a> {
407     type Item = &'a gst::StructureRef;
408 
next(&mut self) -> Option<&'a gst::StructureRef>409     fn next(&mut self) -> Option<&'a gst::StructureRef> {
410         if self.list.is_null() {
411             return None;
412         }
413 
414         unsafe {
415             let data = (*self.list).data;
416             assert!(!data.is_null());
417             self.list = (*self.list).next;
418 
419             let s = gst::StructureRef::from_glib_borrow(data as *const gst::ffi::GstStructure);
420 
421             Some(s)
422         }
423     }
424 }
425 
426 unsafe impl MetaAPI for VideoRegionOfInterestMeta {
427     type GstType = ffi::GstVideoRegionOfInterestMeta;
428 
429     #[doc(alias = "gst_video_region_of_interest_meta_api_get_type")]
meta_api() -> glib::Type430     fn meta_api() -> glib::Type {
431         unsafe { from_glib(ffi::gst_video_region_of_interest_meta_api_get_type()) }
432     }
433 }
434 
435 impl fmt::Debug for VideoRegionOfInterestMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result436     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
437         let mut f = f.debug_struct("VideoRegionOfInterestMeta");
438 
439         f.field("roi_type", &self.roi_type())
440             .field("rect", &self.rect())
441             .field("id", &self.id())
442             .field("parent_id", &self.parent_id());
443 
444         #[cfg(feature = "v1_14")]
445         {
446             f.field("params", &self.params().collect::<Vec<_>>());
447         }
448 
449         f.finish()
450     }
451 }
452 
453 #[repr(transparent)]
454 #[doc(alias = "GstVideoAffineTransformationMeta")]
455 pub struct VideoAffineTransformationMeta(ffi::GstVideoAffineTransformationMeta);
456 
457 unsafe impl Send for VideoAffineTransformationMeta {}
458 unsafe impl Sync for VideoAffineTransformationMeta {}
459 
460 impl VideoAffineTransformationMeta {
461     #[doc(alias = "gst_buffer_add_meta")]
add<'a>( buffer: &'a mut gst::BufferRef, matrix: Option<&[f32; 16]>, ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone>462     pub fn add<'a>(
463         buffer: &'a mut gst::BufferRef,
464         matrix: Option<&[f32; 16]>,
465     ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
466         skip_assert_initialized!();
467         unsafe {
468             let meta = gst::ffi::gst_buffer_add_meta(
469                 buffer.as_mut_ptr(),
470                 ffi::gst_video_affine_transformation_meta_get_info(),
471                 ptr::null_mut(),
472             ) as *mut ffi::GstVideoAffineTransformationMeta;
473 
474             if let Some(matrix) = matrix {
475                 let meta = &mut *meta;
476                 meta.matrix.copy_from_slice(matrix);
477             }
478 
479             Self::from_mut_ptr(buffer, meta)
480         }
481     }
482 
483     #[doc(alias = "get_matrix")]
matrix(&self) -> &[f32; 16]484     pub fn matrix(&self) -> &[f32; 16] {
485         &self.0.matrix
486     }
487 
set_matrix(&mut self, matrix: &[f32; 16])488     pub fn set_matrix(&mut self, matrix: &[f32; 16]) {
489         self.0.matrix.copy_from_slice(matrix);
490     }
491 
492     #[doc(alias = "gst_video_affine_transformation_meta_apply_matrix")]
apply_matrix(&mut self, matrix: &[f32; 16])493     pub fn apply_matrix(&mut self, matrix: &[f32; 16]) {
494         unsafe {
495             ffi::gst_video_affine_transformation_meta_apply_matrix(&mut self.0, matrix);
496         }
497     }
498 }
499 
500 unsafe impl MetaAPI for VideoAffineTransformationMeta {
501     type GstType = ffi::GstVideoAffineTransformationMeta;
502 
503     #[doc(alias = "gst_video_affine_transformation_meta_api_get_type")]
meta_api() -> glib::Type504     fn meta_api() -> glib::Type {
505         unsafe { from_glib(ffi::gst_video_affine_transformation_meta_api_get_type()) }
506     }
507 }
508 
509 impl fmt::Debug for VideoAffineTransformationMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result510     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
511         f.debug_struct("VideoAffineTransformationMeta")
512             .field("matrix", &self.matrix())
513             .finish()
514     }
515 }
516 
517 #[repr(transparent)]
518 #[doc(alias = "GstVideoOverlayCompositionMeta")]
519 pub struct VideoOverlayCompositionMeta(ffi::GstVideoOverlayCompositionMeta);
520 
521 unsafe impl Send for VideoOverlayCompositionMeta {}
522 unsafe impl Sync for VideoOverlayCompositionMeta {}
523 
524 impl VideoOverlayCompositionMeta {
525     #[doc(alias = "gst_buffer_add_video_overlay_composition_meta")]
add<'a>( buffer: &'a mut gst::BufferRef, overlay: &crate::VideoOverlayComposition, ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone>526     pub fn add<'a>(
527         buffer: &'a mut gst::BufferRef,
528         overlay: &crate::VideoOverlayComposition,
529     ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
530         skip_assert_initialized!();
531         unsafe {
532             let meta = ffi::gst_buffer_add_video_overlay_composition_meta(
533                 buffer.as_mut_ptr(),
534                 overlay.as_mut_ptr(),
535             );
536 
537             Self::from_mut_ptr(buffer, meta)
538         }
539     }
540 
541     #[doc(alias = "get_overlay")]
overlay(&self) -> &crate::VideoOverlayCompositionRef542     pub fn overlay(&self) -> &crate::VideoOverlayCompositionRef {
543         unsafe { crate::VideoOverlayCompositionRef::from_ptr(self.0.overlay) }
544     }
545 
546     #[doc(alias = "get_overlay_owned")]
overlay_owned(&self) -> crate::VideoOverlayComposition547     pub fn overlay_owned(&self) -> crate::VideoOverlayComposition {
548         unsafe { from_glib_none(self.overlay().as_ptr()) }
549     }
550 
set_overlay(&mut self, overlay: &crate::VideoOverlayComposition)551     pub fn set_overlay(&mut self, overlay: &crate::VideoOverlayComposition) {
552         #![allow(clippy::cast_ptr_alignment)]
553         unsafe {
554             gst::ffi::gst_mini_object_unref(self.0.overlay as *mut _);
555             self.0.overlay =
556                 gst::ffi::gst_mini_object_ref(overlay.as_mut_ptr() as *mut _) as *mut _;
557         }
558     }
559 }
560 
561 unsafe impl MetaAPI for VideoOverlayCompositionMeta {
562     type GstType = ffi::GstVideoOverlayCompositionMeta;
563 
564     #[doc(alias = "gst_video_overlay_composition_meta_api_get_type")]
meta_api() -> glib::Type565     fn meta_api() -> glib::Type {
566         unsafe { from_glib(ffi::gst_video_overlay_composition_meta_api_get_type()) }
567     }
568 }
569 
570 impl fmt::Debug for VideoOverlayCompositionMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result571     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
572         f.debug_struct("VideoOverlayCompositionMeta")
573             .field("overlay", &self.overlay())
574             .finish()
575     }
576 }
577 
578 #[cfg(any(feature = "v1_16", feature = "dox"))]
579 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
580 #[repr(transparent)]
581 #[doc(alias = "GstVideoCaptionMeta")]
582 pub struct VideoCaptionMeta(ffi::GstVideoCaptionMeta);
583 
584 #[cfg(any(feature = "v1_16", feature = "dox"))]
585 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
586 unsafe impl Send for VideoCaptionMeta {}
587 #[cfg(any(feature = "v1_16", feature = "dox"))]
588 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
589 unsafe impl Sync for VideoCaptionMeta {}
590 
591 #[cfg(any(feature = "v1_16", feature = "dox"))]
592 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
593 impl VideoCaptionMeta {
594     #[doc(alias = "gst_buffer_add_video_caption_meta")]
add<'a>( buffer: &'a mut gst::BufferRef, caption_type: crate::VideoCaptionType, data: &[u8], ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone>595     pub fn add<'a>(
596         buffer: &'a mut gst::BufferRef,
597         caption_type: crate::VideoCaptionType,
598         data: &[u8],
599     ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
600         skip_assert_initialized!();
601         assert!(!data.is_empty());
602         unsafe {
603             let meta = ffi::gst_buffer_add_video_caption_meta(
604                 buffer.as_mut_ptr(),
605                 caption_type.into_glib(),
606                 data.as_ptr(),
607                 data.len(),
608             );
609 
610             Self::from_mut_ptr(buffer, meta)
611         }
612     }
613 
614     #[doc(alias = "get_caption_type")]
caption_type(&self) -> crate::VideoCaptionType615     pub fn caption_type(&self) -> crate::VideoCaptionType {
616         unsafe { from_glib(self.0.caption_type) }
617     }
618 
619     #[doc(alias = "get_data")]
data(&self) -> &[u8]620     pub fn data(&self) -> &[u8] {
621         unsafe {
622             use std::slice;
623 
624             slice::from_raw_parts(self.0.data, self.0.size)
625         }
626     }
627 }
628 
629 #[cfg(any(feature = "v1_16", feature = "dox"))]
630 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
631 unsafe impl MetaAPI for VideoCaptionMeta {
632     type GstType = ffi::GstVideoCaptionMeta;
633 
634     #[doc(alias = "gst_video_caption_meta_api_get_type")]
meta_api() -> glib::Type635     fn meta_api() -> glib::Type {
636         unsafe { from_glib(ffi::gst_video_caption_meta_api_get_type()) }
637     }
638 }
639 
640 #[cfg(any(feature = "v1_16", feature = "dox"))]
641 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
642 impl fmt::Debug for VideoCaptionMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result643     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
644         f.debug_struct("VideoCaptionMeta")
645             .field("caption_type", &self.caption_type())
646             .field("data", &self.data())
647             .finish()
648     }
649 }
650 
651 #[cfg(any(feature = "v1_18", feature = "dox"))]
652 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
653 #[repr(transparent)]
654 #[doc(alias = "GstVideoAFDMeta")]
655 pub struct VideoAFDMeta(ffi::GstVideoAFDMeta);
656 
657 #[cfg(any(feature = "v1_18", feature = "dox"))]
658 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
659 unsafe impl Send for VideoAFDMeta {}
660 #[cfg(any(feature = "v1_18", feature = "dox"))]
661 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
662 unsafe impl Sync for VideoAFDMeta {}
663 
664 #[cfg(any(feature = "v1_18", feature = "dox"))]
665 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
666 impl VideoAFDMeta {
667     #[doc(alias = "gst_buffer_add_video_afd_meta")]
add( buffer: &mut gst::BufferRef, field: u8, spec: crate::VideoAFDSpec, afd: crate::VideoAFDValue, ) -> gst::MetaRefMut<Self, gst::meta::Standalone>668     pub fn add(
669         buffer: &mut gst::BufferRef,
670         field: u8,
671         spec: crate::VideoAFDSpec,
672         afd: crate::VideoAFDValue,
673     ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
674         skip_assert_initialized!();
675 
676         unsafe {
677             let meta = ffi::gst_buffer_add_video_afd_meta(
678                 buffer.as_mut_ptr(),
679                 field,
680                 spec.into_glib(),
681                 afd.into_glib(),
682             );
683 
684             Self::from_mut_ptr(buffer, meta)
685         }
686     }
687 
688     #[doc(alias = "get_field")]
field(&self) -> u8689     pub fn field(&self) -> u8 {
690         self.0.field
691     }
692 
693     #[doc(alias = "get_spec")]
spec(&self) -> crate::VideoAFDSpec694     pub fn spec(&self) -> crate::VideoAFDSpec {
695         unsafe { from_glib(self.0.spec) }
696     }
697 
698     #[doc(alias = "get_afd")]
afd(&self) -> crate::VideoAFDValue699     pub fn afd(&self) -> crate::VideoAFDValue {
700         unsafe { from_glib(self.0.afd) }
701     }
702 }
703 
704 #[cfg(any(feature = "v1_18", feature = "dox"))]
705 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
706 unsafe impl MetaAPI for VideoAFDMeta {
707     type GstType = ffi::GstVideoAFDMeta;
708 
709     #[doc(alias = "gst_video_afd_meta_api_get_type")]
meta_api() -> glib::Type710     fn meta_api() -> glib::Type {
711         unsafe { from_glib(ffi::gst_video_afd_meta_api_get_type()) }
712     }
713 }
714 
715 #[cfg(any(feature = "v1_18", feature = "dox"))]
716 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
717 impl fmt::Debug for VideoAFDMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result718     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
719         f.debug_struct("VideoAFDMeta")
720             .field("field", &self.field())
721             .field("spec", &self.spec())
722             .field("afd", &self.afd())
723             .finish()
724     }
725 }
726 
727 #[cfg(any(feature = "v1_18", feature = "dox"))]
728 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
729 #[repr(transparent)]
730 #[doc(alias = "GstVideoBarMeta")]
731 pub struct VideoBarMeta(ffi::GstVideoBarMeta);
732 
733 #[cfg(any(feature = "v1_18", feature = "dox"))]
734 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
735 unsafe impl Send for VideoBarMeta {}
736 #[cfg(any(feature = "v1_18", feature = "dox"))]
737 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
738 unsafe impl Sync for VideoBarMeta {}
739 
740 #[cfg(any(feature = "v1_18", feature = "dox"))]
741 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
742 impl VideoBarMeta {
743     #[doc(alias = "gst_buffer_add_video_bar_meta")]
add( buffer: &mut gst::BufferRef, field: u8, is_letterbox: bool, bar_data1: u32, bar_data2: u32, ) -> gst::MetaRefMut<Self, gst::meta::Standalone>744     pub fn add(
745         buffer: &mut gst::BufferRef,
746         field: u8,
747         is_letterbox: bool,
748         bar_data1: u32,
749         bar_data2: u32,
750     ) -> gst::MetaRefMut<Self, gst::meta::Standalone> {
751         skip_assert_initialized!();
752 
753         unsafe {
754             let meta = ffi::gst_buffer_add_video_bar_meta(
755                 buffer.as_mut_ptr(),
756                 field,
757                 is_letterbox.into_glib(),
758                 bar_data1,
759                 bar_data2,
760             );
761 
762             Self::from_mut_ptr(buffer, meta)
763         }
764     }
765 
766     #[doc(alias = "get_field")]
field(&self) -> u8767     pub fn field(&self) -> u8 {
768         self.0.field
769     }
770 
is_letterbox(&self) -> bool771     pub fn is_letterbox(&self) -> bool {
772         unsafe { from_glib(self.0.is_letterbox) }
773     }
774 
775     #[doc(alias = "get_bar_data1")]
bar_data1(&self) -> u32776     pub fn bar_data1(&self) -> u32 {
777         self.0.bar_data1
778     }
779 
780     #[doc(alias = "get_bar_data2")]
bar_data2(&self) -> u32781     pub fn bar_data2(&self) -> u32 {
782         self.0.bar_data2
783     }
784 }
785 
786 #[cfg(any(feature = "v1_18", feature = "dox"))]
787 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
788 unsafe impl MetaAPI for VideoBarMeta {
789     type GstType = ffi::GstVideoBarMeta;
790 
791     #[doc(alias = "gst_video_bar_meta_api_get_type")]
meta_api() -> glib::Type792     fn meta_api() -> glib::Type {
793         unsafe { from_glib(ffi::gst_video_bar_meta_api_get_type()) }
794     }
795 }
796 
797 #[cfg(any(feature = "v1_18", feature = "dox"))]
798 #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
799 impl fmt::Debug for VideoBarMeta {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result800     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
801         f.debug_struct("VideoBarMeta")
802             .field("field", &self.field())
803             .field("is_letterbox", &self.is_letterbox())
804             .field("bar_data1", &self.bar_data1())
805             .field("bar_data2", &self.bar_data2())
806             .finish()
807     }
808 }
809 
810 #[cfg(test)]
811 mod tests {
812     use super::*;
813 
814     #[test]
test_add_get_meta()815     fn test_add_get_meta() {
816         gst::init().unwrap();
817 
818         let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
819         {
820             let meta = VideoMeta::add(
821                 buffer.get_mut().unwrap(),
822                 crate::VideoFrameFlags::empty(),
823                 crate::VideoFormat::Argb,
824                 320,
825                 240,
826             )
827             .unwrap();
828             assert_eq!(meta.id(), 0);
829             assert_eq!(meta.flags(), crate::VideoFrameFlags::empty());
830             assert_eq!(meta.format(), crate::VideoFormat::Argb);
831             assert_eq!(meta.width(), 320);
832             assert_eq!(meta.height(), 240);
833             assert_eq!(meta.n_planes(), 1);
834             assert_eq!(meta.offset(), &[0]);
835             assert_eq!(meta.stride(), &[320 * 4]);
836         }
837 
838         {
839             let meta = buffer.meta::<VideoMeta>().unwrap();
840             assert_eq!(meta.id(), 0);
841             assert_eq!(meta.flags(), crate::VideoFrameFlags::empty());
842             assert_eq!(meta.format(), crate::VideoFormat::Argb);
843             assert_eq!(meta.width(), 320);
844             assert_eq!(meta.height(), 240);
845             assert_eq!(meta.n_planes(), 1);
846             assert_eq!(meta.offset(), &[0]);
847             assert_eq!(meta.stride(), &[320 * 4]);
848         }
849     }
850 
851     #[test]
test_add_full_get_meta()852     fn test_add_full_get_meta() {
853         gst::init().unwrap();
854 
855         let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
856         {
857             let meta = VideoMeta::add_full(
858                 buffer.get_mut().unwrap(),
859                 crate::VideoFrameFlags::empty(),
860                 crate::VideoFormat::Argb,
861                 320,
862                 240,
863                 &[0],
864                 &[320 * 4],
865             )
866             .unwrap();
867             assert_eq!(meta.id(), 0);
868             assert_eq!(meta.flags(), crate::VideoFrameFlags::empty());
869             assert_eq!(meta.format(), crate::VideoFormat::Argb);
870             assert_eq!(meta.width(), 320);
871             assert_eq!(meta.height(), 240);
872             assert_eq!(meta.n_planes(), 1);
873             assert_eq!(meta.offset(), &[0]);
874             assert_eq!(meta.stride(), &[320 * 4]);
875         }
876 
877         {
878             let meta = buffer.meta::<VideoMeta>().unwrap();
879             assert_eq!(meta.id(), 0);
880             assert_eq!(meta.flags(), crate::VideoFrameFlags::empty());
881             assert_eq!(meta.format(), crate::VideoFormat::Argb);
882             assert_eq!(meta.width(), 320);
883             assert_eq!(meta.height(), 240);
884             assert_eq!(meta.n_planes(), 1);
885             assert_eq!(meta.offset(), &[0]);
886             assert_eq!(meta.stride(), &[320 * 4]);
887         }
888     }
889 
890     #[test]
891     #[cfg(feature = "v1_18")]
test_vide_meta_alignment()892     fn test_vide_meta_alignment() {
893         gst::init().unwrap();
894 
895         let mut buffer = gst::Buffer::with_size(115200).unwrap();
896         let meta = VideoMeta::add(
897             buffer.get_mut().unwrap(),
898             crate::VideoFrameFlags::empty(),
899             crate::VideoFormat::Nv12,
900             320,
901             240,
902         )
903         .unwrap();
904 
905         let alig = meta.alignment();
906         assert_eq!(alig, crate::VideoAlignment::new(0, 0, 0, 0, &[0, 0, 0, 0]));
907 
908         assert_eq!(meta.plane_size().unwrap(), [76800, 38400, 0, 0]);
909         assert_eq!(meta.plane_height().unwrap(), [240, 120, 0, 0]);
910 
911         /* horizontal padding */
912         let mut info = crate::VideoInfo::builder(crate::VideoFormat::Nv12, 320, 240)
913             .build()
914             .expect("Failed to create VideoInfo");
915         let mut alig = crate::VideoAlignment::new(0, 0, 2, 6, &[0, 0, 0, 0]);
916         info.align(&mut alig).unwrap();
917 
918         let mut meta = VideoMeta::add_full(
919             buffer.get_mut().unwrap(),
920             crate::VideoFrameFlags::empty(),
921             crate::VideoFormat::Nv12,
922             info.width(),
923             info.height(),
924             info.offset(),
925             info.stride(),
926         )
927         .unwrap();
928         meta.set_alignment(&alig).unwrap();
929 
930         let alig = meta.alignment();
931         assert_eq!(alig, crate::VideoAlignment::new(0, 0, 2, 6, &[0, 0, 0, 0]));
932 
933         assert_eq!(meta.plane_size().unwrap(), [78720, 39360, 0, 0]);
934         assert_eq!(meta.plane_height().unwrap(), [240, 120, 0, 0]);
935 
936         /* vertical alignment */
937         let mut info = crate::VideoInfo::builder(crate::VideoFormat::Nv12, 320, 240)
938             .build()
939             .expect("Failed to create VideoInfo");
940         let mut alig = crate::VideoAlignment::new(2, 6, 0, 0, &[0, 0, 0, 0]);
941         info.align(&mut alig).unwrap();
942 
943         let mut meta = VideoMeta::add_full(
944             buffer.get_mut().unwrap(),
945             crate::VideoFrameFlags::empty(),
946             crate::VideoFormat::Nv12,
947             info.width(),
948             info.height(),
949             info.offset(),
950             info.stride(),
951         )
952         .unwrap();
953         meta.set_alignment(&alig).unwrap();
954 
955         let alig = meta.alignment();
956         assert_eq!(alig, crate::VideoAlignment::new(2, 6, 0, 0, &[0, 0, 0, 0]));
957 
958         assert_eq!(meta.plane_size().unwrap(), [79360, 39680, 0, 0]);
959         assert_eq!(meta.plane_height().unwrap(), [248, 124, 0, 0]);
960     }
961 }
962