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