1 // Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com> 2 // 3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 6 // option. This file may not be copied, modified, or distributed 7 // except according to those terms. 8 9 use AllocationParams; 10 use Allocator; 11 use BufferPool; 12 use Structure; 13 14 use glib; 15 use glib::translate::{from_glib, from_glib_full, from_glib_none, ToGlib, ToGlibPtr, ToGlibPtrMut}; 16 use glib::IsA; 17 18 use gst_sys; 19 20 use std::mem; 21 use std::ops; 22 use std::ptr; 23 24 #[derive(Debug, Clone, PartialEq, Eq)] 25 pub struct BufferPoolConfig(Structure); 26 27 impl ops::Deref for BufferPoolConfig { 28 type Target = ::StructureRef; 29 deref(&self) -> &::StructureRef30 fn deref(&self) -> &::StructureRef { 31 self.0.deref() 32 } 33 } 34 35 impl ops::DerefMut for BufferPoolConfig { deref_mut(&mut self) -> &mut ::StructureRef36 fn deref_mut(&mut self) -> &mut ::StructureRef { 37 self.0.deref_mut() 38 } 39 } 40 41 impl AsRef<::StructureRef> for BufferPoolConfig { as_ref(&self) -> &::StructureRef42 fn as_ref(&self) -> &::StructureRef { 43 self.0.as_ref() 44 } 45 } 46 47 impl AsMut<::StructureRef> for BufferPoolConfig { as_mut(&mut self) -> &mut ::StructureRef48 fn as_mut(&mut self) -> &mut ::StructureRef { 49 self.0.as_mut() 50 } 51 } 52 53 impl BufferPoolConfig { add_option(&mut self, option: &str)54 pub fn add_option(&mut self, option: &str) { 55 unsafe { 56 gst_sys::gst_buffer_pool_config_add_option( 57 self.0.to_glib_none_mut().0, 58 option.to_glib_none().0, 59 ); 60 } 61 } 62 has_option(&self, option: &str) -> bool63 pub fn has_option(&self, option: &str) -> bool { 64 unsafe { 65 from_glib(gst_sys::gst_buffer_pool_config_has_option( 66 self.0.to_glib_none().0, 67 option.to_glib_none().0, 68 )) 69 } 70 } 71 get_options(&self) -> Vec<String>72 pub fn get_options(&self) -> Vec<String> { 73 unsafe { 74 let n = gst_sys::gst_buffer_pool_config_n_options(self.0.to_glib_none().0) as usize; 75 let mut options = Vec::with_capacity(n); 76 77 for i in 0..n { 78 options.push(from_glib_none(gst_sys::gst_buffer_pool_config_get_option( 79 self.0.to_glib_none().0, 80 i as u32, 81 ))); 82 } 83 84 options 85 } 86 } 87 set_params( &mut self, caps: Option<&::Caps>, size: u32, min_buffers: u32, max_buffers: u32, )88 pub fn set_params( 89 &mut self, 90 caps: Option<&::Caps>, 91 size: u32, 92 min_buffers: u32, 93 max_buffers: u32, 94 ) { 95 unsafe { 96 gst_sys::gst_buffer_pool_config_set_params( 97 self.0.to_glib_none_mut().0, 98 caps.to_glib_none().0, 99 size, 100 min_buffers, 101 max_buffers, 102 ); 103 } 104 } 105 get_params(&self) -> Option<(Option<::Caps>, u32, u32, u32)>106 pub fn get_params(&self) -> Option<(Option<::Caps>, u32, u32, u32)> { 107 unsafe { 108 let mut caps = ptr::null_mut(); 109 let mut size = mem::MaybeUninit::uninit(); 110 let mut min_buffers = mem::MaybeUninit::uninit(); 111 let mut max_buffers = mem::MaybeUninit::uninit(); 112 113 let ret: bool = from_glib(gst_sys::gst_buffer_pool_config_get_params( 114 self.0.to_glib_none().0, 115 &mut caps, 116 size.as_mut_ptr(), 117 min_buffers.as_mut_ptr(), 118 max_buffers.as_mut_ptr(), 119 )); 120 if !ret { 121 return None; 122 } 123 124 Some(( 125 from_glib_none(caps), 126 size.assume_init(), 127 min_buffers.assume_init(), 128 max_buffers.assume_init(), 129 )) 130 } 131 } 132 validate_params( &self, caps: Option<&::Caps>, size: u32, min_buffers: u32, max_buffers: u32, ) -> Result<(), glib::BoolError>133 pub fn validate_params( 134 &self, 135 caps: Option<&::Caps>, 136 size: u32, 137 min_buffers: u32, 138 max_buffers: u32, 139 ) -> Result<(), glib::BoolError> { 140 unsafe { 141 glib_result_from_gboolean!( 142 gst_sys::gst_buffer_pool_config_validate_params( 143 self.0.to_glib_none().0, 144 caps.to_glib_none().0, 145 size, 146 min_buffers, 147 max_buffers, 148 ), 149 "Parameters are not valid in this context" 150 ) 151 } 152 } 153 get_allocator(&self) -> Option<(Option<Allocator>, AllocationParams)>154 pub fn get_allocator(&self) -> Option<(Option<Allocator>, AllocationParams)> { 155 unsafe { 156 let mut allocator = ptr::null_mut(); 157 let mut params = mem::MaybeUninit::zeroed(); 158 let ret = from_glib(gst_sys::gst_buffer_pool_config_get_allocator( 159 self.0.to_glib_none().0, 160 &mut allocator, 161 params.as_mut_ptr(), 162 )); 163 if ret { 164 Some((from_glib_none(allocator), params.assume_init().into())) 165 } else { 166 None 167 } 168 } 169 } 170 set_allocator(&self, allocator: Option<&Allocator>, params: Option<&AllocationParams>)171 pub fn set_allocator(&self, allocator: Option<&Allocator>, params: Option<&AllocationParams>) { 172 assert!(allocator.is_some() || params.is_some()); 173 unsafe { 174 gst_sys::gst_buffer_pool_config_set_allocator( 175 self.0.to_glib_none().0, 176 allocator.to_glib_none().0, 177 match params { 178 Some(val) => val.as_ptr(), 179 None => ptr::null(), 180 }, 181 ) 182 } 183 } 184 // TODO: options iterator 185 } 186 187 #[derive(Debug)] 188 pub struct BufferPoolAcquireParams(gst_sys::GstBufferPoolAcquireParams); 189 190 unsafe impl Send for BufferPoolAcquireParams {} 191 unsafe impl Sync for BufferPoolAcquireParams {} 192 193 impl BufferPoolAcquireParams { with_flags(flags: ::BufferPoolAcquireFlags) -> Self194 pub fn with_flags(flags: ::BufferPoolAcquireFlags) -> Self { 195 BufferPoolAcquireParams(gst_sys::GstBufferPoolAcquireParams { 196 format: gst_sys::GST_FORMAT_UNDEFINED, 197 start: -1, 198 stop: -1, 199 flags: flags.to_glib(), 200 _gst_reserved: [ptr::null_mut(); 4], 201 }) 202 } 203 with_start_stop<T: ::SpecificFormattedValue>( start: T, stop: T, flags: ::BufferPoolAcquireFlags, ) -> Self204 pub fn with_start_stop<T: ::SpecificFormattedValue>( 205 start: T, 206 stop: T, 207 flags: ::BufferPoolAcquireFlags, 208 ) -> Self { 209 unsafe { 210 BufferPoolAcquireParams(gst_sys::GstBufferPoolAcquireParams { 211 format: start.get_format().to_glib(), 212 start: start.to_raw_value(), 213 stop: stop.to_raw_value(), 214 flags: flags.to_glib(), 215 _gst_reserved: [ptr::null_mut(); 4], 216 }) 217 } 218 } 219 flags(&self) -> ::BufferPoolAcquireFlags220 pub fn flags(&self) -> ::BufferPoolAcquireFlags { 221 from_glib(self.0.flags) 222 } 223 format(&self) -> ::Format224 pub fn format(&self) -> ::Format { 225 from_glib(self.0.format) 226 } 227 start(&self) -> ::GenericFormattedValue228 pub fn start(&self) -> ::GenericFormattedValue { 229 ::GenericFormattedValue::new(from_glib(self.0.format), self.0.start) 230 } 231 stop(&self) -> ::GenericFormattedValue232 pub fn stop(&self) -> ::GenericFormattedValue { 233 ::GenericFormattedValue::new(from_glib(self.0.format), self.0.stop) 234 } 235 } 236 237 impl PartialEq for BufferPoolAcquireParams { eq(&self, other: &Self) -> bool238 fn eq(&self, other: &Self) -> bool { 239 self.format() == other.format() 240 && self.start() == other.start() 241 && self.stop() == other.stop() 242 } 243 } 244 245 impl Eq for BufferPoolAcquireParams {} 246 247 #[doc(hidden)] 248 impl<'a> ToGlibPtr<'a, *const gst_sys::GstBufferPoolAcquireParams> for BufferPoolAcquireParams { 249 type Storage = &'a Self; 250 to_glib_none( &'a self, ) -> glib::translate::Stash<'a, *const gst_sys::GstBufferPoolAcquireParams, Self>251 fn to_glib_none( 252 &'a self, 253 ) -> glib::translate::Stash<'a, *const gst_sys::GstBufferPoolAcquireParams, Self> { 254 glib::translate::Stash(&self.0, self) 255 } 256 } 257 258 #[doc(hidden)] 259 impl<'a> ToGlibPtrMut<'a, *mut gst_sys::GstBufferPoolAcquireParams> for BufferPoolAcquireParams { 260 type Storage = &'a mut Self; 261 to_glib_none_mut( &'a mut self, ) -> glib::translate::StashMut<'a, *mut gst_sys::GstBufferPoolAcquireParams, Self>262 fn to_glib_none_mut( 263 &'a mut self, 264 ) -> glib::translate::StashMut<'a, *mut gst_sys::GstBufferPoolAcquireParams, Self> { 265 glib::translate::StashMut(&mut self.0, self) 266 } 267 } 268 269 impl BufferPool { new() -> BufferPool270 pub fn new() -> BufferPool { 271 assert_initialized_main_thread!(); 272 let (major, minor, _, _) = ::version(); 273 if (major, minor) > (1, 12) { 274 unsafe { from_glib_full(gst_sys::gst_buffer_pool_new()) } 275 } else { 276 // Work-around for 1.14 switching from transfer-floating to transfer-full 277 unsafe { from_glib_none(gst_sys::gst_buffer_pool_new()) } 278 } 279 } 280 } 281 282 impl Default for BufferPool { default() -> Self283 fn default() -> Self { 284 Self::new() 285 } 286 } 287 288 pub trait BufferPoolExtManual: 'static { get_config(&self) -> BufferPoolConfig289 fn get_config(&self) -> BufferPoolConfig; set_config(&self, config: BufferPoolConfig) -> Result<(), glib::error::BoolError>290 fn set_config(&self, config: BufferPoolConfig) -> Result<(), glib::error::BoolError>; 291 is_flushing(&self) -> bool292 fn is_flushing(&self) -> bool; 293 acquire_buffer( &self, params: Option<&BufferPoolAcquireParams>, ) -> Result<::Buffer, ::FlowError>294 fn acquire_buffer( 295 &self, 296 params: Option<&BufferPoolAcquireParams>, 297 ) -> Result<::Buffer, ::FlowError>; release_buffer(&self, buffer: ::Buffer)298 fn release_buffer(&self, buffer: ::Buffer); 299 } 300 301 impl<O: IsA<BufferPool>> BufferPoolExtManual for O { get_config(&self) -> BufferPoolConfig302 fn get_config(&self) -> BufferPoolConfig { 303 unsafe { 304 let ptr = gst_sys::gst_buffer_pool_get_config(self.as_ref().to_glib_none().0); 305 BufferPoolConfig(from_glib_full(ptr)) 306 } 307 } 308 set_config(&self, config: BufferPoolConfig) -> Result<(), glib::error::BoolError>309 fn set_config(&self, config: BufferPoolConfig) -> Result<(), glib::error::BoolError> { 310 unsafe { 311 glib_result_from_gboolean!( 312 gst_sys::gst_buffer_pool_set_config( 313 self.as_ref().to_glib_none().0, 314 config.0.into_ptr() 315 ), 316 "Failed to set config", 317 ) 318 } 319 } 320 is_flushing(&self) -> bool321 fn is_flushing(&self) -> bool { 322 unsafe { 323 let stash = self.as_ref().to_glib_none(); 324 let ptr: *mut gst_sys::GstBufferPool = stash.0; 325 326 from_glib((*ptr).flushing) 327 } 328 } 329 acquire_buffer( &self, params: Option<&BufferPoolAcquireParams>, ) -> Result<::Buffer, ::FlowError>330 fn acquire_buffer( 331 &self, 332 params: Option<&BufferPoolAcquireParams>, 333 ) -> Result<::Buffer, ::FlowError> { 334 let params_ptr = params.to_glib_none().0 as *mut _; 335 336 unsafe { 337 let mut buffer = ptr::null_mut(); 338 let ret: ::FlowReturn = from_glib(gst_sys::gst_buffer_pool_acquire_buffer( 339 self.as_ref().to_glib_none().0, 340 &mut buffer, 341 params_ptr, 342 )); 343 344 ret.into_result_value(|| from_glib_full(buffer)) 345 } 346 } 347 release_buffer(&self, buffer: ::Buffer)348 fn release_buffer(&self, buffer: ::Buffer) { 349 unsafe { 350 gst_sys::gst_buffer_pool_release_buffer( 351 self.as_ref().to_glib_none().0, 352 buffer.into_ptr(), 353 ); 354 } 355 } 356 } 357 358 #[cfg(test)] 359 mod tests { 360 use super::*; 361 use prelude::*; 362 363 #[test] test_pool()364 fn test_pool() { 365 ::init().unwrap(); 366 367 let pool = ::BufferPool::new(); 368 let mut config = pool.get_config(); 369 config.set_params(Some(&::Caps::new_simple("foo/bar", &[])), 1024, 0, 2); 370 pool.set_config(config).unwrap(); 371 372 pool.set_active(true).unwrap(); 373 374 let params = ::BufferPoolAcquireParams::with_flags(::BufferPoolAcquireFlags::DONTWAIT); 375 376 let _buf1 = pool.acquire_buffer(Some(¶ms)).unwrap(); 377 let buf2 = pool.acquire_buffer(Some(¶ms)).unwrap(); 378 379 assert!(pool.acquire_buffer(Some(¶ms)).is_err()); 380 381 drop(buf2); 382 let _buf2 = pool.acquire_buffer(Some(¶ms)).unwrap(); 383 384 pool.set_active(false).unwrap(); 385 } 386 } 387