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