diff --git a/gst-plugin-file/src/filesrc.rs b/gst-plugin-file/src/filesrc.rs index 0e95f4e2..49d029ec 100644 --- a/gst-plugin-file/src/filesrc.rs +++ b/gst-plugin-file/src/filesrc.rs @@ -167,10 +167,7 @@ impl Source for FileSrc { *position += size as u64; - if let Err(err) = buffer.set_size(size) { - return Err(FlowError::Error(error_msg!(SourceError::Failure, - ["Failed to resize buffer: {}", err]))); - } + buffer.set_size(size); Ok(()) } diff --git a/gst-plugin-flv/src/flvdemux.rs b/gst-plugin-flv/src/flvdemux.rs index d7f196d3..b97253dd 100644 --- a/gst-plugin-flv/src/flvdemux.rs +++ b/gst-plugin-flv/src/flvdemux.rs @@ -31,6 +31,7 @@ use gst_plugin::utils; use gst_plugin::utils::Element; use gst_plugin::log::*; use gst_plugin::caps::Caps; +use gst_plugin::miniobject::*; use gst_plugin::value::Rational32; use gst_plugin::bytes::*; @@ -62,8 +63,8 @@ struct StreamingState { metadata: Option, - aac_sequence_header: Option, - avc_sequence_header: Option, + aac_sequence_header: Option>, + avc_sequence_header: Option>, } impl StreamingState { @@ -89,7 +90,7 @@ struct AudioFormat { width: u8, channels: u8, bitrate: Option, - aac_sequence_header: Option, + aac_sequence_header: Option>, } // Ignores bitrate @@ -104,7 +105,7 @@ impl PartialEq for AudioFormat { impl AudioFormat { fn new(data_header: &flavors::AudioDataHeader, metadata: &Option, - aac_sequence_header: &Option) + aac_sequence_header: &Option>) -> AudioFormat { let numeric_rate = match (data_header.sound_format, data_header.sound_rate) { (flavors::SoundFormat::NELLYMOSER_16KHZ_MONO, _) => 16000, @@ -152,7 +153,7 @@ impl AudioFormat { self.to_caps().map(|c| c.to_string()) } - fn to_caps(&self) -> Option { + fn to_caps(&self) -> Option> { let mut caps = match self.format { flavors::SoundFormat::MP3 | flavors::SoundFormat::MP3_8KHZ => { @@ -190,7 +191,7 @@ impl AudioFormat { &[("mpegversion", &4.into()), ("framed", &true.into()), ("stream-format", &"raw".into()), - ("codec_data", &header.into())]) + ("codec_data", &header.as_ref().into())]) }) } flavors::SoundFormat::SPEEX => { @@ -245,11 +246,13 @@ impl AudioFormat { if self.rate != 0 { caps.as_mut() - .map(|c| c.set_simple(&[("rate", &(self.rate as i32).into())])); + .map(|c| c.get_mut().unwrap().set_simple(&[("rate", &(self.rate as i32).into())])); } if self.channels != 0 { caps.as_mut() - .map(|c| c.set_simple(&[("channels", &(self.channels as i32).into())])); + .map(|c| { + c.get_mut().unwrap().set_simple(&[("channels", &(self.channels as i32).into())]) + }); } caps @@ -264,13 +267,13 @@ struct VideoFormat { pixel_aspect_ratio: Option, framerate: Option, bitrate: Option, - avc_sequence_header: Option, + avc_sequence_header: Option>, } impl VideoFormat { fn new(data_header: &flavors::VideoDataHeader, metadata: &Option, - avc_sequence_header: &Option) + avc_sequence_header: &Option>) -> VideoFormat { VideoFormat { format: data_header.codec_id, @@ -318,7 +321,7 @@ impl VideoFormat { self.to_caps().map(|caps| caps.to_string()) } - fn to_caps(&self) -> Option { + fn to_caps(&self) -> Option> { let mut caps = match self.format { flavors::CodecId::SORENSON_H263 => { Some(Caps::new_simple("video/x-flash-video", &[("flvversion", &1.into())])) @@ -331,7 +334,7 @@ impl VideoFormat { self.avc_sequence_header.as_ref().map(|header| { Caps::new_simple("video/x-h264", &[("stream-format", &"avc".into()), - ("codec_data", &header.into())]) + ("codec_data", &header.as_ref().into())]) }) } flavors::CodecId::H263 => Some(Caps::new_simple("video/x-h263", &[])), @@ -348,21 +351,23 @@ impl VideoFormat { if let (Some(width), Some(height)) = (self.width, self.height) { caps.as_mut().map(|c| { - c.set_simple(&[("width", &(width as i32).into()), - ("height", &(height as i32).into())]) + c.get_mut().unwrap().set_simple(&[("width", &(width as i32).into()), + ("height", &(height as i32).into())]) }); } if let Some(par) = self.pixel_aspect_ratio { if *par.numer() != 0 && par.numer() != par.denom() { - caps.as_mut().map(|c| c.set_simple(&[("pixel-aspect-ratio", &par.into())])); + caps.as_mut().map(|c| { + c.get_mut().unwrap().set_simple(&[("pixel-aspect-ratio", &par.into())]) + }); } } if let Some(fps) = self.framerate { if *fps.numer() != 0 { caps.as_mut() - .map(|c| c.set_simple(&[("framerate", &fps.into())])); + .map(|c| c.get_mut().unwrap().set_simple(&[("framerate", &fps.into())])); } } @@ -700,7 +705,11 @@ impl FlvDemux { .get_buffer((tag_header.data_size - 1 - offset) as usize) .unwrap(); - buffer.set_pts(Some((tag_header.timestamp as u64) * 1000 * 1000)).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + buffer.set_pts(Some((tag_header.timestamp as u64) * 1000 * 1000)); + } + trace!(self.logger, "Outputting audio buffer {:?} for tag {:?} of size {}", buffer, @@ -850,19 +859,22 @@ impl FlvDemux { let mut buffer = self.adapter .get_buffer((tag_header.data_size - 1 - offset) as usize) .unwrap(); - if !is_keyframe { - buffer.set_flags(BUFFER_FLAG_DELTA_UNIT).unwrap(); - } - buffer.set_dts(Some((tag_header.timestamp as u64) * 1000 * 1000)) - .unwrap(); - // Prevent negative numbers - let pts = if cts < 0 && tag_header.timestamp < (-cts) as u32 { - 0 - } else { - ((tag_header.timestamp as i64) + (cts as i64)) as u64 - }; - buffer.set_pts(Some(pts * 1000 * 1000)).unwrap(); + { + let buffer = buffer.get_mut().unwrap(); + if !is_keyframe { + buffer.set_flags(BUFFER_FLAG_DELTA_UNIT); + } + buffer.set_dts(Some((tag_header.timestamp as u64) * 1000 * 1000)); + + // Prevent negative numbers + let pts = if cts < 0 && tag_header.timestamp < (-cts) as u32 { + 0 + } else { + ((tag_header.timestamp as i64) + (cts as i64)) as u64 + }; + buffer.set_pts(Some(pts * 1000 * 1000)); + } trace!(self.logger, "Outputting video buffer {:?} for tag {:?} of size {}, keyframe: {}", @@ -1030,7 +1042,9 @@ impl Demuxer for FlvDemux { unimplemented!(); } - fn handle_buffer(&mut self, buffer: Option) -> Result { + fn handle_buffer(&mut self, + buffer: Option>) + -> Result { if let Some(buffer) = buffer { self.adapter.push(buffer); } diff --git a/gst-plugin-http/src/httpsrc.rs b/gst-plugin-http/src/httpsrc.rs index 5d747a19..cec9b5ec 100644 --- a/gst-plugin-http/src/httpsrc.rs +++ b/gst-plugin-http/src/httpsrc.rs @@ -243,11 +243,7 @@ impl Source for HttpSrc { *position += size as u64; - if let Err(err) = buffer.set_size(size) { - return Err(FlowError::Error(error_msg!(SourceError::Failure, - ["Failed to resize buffer: {}", err]))); - } - + buffer.set_size(size); Ok(()) } diff --git a/gst-plugin/src/adapter.rs b/gst-plugin/src/adapter.rs index 2ae4c992..37d06a63 100644 --- a/gst-plugin/src/adapter.rs +++ b/gst-plugin/src/adapter.rs @@ -17,6 +17,7 @@ // use buffer::*; +use miniobject::*; use log::*; use std::collections::VecDeque; use std::cmp; @@ -55,7 +56,7 @@ impl Adapter { } } - pub fn push(&mut self, buffer: Buffer) { + pub fn push(&mut self, buffer: GstRc) { let size = buffer.get_size(); self.size += size; @@ -64,7 +65,7 @@ impl Adapter { buffer, size, self.size); - self.deque.push_back(buffer.into_read_mapped_buffer().unwrap()); + self.deque.push_back(Buffer::into_read_mapped_buffer(buffer).unwrap()); } pub fn clear(&mut self) { @@ -159,7 +160,7 @@ impl Adapter { Ok(self.scratch.as_slice()) } - pub fn get_buffer(&mut self, size: usize) -> Result { + pub fn get_buffer(&mut self, size: usize) -> Result, AdapterError> { if self.size < size { debug!(LOGGER, "Get buffer of {} bytes, not enough data: have {}", @@ -172,14 +173,12 @@ impl Adapter { return Ok(Buffer::new()); } - let sub = self.deque.front().and_then(|front| { - if front.get_size() - self.skip >= size { - trace!(LOGGER, "Get buffer of {} bytes, subbuffer of first", size); - let new = front.get_buffer().copy_region(self.skip, Some(size)).unwrap(); - Some(new) - } else { - None - } + let sub = self.deque.front().and_then(|front| if front.get_size() - self.skip >= size { + trace!(LOGGER, "Get buffer of {} bytes, subbuffer of first", size); + let new = front.get_buffer().copy_region(self.skip, Some(size)).unwrap(); + Some(new) + } else { + None }); if let Some(s) = sub { @@ -190,7 +189,7 @@ impl Adapter { trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size); let mut new = Buffer::new_with_size(size).unwrap(); { - let mut map = new.map_readwrite().unwrap(); + let mut map = new.get_mut().unwrap().map_readwrite().unwrap(); let data = map.as_mut_slice(); Self::copy_data(&self.deque, self.skip, data, size); } @@ -244,7 +243,6 @@ impl Adapter { #[cfg(test)] mod tests { use super::*; - use buffer::*; use std::ptr; use std::os::raw::c_void; diff --git a/gst-plugin/src/buffer.c b/gst-plugin/src/buffer.c index 4d019b15..33f67b43 100644 --- a/gst-plugin/src/buffer.c +++ b/gst-plugin/src/buffer.c @@ -42,6 +42,18 @@ gst_rs_buffer_set_dts (GstBuffer * buffer, guint64 dts) GST_BUFFER_DTS (buffer) = dts; } +guint64 +gst_rs_buffer_get_duration (GstBuffer * buffer) +{ + return GST_BUFFER_DURATION (buffer); +} + +void +gst_rs_buffer_set_duration (GstBuffer * buffer, guint64 dts) +{ + GST_BUFFER_DURATION (buffer) = dts; +} + guint64 gst_rs_buffer_get_offset (GstBuffer * buffer) { diff --git a/gst-plugin/src/buffer.rs b/gst-plugin/src/buffer.rs index cbf65661..0206af8b 100644 --- a/gst-plugin/src/buffer.rs +++ b/gst-plugin/src/buffer.rs @@ -20,21 +20,14 @@ use std::ptr; use std::mem; use std::os::raw::c_void; use std::slice; -use std::marker::PhantomData; use std::u64; use std::usize; -use std::fmt::{Display, Formatter}; -use std::fmt::Error as FmtError; -use std::error::Error; -use std::ops::{Deref, DerefMut}; use utils::*; +use miniobject::*; #[derive(Debug)] -pub struct Buffer { - raw: *mut c_void, - owned: bool, -} +pub struct Buffer(*mut c_void); #[repr(C)] #[derive(Debug)] @@ -62,77 +55,40 @@ pub struct ReadWriteBufferMap<'a> { #[derive(Debug)] pub struct ReadMappedBuffer { - buffer: Buffer, + buffer: GstRc, map_info: GstMapInfo, } #[derive(Debug)] pub struct ReadWriteMappedBuffer { - buffer: Buffer, + buffer: GstRc, map_info: GstMapInfo, } -#[derive(Debug, PartialEq, Eq)] -pub enum BufferError { - NotWritable, - NotEnoughSpace, - Unknown, -} - -impl Display for BufferError { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - f.write_str(self.description()) +unsafe impl MiniObject for Buffer { + unsafe fn as_ptr(&self) -> *mut c_void { + self.0 } -} -impl Error for BufferError { - fn description(&self) -> &str { - match *self { - BufferError::NotWritable => "Not Writable", - BufferError::NotEnoughSpace => "Not Enough Space", - BufferError::Unknown => "Unknown", - } + unsafe fn replace_ptr(&mut self, ptr: *mut c_void) { + self.0 = ptr + } + + unsafe fn new_from_ptr(ptr: *mut c_void) -> Self { + Buffer(ptr) } } impl Buffer { - pub unsafe fn new_from_ptr(raw: *mut c_void) -> Buffer { - extern "C" { - fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void; - }; - Buffer { - raw: gst_mini_object_ref(raw), - owned: true, - } - } - - pub unsafe fn new_from_ptr_owned(raw: *mut c_void) -> Buffer { - Buffer { - raw: raw, - owned: true, - } - } - - unsafe fn new_from_ptr_scoped(raw: *mut c_void) -> Buffer { - Buffer { - raw: raw, - owned: false, - } - } - - pub fn new() -> Buffer { + pub fn new() -> GstRc { extern "C" { fn gst_buffer_new() -> *mut c_void; } - let raw = unsafe { gst_buffer_new() }; - Buffer { - raw: raw, - owned: true, - } + unsafe { GstRc::new_from_owned_ptr(gst_buffer_new()) } } - pub fn new_with_size(size: usize) -> Option { + pub fn new_with_size(size: usize) -> Option> { extern "C" { fn gst_buffer_new_allocate(allocator: *const c_void, size: usize, @@ -144,10 +100,7 @@ impl Buffer { if raw.is_null() { None } else { - Some(Buffer { - raw: raw, - owned: true, - }) + Some(unsafe { GstRc::new_from_owned_ptr(raw) }) } } @@ -156,7 +109,7 @@ impl Buffer { drop(vec); } - pub fn new_from_vec(vec: Vec) -> Option { + pub fn new_from_vec(vec: Vec) -> Option> { extern "C" { fn gst_buffer_new_wrapped_full(flags: u32, data: *mut u8, @@ -186,10 +139,7 @@ impl Buffer { if raw.is_null() { None } else { - Some(Buffer { - raw: raw, - owned: true, - }) + Some(unsafe { GstRc::new_from_owned_ptr(raw) }) } } @@ -203,7 +153,7 @@ impl Buffer { let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; let res = - unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) }; + unsafe { gst_buffer_map(self.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) }; if res.to_bool() { Some(ReadBufferMap { buffer: self, @@ -223,11 +173,8 @@ impl Buffer { } let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; - let res = unsafe { - gst_buffer_map(self.raw, - &mut map_info as *mut GstMapInfo, - MAP_FLAG_READWRITE) - }; + let res = + unsafe { gst_buffer_map(self.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READWRITE) }; if res.to_bool() { Some(ReadWriteBufferMap { buffer: self, @@ -238,7 +185,7 @@ impl Buffer { } } - pub fn into_read_mapped_buffer(self) -> Option { + pub fn into_read_mapped_buffer(buffer: GstRc) -> Option { extern "C" { fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, @@ -248,10 +195,10 @@ impl Buffer { let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; let res = - unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) }; + unsafe { gst_buffer_map(buffer.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) }; if res.to_bool() { Some(ReadMappedBuffer { - buffer: self, + buffer: buffer, map_info: map_info, }) } else { @@ -259,7 +206,7 @@ impl Buffer { } } - pub fn into_readwrite_mapped_buffer(self) -> Option { + pub fn into_readwrite_mapped_buffer(buffer: GstRc) -> Option { extern "C" { fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, @@ -269,13 +216,13 @@ impl Buffer { let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; let res = unsafe { - gst_buffer_map(self.raw, + gst_buffer_map(buffer.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READWRITE) }; if res.to_bool() { Some(ReadWriteMappedBuffer { - buffer: self, + buffer: buffer, map_info: map_info, }) } else { @@ -283,67 +230,15 @@ impl Buffer { } } - pub unsafe fn into_ptr(mut self) -> *mut c_void { - extern "C" { - fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void; - }; - if !self.owned { - gst_mini_object_ref(self.raw); - } - - self.owned = false; - - self.raw - } - - pub unsafe fn as_ptr(&self) -> *mut c_void { - self.raw - } - - pub fn is_writable(&self) -> bool { - extern "C" { - fn gst_mini_object_is_writable(obj: *const c_void) -> GBoolean; - } - - let res = unsafe { gst_mini_object_is_writable(self.raw) }; - - res.to_bool() - } - - pub fn make_writable(self: Buffer) -> Buffer { - extern "C" { - fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void; - } - - let raw = unsafe { gst_mini_object_make_writable(self.raw) }; - - Buffer { - raw: raw, - owned: true, - } - } - - pub fn copy(&self) -> Buffer { - extern "C" { - fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; - } - unsafe { Buffer::new_from_ptr_owned(gst_mini_object_copy(self.raw)) } - } - - pub fn append(self, other: Buffer) -> Buffer { + pub fn append(buffer: GstRc, other: GstRc) -> GstRc { extern "C" { fn gst_buffer_append(buf1: *mut c_void, buf2: *mut c_void) -> *mut c_void; } - let raw = unsafe { gst_buffer_append(self.raw, other.raw) }; - - Buffer { - raw: raw, - owned: true, - } + unsafe { GstRc::new_from_owned_ptr(gst_buffer_append(buffer.into_ptr(), other.into_ptr())) } } - pub fn copy_region(&self, offset: usize, size: Option) -> Option { + pub fn copy_region(&self, offset: usize, size: Option) -> Option> { extern "C" { fn gst_buffer_copy_region(buf: *mut c_void, flags: BufferCopyFlags, @@ -355,28 +250,20 @@ impl Buffer { let size_real = size.unwrap_or(usize::MAX); let raw = - unsafe { gst_buffer_copy_region(self.raw, BUFFER_COPY_FLAG_ALL, offset, size_real) }; + unsafe { gst_buffer_copy_region(self.0, BUFFER_COPY_FLAG_ALL, offset, size_real) }; if raw.is_null() { None } else { - Some(Buffer { - raw: raw, - owned: true, - }) + Some(unsafe { GstRc::new_from_owned_ptr(raw) }) } } - pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), BufferError> { - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - + pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), usize> { let maxsize = self.get_maxsize(); let size = slice.len(); - if maxsize < offset || maxsize - offset < size { - return Err(BufferError::NotEnoughSpace); - } + + assert!(maxsize >= offset && maxsize - offset >= size); extern "C" { fn gst_buffer_fill(buffer: *mut c_void, @@ -388,22 +275,17 @@ impl Buffer { let copied = unsafe { let src = slice.as_ptr(); - gst_buffer_fill(self.raw, offset, src, size) + gst_buffer_fill(self.0, offset, src, size) }; - if copied < size { - Err(BufferError::Unknown) - } else { - Ok(()) - } + if copied == size { Ok(()) } else { Err(copied) } } - pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), BufferError> { + pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), usize> { let maxsize = self.get_size(); let size = slice.len(); - if maxsize < offset || maxsize - offset < size { - return Err(BufferError::NotEnoughSpace); - } + + assert!(maxsize >= offset && maxsize - offset >= size); extern "C" { fn gst_buffer_extract(buffer: *mut c_void, @@ -415,14 +297,10 @@ impl Buffer { let copied = unsafe { let src = slice.as_mut_ptr(); - gst_buffer_extract(self.raw, offset, src, size) + gst_buffer_extract(self.0, offset, src, size) }; - if copied < size { - Err(BufferError::Unknown) - } else { - Ok(()) - } + if copied == size { Ok(()) } else { Err(copied) } } pub fn get_size(&self) -> usize { @@ -430,7 +308,7 @@ impl Buffer { fn gst_buffer_get_size(obj: *const c_void) -> usize; } - unsafe { gst_buffer_get_size(self.raw) } + unsafe { gst_buffer_get_size(self.0) } } pub fn get_maxsize(&self) -> usize { @@ -446,34 +324,22 @@ impl Buffer { let mut maxsize: usize = 0; unsafe { - gst_buffer_get_sizes_range(self.raw, - 0, - -1, - ptr::null_mut(), - &mut maxsize as *mut usize); + gst_buffer_get_sizes_range(self.0, 0, -1, ptr::null_mut(), &mut maxsize as *mut usize); }; maxsize } - pub fn set_size(&mut self, size: usize) -> Result<(), BufferError> { + pub fn set_size(&mut self, size: usize) { extern "C" { fn gst_buffer_set_size(obj: *const c_void, size: usize); } - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - - if self.get_maxsize() < size { - return Err(BufferError::NotEnoughSpace); - } + assert!(self.get_maxsize() >= size); unsafe { - gst_buffer_set_size(self.raw, size); + gst_buffer_set_size(self.0, size); } - - Ok(()) } pub fn get_offset(&self) -> Option { @@ -481,7 +347,7 @@ impl Buffer { fn gst_rs_buffer_get_offset(buf: *const c_void) -> u64; } - let offset = unsafe { gst_rs_buffer_get_offset(self.raw) }; + let offset = unsafe { gst_rs_buffer_get_offset(self.0) }; if offset == u64::MAX { None @@ -490,11 +356,7 @@ impl Buffer { } } - pub fn set_offset(&mut self, offset: Option) -> Result<(), BufferError> { - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - + pub fn set_offset(&mut self, offset: Option) { extern "C" { fn gst_rs_buffer_set_offset(buf: *const c_void, offset: u64); } @@ -502,10 +364,8 @@ impl Buffer { let offset = offset.unwrap_or(u64::MAX); unsafe { - gst_rs_buffer_set_offset(self.raw, offset); + gst_rs_buffer_set_offset(self.0, offset); } - - Ok(()) } pub fn get_offset_end(&self) -> Option { @@ -513,7 +373,7 @@ impl Buffer { fn gst_rs_buffer_get_offset_end(buf: *const c_void) -> u64; } - let offset_end = unsafe { gst_rs_buffer_get_offset_end(self.raw) }; + let offset_end = unsafe { gst_rs_buffer_get_offset_end(self.0) }; if offset_end == u64::MAX { None @@ -522,11 +382,7 @@ impl Buffer { } } - pub fn set_offset_end(&mut self, offset_end: Option) -> Result<(), BufferError> { - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - + pub fn set_offset_end(&mut self, offset_end: Option) { extern "C" { fn gst_rs_buffer_set_offset_end(buf: *const c_void, offset_end: u64); } @@ -534,10 +390,8 @@ impl Buffer { let offset_end = offset_end.unwrap_or(u64::MAX); unsafe { - gst_rs_buffer_set_offset_end(self.raw, offset_end); + gst_rs_buffer_set_offset_end(self.0, offset_end); } - - Ok(()) } pub fn get_pts(&self) -> Option { @@ -545,16 +399,12 @@ impl Buffer { fn gst_rs_buffer_get_pts(buf: *const c_void) -> u64; } - let pts = unsafe { gst_rs_buffer_get_pts(self.raw) }; + let pts = unsafe { gst_rs_buffer_get_pts(self.0) }; if pts == u64::MAX { None } else { Some(pts) } } - pub fn set_pts(&mut self, pts: Option) -> Result<(), BufferError> { - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - + pub fn set_pts(&mut self, pts: Option) { extern "C" { fn gst_rs_buffer_set_pts(buf: *const c_void, pts: u64); } @@ -562,10 +412,8 @@ impl Buffer { let pts = pts.unwrap_or(u64::MAX); unsafe { - gst_rs_buffer_set_pts(self.raw, pts); + gst_rs_buffer_set_pts(self.0, pts); } - - Ok(()) } pub fn get_dts(&self) -> Option { @@ -573,16 +421,12 @@ impl Buffer { fn gst_rs_buffer_get_dts(buf: *const c_void) -> u64; } - let dts = unsafe { gst_rs_buffer_get_dts(self.raw) }; + let dts = unsafe { gst_rs_buffer_get_dts(self.0) }; if dts == u64::MAX { None } else { Some(dts) } } - pub fn set_dts(&mut self, dts: Option) -> Result<(), BufferError> { - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - + pub fn set_dts(&mut self, dts: Option) { extern "C" { fn gst_rs_buffer_set_dts(buf: *const c_void, dts: u64); } @@ -590,10 +434,34 @@ impl Buffer { let dts = dts.unwrap_or(u64::MAX); unsafe { - gst_rs_buffer_set_dts(self.raw, dts); + gst_rs_buffer_set_dts(self.0, dts); + } + } + + pub fn get_duration(&self) -> Option { + extern "C" { + fn gst_rs_buffer_get_duration(buf: *const c_void) -> u64; } - Ok(()) + let duration = unsafe { gst_rs_buffer_get_duration(self.0) }; + + if duration == u64::MAX { + None + } else { + Some(duration) + } + } + + pub fn set_duration(&mut self, duration: Option) { + extern "C" { + fn gst_rs_buffer_set_duration(buf: *const c_void, duration: u64); + } + + let duration = duration.unwrap_or(u64::MAX); + + unsafe { + gst_rs_buffer_set_duration(self.0, duration); + } } pub fn get_flags(&self) -> BufferFlags { @@ -601,34 +469,16 @@ impl Buffer { fn gst_rs_buffer_get_flags(buf: *const c_void) -> BufferFlags; } - unsafe { gst_rs_buffer_get_flags(self.raw) } + unsafe { gst_rs_buffer_get_flags(self.0) } } - pub fn set_flags(&mut self, flags: BufferFlags) -> Result<(), BufferError> { - if !self.is_writable() { - return Err(BufferError::NotWritable); - } - + pub fn set_flags(&mut self, flags: BufferFlags) { extern "C" { fn gst_rs_buffer_set_flags(buf: *const c_void, flags: BufferFlags); } unsafe { - gst_rs_buffer_set_flags(self.raw, flags); - } - - Ok(()) - } -} - -impl Drop for Buffer { - fn drop(&mut self) { - extern "C" { - fn gst_mini_object_unref(obj: *mut c_void); - } - - if self.owned && !self.raw.is_null() { - unsafe { gst_mini_object_unref(self.raw) } + gst_rs_buffer_set_flags(self.0, flags); } } } @@ -636,21 +486,6 @@ impl Drop for Buffer { unsafe impl Sync for Buffer {} unsafe impl Send for Buffer {} -impl Clone for Buffer { - fn clone(&self) -> Buffer { - extern "C" { - fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void; - } - - let raw = unsafe { gst_mini_object_ref(self.raw) }; - - Buffer { - raw: raw, - owned: true, - } - } -} - impl PartialEq for Buffer { fn eq(&self, other: &Buffer) -> bool { if self.get_size() != other.get_size() { @@ -677,6 +512,10 @@ impl<'a> ReadBufferMap<'a> { pub fn get_size(&self) -> usize { self.map_info.size } + + pub fn get_buffer(&self) -> &Buffer { + self.buffer + } } impl<'a> Drop for ReadBufferMap<'a> { @@ -686,7 +525,7 @@ impl<'a> Drop for ReadBufferMap<'a> { }; unsafe { - gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo); + gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo); } } } @@ -703,6 +542,10 @@ impl<'a> ReadWriteBufferMap<'a> { pub fn get_size(&self) -> usize { self.map_info.size } + + pub fn get_buffer(&self) -> &Buffer { + self.buffer + } } impl<'a> Drop for ReadWriteBufferMap<'a> { @@ -712,7 +555,7 @@ impl<'a> Drop for ReadWriteBufferMap<'a> { }; unsafe { - gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo); + gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo); } } } @@ -727,7 +570,7 @@ impl ReadMappedBuffer { } pub fn get_buffer(&self) -> &Buffer { - &self.buffer + self.buffer.as_ref() } } @@ -737,9 +580,9 @@ impl Drop for ReadMappedBuffer { fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo); }; - if !self.buffer.raw.is_null() { + if !self.buffer.0.is_null() { unsafe { - gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo); + gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo); } } } @@ -762,7 +605,7 @@ impl ReadWriteMappedBuffer { } pub fn get_buffer(&self) -> &Buffer { - &self.buffer + self.buffer.as_ref() } } @@ -772,9 +615,9 @@ impl Drop for ReadWriteMappedBuffer { fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo); }; - if !self.buffer.raw.is_null() { + if !self.buffer.0.is_null() { unsafe { - gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo); + gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo); } } } @@ -783,38 +626,6 @@ impl Drop for ReadWriteMappedBuffer { unsafe impl Sync for ReadWriteMappedBuffer {} unsafe impl Send for ReadWriteMappedBuffer {} -#[repr(C)] -pub struct ScopedBufferPtr(*mut c_void); - -pub struct ScopedBuffer<'a> { - buffer: Buffer, - #[allow(dead_code)] - phantom: PhantomData<&'a ScopedBufferPtr>, -} - -impl<'a> ScopedBuffer<'a> { - pub unsafe fn new(ptr: &'a ScopedBufferPtr) -> ScopedBuffer<'a> { - ScopedBuffer { - buffer: Buffer::new_from_ptr_scoped(ptr.0), - phantom: PhantomData, - } - } -} - -impl<'a> Deref for ScopedBuffer<'a> { - type Target = Buffer; - - fn deref(&self) -> &Self::Target { - &self.buffer - } -} - -impl<'a> DerefMut for ScopedBuffer<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.buffer - } -} - bitflags! { #[repr(C)] flags MapFlags: u32 { diff --git a/gst-plugin/src/caps.rs b/gst-plugin/src/caps.rs index 4325a34a..2f326524 100644 --- a/gst-plugin/src/caps.rs +++ b/gst-plugin/src/caps.rs @@ -22,28 +22,43 @@ use std::ffi::CStr; use std::fmt; use value::*; use utils::*; +use miniobject::*; #[derive(Eq)] pub struct Caps(*mut c_void); +unsafe impl MiniObject for Caps { + unsafe fn as_ptr(&self) -> *mut c_void { + self.0 + } + + unsafe fn replace_ptr(&mut self, ptr: *mut c_void) { + self.0 = ptr + } + + unsafe fn new_from_ptr(ptr: *mut c_void) -> Self { + Caps(ptr) + } +} + impl Caps { - pub fn new_empty() -> Self { + pub fn new_empty() -> GstRc { extern "C" { fn gst_caps_new_empty() -> *mut c_void; } - Caps(unsafe { gst_caps_new_empty() }) + unsafe { GstRc::new_from_owned_ptr(gst_caps_new_empty()) } } - pub fn new_any() -> Self { + pub fn new_any() -> GstRc { extern "C" { fn gst_caps_new_any() -> *mut c_void; } - Caps(unsafe { gst_caps_new_any() }) + unsafe { GstRc::new_from_owned_ptr(gst_caps_new_any()) } } - pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> Self { + pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc { extern "C" { fn gst_caps_append_structure(caps: *mut c_void, structure: *mut c_void); fn gst_structure_new_empty(name: *const c_char) -> *mut c_void; @@ -55,35 +70,29 @@ impl Caps { let structure = unsafe { gst_structure_new_empty(name_cstr.as_ptr()) }; unsafe { - gst_caps_append_structure(caps.0, structure); + gst_caps_append_structure(caps.as_ptr(), structure); } - caps.set_simple(values); + caps.get_mut().unwrap().set_simple(values); caps } - pub unsafe fn new_from_ptr(ptr: *mut c_void) -> Caps { - extern "C" { - fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void; - } - - Caps(gst_mini_object_ref(ptr)) - } - - pub fn from_string(value: &str) -> Option { + pub fn from_string(value: &str) -> Option> { extern "C" { fn gst_caps_from_string(value: *const c_char) -> *mut c_void; } let value_cstr = CString::new(value).unwrap(); - let caps_ptr = unsafe { gst_caps_from_string(value_cstr.as_ptr()) }; + unsafe { + let caps_ptr = gst_caps_from_string(value_cstr.as_ptr()); - if caps_ptr.is_null() { - None - } else { - Some(Caps(caps_ptr)) + if caps_ptr.is_null() { + None + } else { + Some(GstRc::new_from_owned_ptr(caps_ptr)) + } } } @@ -116,47 +125,6 @@ impl Caps { s } } - - pub unsafe fn as_ptr(&self) -> *const c_void { - self.0 - } - - pub fn make_writable(self: Caps) -> Caps { - extern "C" { - fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void; - } - - let raw = unsafe { gst_mini_object_make_writable(self.0) }; - - Caps(raw) - } - - pub fn copy(&self) -> Caps { - extern "C" { - fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; - } - unsafe { Caps(gst_mini_object_copy(self.0)) } - } -} - -impl Clone for Caps { - fn clone(&self) -> Self { - extern "C" { - fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void; - } - - unsafe { Caps(gst_mini_object_ref(self.0)) } - } -} - -impl Drop for Caps { - fn drop(&mut self) { - extern "C" { - fn gst_mini_object_unref(mini_object: *mut c_void); - } - - unsafe { gst_mini_object_unref(self.0) } - } } impl fmt::Debug for Caps { @@ -175,10 +143,12 @@ impl PartialEq for Caps { } } +unsafe impl Sync for Caps {} +unsafe impl Send for Caps {} + #[cfg(test)] mod tests { use super::*; - use value::*; use std::ptr; use std::os::raw::c_void; diff --git a/gst-plugin/src/demuxer.rs b/gst-plugin/src/demuxer.rs index 5f350a18..2556415e 100644 --- a/gst-plugin/src/demuxer.rs +++ b/gst-plugin/src/demuxer.rs @@ -32,6 +32,7 @@ use slog::*; use utils::*; use error::*; use buffer::*; +use miniobject::*; use log::*; use caps::Caps; use plugin::Plugin; @@ -57,7 +58,7 @@ pub enum HandleBufferResult { StreamsChanged(Vec), // TODO need something to replace/add new streams // TODO should probably directly implement the GstStreams new world order - BufferForStream(StreamIndex, Buffer), + BufferForStream(StreamIndex, GstRc), Eos(Option), } @@ -69,7 +70,9 @@ pub trait Demuxer { fn stop(&mut self) -> Result<(), ErrorMessage>; fn seek(&mut self, start: u64, stop: Option) -> Result; - fn handle_buffer(&mut self, buffer: Option) -> Result; + fn handle_buffer(&mut self, + buffer: Option>) + -> Result; fn end_of_stream(&mut self) -> Result<(), ErrorMessage>; fn is_seekable(&self) -> bool; @@ -80,12 +83,12 @@ pub trait Demuxer { #[derive(Debug)] pub struct Stream { pub index: StreamIndex, - pub caps: Caps, + pub caps: GstRc, pub stream_id: String, } impl Stream { - pub fn new(index: StreamIndex, caps: Caps, stream_id: String) -> Stream { + pub fn new(index: StreamIndex, caps: GstRc, stream_id: String) -> Stream { Stream { index: index, caps: caps, @@ -250,7 +253,7 @@ impl DemuxerWrapper { } } - fn handle_buffer(&self, buffer: Buffer) -> GstFlowReturn { + fn handle_buffer(&self, buffer: GstRc) -> GstFlowReturn { extern "C" { fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32); fn gst_rs_demuxer_add_stream(raw: *mut c_void, @@ -474,7 +477,7 @@ pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper, let wrap: &mut DemuxerWrapper = &mut *ptr; panic_to_error!(wrap, GstFlowReturn::Error, { - let buffer = Buffer::new_from_ptr_owned(buffer); + let buffer = GstRc::new_from_owned_ptr(buffer); wrap.handle_buffer(buffer) }) } diff --git a/gst-plugin/src/lib.rs b/gst-plugin/src/lib.rs index 1ec94b79..893b41ec 100644 --- a/gst-plugin/src/lib.rs +++ b/gst-plugin/src/lib.rs @@ -44,3 +44,4 @@ pub mod caps; pub mod bytes; pub mod tags; pub mod streams; +pub mod miniobject; diff --git a/gst-plugin/src/miniobject.rs b/gst-plugin/src/miniobject.rs new file mode 100644 index 00000000..1419b6d0 --- /dev/null +++ b/gst-plugin/src/miniobject.rs @@ -0,0 +1,231 @@ +// Copyright (C) 2016 Sebastian Dröge +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301, USA. + +use std::os::raw::c_void; +use std::{fmt, ops, borrow, ptr}; +use std::marker::PhantomData; +use utils::*; + +#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GstRc { + obj: T, +} + +impl GstRc { + unsafe fn new(obj: T, owned: bool) -> Self { + extern "C" { + fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void; + } + + assert!(!obj.as_ptr().is_null()); + + if !owned { + gst_mini_object_ref(obj.as_ptr()); + } + + GstRc { obj: obj } + } + + pub unsafe fn new_from_owned_ptr(ptr: *mut c_void) -> Self { + Self::new(T::new_from_ptr(ptr), true) + } + + pub unsafe fn new_from_unowned_ptr(ptr: *mut c_void) -> Self { + Self::new(T::new_from_ptr(ptr), false) + } + + pub fn make_mut(&mut self) -> &mut T { + extern "C" { + fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void; + } + unsafe { + let ptr = self.obj.as_ptr(); + + if self.is_writable() { + return &mut self.obj; + } + + self.obj.replace_ptr(gst_mini_object_make_writable(ptr)); + assert!(self.is_writable()); + + &mut self.obj + } + } + + pub fn get_mut(&mut self) -> Option<&mut T> { + if self.is_writable() { + Some(&mut self.obj) + } else { + None + } + } + + pub fn copy(&self) -> Self { + extern "C" { + fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; + } + unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) } + } + + pub unsafe fn into_ptr(mut self) -> *mut c_void { + self.obj.swap_ptr(ptr::null_mut()) + } +} + +impl ops::Deref for GstRc { + type Target = T; + fn deref(&self) -> &T { + &self.obj + } +} + +impl AsRef for GstRc { + fn as_ref(&self) -> &T { + &self.obj + } +} + +impl borrow::Borrow for GstRc { + fn borrow(&self) -> &T { + &self.obj + } +} + +impl Clone for GstRc { + fn clone(&self) -> GstRc { + unsafe { GstRc::new_from_unowned_ptr(self.obj.as_ptr()) } + } +} + +impl Drop for GstRc { + fn drop(&mut self) { + extern "C" { + fn gst_mini_object_unref(obj: *mut c_void) -> *mut c_void; + } + + unsafe { + if !self.obj.as_ptr().is_null() { + gst_mini_object_unref(self.obj.as_ptr()); + } + } + } +} + +unsafe impl Sync for GstRc {} +unsafe impl Send for GstRc {} + +impl fmt::Display for GstRc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.obj.fmt(f) + } +} + +// NOTE: Reference counting must not happen in here +pub unsafe trait MiniObject { + unsafe fn as_ptr(&self) -> *mut c_void; + unsafe fn replace_ptr(&mut self, ptr: *mut c_void); + unsafe fn swap_ptr(&mut self, new_ptr: *mut c_void) -> *mut c_void { + let ptr = self.as_ptr(); + self.replace_ptr(new_ptr); + + ptr + } + + unsafe fn new_from_ptr(ptr: *mut c_void) -> Self; + + fn is_writable(&self) -> bool { + extern "C" { + fn gst_mini_object_is_writable(obj: *mut c_void) -> GBoolean; + } + unsafe { gst_mini_object_is_writable(self.as_ptr()).to_bool() } + } +} + +impl<'a, T: MiniObject> From<&'a T> for GstRc { + fn from(f: &'a T) -> GstRc { + unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) } + } +} + +impl<'a, T: MiniObject> From<&'a mut T> for GstRc { + fn from(f: &'a mut T) -> GstRc { + unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) } + } +} + +#[repr(C)] +pub struct GstRefPtr(*mut c_void); + +#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GstRef<'a, T: MiniObject> { + obj: T, + #[allow(dead_code)] + phantom: PhantomData<&'a GstRefPtr>, +} + +impl<'a, T: MiniObject> GstRef<'a, T> { + pub unsafe fn new(ptr: &'a GstRefPtr) -> GstRef<'a, T> { + GstRef { + obj: T::new_from_ptr(ptr.0), + phantom: PhantomData, + } + } + + pub fn get_mut(&mut self) -> Option<&mut T> { + if self.is_writable() { + Some(&mut self.obj) + } else { + None + } + } + + pub fn copy(&self) -> GstRc { + extern "C" { + fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; + } + unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) } + } + + pub unsafe fn into_ptr(mut self) -> *mut c_void { + self.obj.swap_ptr(ptr::null_mut()) + } +} + +impl<'a, T: MiniObject> ops::Deref for GstRef<'a, T> { + type Target = T; + fn deref(&self) -> &T { + &self.obj + } +} + +impl<'a, T: MiniObject> AsRef for GstRef<'a, T> { + fn as_ref(&self) -> &T { + &self.obj + } +} + +impl<'a, T: MiniObject> borrow::Borrow for GstRef<'a, T> { + fn borrow(&self) -> &T { + &self.obj + } +} + +impl<'a, T: MiniObject + fmt::Display> fmt::Display for GstRef<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.obj.fmt(f) + } +} diff --git a/gst-plugin/src/sink.rs b/gst-plugin/src/sink.rs index 645666e2..c3d3e871 100644 --- a/gst-plugin/src/sink.rs +++ b/gst-plugin/src/sink.rs @@ -33,6 +33,7 @@ use slog::*; use utils::*; use error::*; use buffer::*; +use miniobject::*; use log::*; use plugin::Plugin; @@ -270,13 +271,11 @@ pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> GBoolean { } #[no_mangle] -pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, - buffer: ScopedBufferPtr) - -> GstFlowReturn { +pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, buffer: GstRefPtr) -> GstFlowReturn { let wrap: &SinkWrapper = &*ptr; panic_to_error!(wrap, GstFlowReturn::Error, { - let buffer = ScopedBuffer::new(&buffer); - wrap.render(&*buffer) + let buffer: GstRef = GstRef::new(&buffer); + wrap.render(buffer.as_ref()) }) } diff --git a/gst-plugin/src/source.rs b/gst-plugin/src/source.rs index d632f6b0..b4447ea2 100644 --- a/gst-plugin/src/source.rs +++ b/gst-plugin/src/source.rs @@ -34,6 +34,7 @@ use plugin::Plugin; use utils::*; use error::*; use buffer::*; +use miniobject::*; use log::*; #[derive(Debug)] @@ -323,13 +324,13 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean { pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper, offset: u64, length: u32, - buffer: ScopedBufferPtr) + buffer: GstRefPtr) -> GstFlowReturn { let wrap: &SourceWrapper = &*ptr; panic_to_error!(wrap, GstFlowReturn::Error, { - let mut buffer = ScopedBuffer::new(&buffer); - wrap.fill(offset, length, &mut *buffer) + let mut buffer: GstRef = GstRef::new(&buffer); + wrap.fill(offset, length, buffer.get_mut().unwrap()) }) } diff --git a/gst-plugin/src/streams.rs b/gst-plugin/src/streams.rs index 9dac5bcc..18337b32 100644 --- a/gst-plugin/src/streams.rs +++ b/gst-plugin/src/streams.rs @@ -20,6 +20,7 @@ use std::ptr; use libc::c_char; use std::ffi::{CStr, CString}; use caps::Caps; +use miniobject::*; use tags::TagList; pub struct Stream(*mut c_void); @@ -46,7 +47,11 @@ bitflags! { } impl Stream { - pub fn new(stream_id: &str, caps: Option, t: StreamType, flags: StreamFlags) -> Self { + pub fn new(stream_id: &str, + caps: Option>, + t: StreamType, + flags: StreamFlags) + -> Self { extern "C" { fn gst_stream_new(stream_id: *const c_char, caps: *const c_void, @@ -65,7 +70,7 @@ impl Stream { self.0 } - pub fn get_caps(&self) -> Option { + pub fn get_caps(&self) -> Option> { extern "C" { fn gst_stream_get_caps(stream: *mut c_void) -> *mut c_void; } @@ -76,7 +81,7 @@ impl Stream { return None; } - Some(unsafe { Caps::new_from_ptr(ptr) }) + Some(unsafe { GstRc::new_from_owned_ptr(ptr) }) } pub fn get_stream_flags(&self) -> StreamFlags { @@ -118,7 +123,7 @@ impl Stream { Some(unsafe { TagList::new_from_ptr(ptr) }) } - pub fn set_caps(&self, caps: Option) { + pub fn set_caps(&self, caps: Option>) { extern "C" { fn gst_stream_set_caps(stream: *mut c_void, caps: *mut c_void); } diff --git a/gst-plugin/src/tags.rs b/gst-plugin/src/tags.rs index 189cf79d..f363da15 100644 --- a/gst-plugin/src/tags.rs +++ b/gst-plugin/src/tags.rs @@ -21,6 +21,7 @@ use libc::c_char; use std::ffi::{CStr, CString}; use utils::*; use value::*; +use miniobject::*; pub trait Tag { type TagType: ValueType; @@ -65,21 +66,27 @@ pub enum MergeMode { #[derive(Eq)] pub struct TagList(*mut c_void); +unsafe impl MiniObject for TagList { + unsafe fn as_ptr(&self) -> *mut c_void { + self.0 + } + + unsafe fn replace_ptr(&mut self, ptr: *mut c_void) { + self.0 = ptr + } + + unsafe fn new_from_ptr(ptr: *mut c_void) -> Self { + TagList(ptr) + } +} + impl TagList { - pub fn new() -> Self { + pub fn new() -> GstRc { extern "C" { fn gst_tag_list_new_empty() -> *mut c_void; } - TagList(unsafe { gst_tag_list_new_empty() }) - } - - pub unsafe fn new_from_ptr(ptr: *mut c_void) -> TagList { - extern "C" { - fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void; - } - - TagList(gst_mini_object_ref(ptr)) + unsafe { GstRc::new_from_owned_ptr(gst_tag_list_new_empty()) } } pub fn add(&mut self, value: T::TagType, mode: MergeMode) @@ -104,7 +111,7 @@ impl TagList { } } - pub fn get(&mut self) -> Option> + pub fn get(&self) -> Option> where Value: From<::TagType> { extern "C" { @@ -145,47 +152,6 @@ impl TagList { s } } - - pub unsafe fn as_ptr(&self) -> *const c_void { - self.0 - } - - pub fn make_writable(self: TagList) -> TagList { - extern "C" { - fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void; - } - - let raw = unsafe { gst_mini_object_make_writable(self.0) }; - - TagList(raw) - } - - pub fn copy(&self) -> TagList { - extern "C" { - fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; - } - unsafe { TagList(gst_mini_object_copy(self.0)) } - } -} - -impl Clone for TagList { - fn clone(&self) -> Self { - extern "C" { - fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void; - } - - unsafe { TagList(gst_mini_object_ref(self.0)) } - } -} - -impl Drop for TagList { - fn drop(&mut self) { - extern "C" { - fn gst_mini_object_unref(mini_object: *mut c_void); - } - - unsafe { gst_mini_object_unref(self.0) } - } } impl fmt::Debug for TagList { @@ -204,10 +170,12 @@ impl PartialEq for TagList { } } +unsafe impl Sync for TagList {} +unsafe impl Send for TagList {} + #[cfg(test)] mod tests { use super::*; - use value::*; use std::ptr; use std::os::raw::c_void; @@ -227,8 +195,11 @@ mod tests { let mut tags = TagList::new(); assert_eq!(tags.to_string(), "taglist;"); - tags.add::("some title".into(), MergeMode::Append); - tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append); + { + let tags = tags.get_mut().unwrap(); + tags.add::<Title>("some title".into(), MergeMode::Append); + tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append); + } assert_eq!(tags.to_string(), "taglist, title=(string)\"some\\ title\", duration=(guint64)120000000000;"); } @@ -239,10 +210,14 @@ mod tests { let mut tags = TagList::new(); assert_eq!(tags.to_string(), "taglist;"); - tags.add::<Title>("some title".into(), MergeMode::Append); - tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append); + { + let tags = tags.get_mut().unwrap(); + tags.add::<Title>("some title".into(), MergeMode::Append); + tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append); + } assert_eq!(*tags.get::<Title>().unwrap(), "some title"); - assert_eq!(*tags.get::<Duration>().unwrap(), (1000u64 * 1000 * 1000 * 120)); + assert_eq!(*tags.get::<Duration>().unwrap(), + (1000u64 * 1000 * 1000 * 120)); } } diff --git a/gst-plugin/src/value.rs b/gst-plugin/src/value.rs index 2e63977a..857f7837 100644 --- a/gst-plugin/src/value.rs +++ b/gst-plugin/src/value.rs @@ -25,6 +25,7 @@ use std::ops::Deref; pub use num_rational::Rational32; use buffer::*; +use miniobject::*; #[derive(Debug, PartialEq, Eq, Clone)] pub enum Value { @@ -35,7 +36,7 @@ pub enum Value { UInt64(u64), String(String), Fraction(Rational32), - Buffer(Buffer), + Buffer(GstRc<Buffer>), Array(Vec<Value>), } @@ -63,7 +64,7 @@ impl_value_type!(i64, Int64); impl_value_type!(u64, UInt64); impl_value_type!(String, String); impl_value_type!(Rational32, Fraction); -impl_value_type!(Buffer, Buffer); +impl_value_type!(GstRc<Buffer>, Buffer); impl_value_type!(Vec<Value>, Array); #[repr(C)] @@ -74,9 +75,7 @@ pub struct GValue { impl GValue { pub fn new() -> GValue { - let gvalue: GValue = unsafe { mem::zeroed() }; - - gvalue + unsafe { mem::zeroed() } } } @@ -234,7 +233,7 @@ impl Value { return None; } - Some(Value::Buffer(Buffer::new_from_ptr(b))) + Some(Value::Buffer(GstRc::new_from_unowned_ptr(b))) }, typ if typ == *TYPE_GST_VALUE_ARRAY => unsafe { let n = gst_value_array_get_size(gvalue as *const GValue); @@ -320,15 +319,15 @@ impl From<(i32, i32)> for Value { } } -impl From<Buffer> for Value { - fn from(f: Buffer) -> Value { +impl From<GstRc<Buffer>> for Value { + fn from(f: GstRc<Buffer>) -> Value { Value::Buffer(f) } } impl<'a> From<&'a Buffer> for Value { fn from(f: &'a Buffer) -> Value { - Value::Buffer(f.clone()) + Value::Buffer(f.into()) } }