Implement GstRc/GstRef wrapper for GstMiniObject

Keeps the miniobject specific code local and provides a more similar API
to Rc/Arc. Also makes it impossible to accidentially try writing to an
unwritable miniobject.
This commit is contained in:
Sebastian Dröge 2017-02-03 16:34:17 +02:00
parent 99a9b7fedc
commit 7b5764e759
15 changed files with 505 additions and 493 deletions

View file

@ -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(())
}

View file

@ -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<Metadata>,
aac_sequence_header: Option<Buffer>,
avc_sequence_header: Option<Buffer>,
aac_sequence_header: Option<GstRc<Buffer>>,
avc_sequence_header: Option<GstRc<Buffer>>,
}
impl StreamingState {
@ -89,7 +90,7 @@ struct AudioFormat {
width: u8,
channels: u8,
bitrate: Option<u32>,
aac_sequence_header: Option<Buffer>,
aac_sequence_header: Option<GstRc<Buffer>>,
}
// Ignores bitrate
@ -104,7 +105,7 @@ impl PartialEq for AudioFormat {
impl AudioFormat {
fn new(data_header: &flavors::AudioDataHeader,
metadata: &Option<Metadata>,
aac_sequence_header: &Option<Buffer>)
aac_sequence_header: &Option<GstRc<Buffer>>)
-> 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<Caps> {
fn to_caps(&self) -> Option<GstRc<Caps>> {
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<Rational32>,
framerate: Option<Rational32>,
bitrate: Option<u32>,
avc_sequence_header: Option<Buffer>,
avc_sequence_header: Option<GstRc<Buffer>>,
}
impl VideoFormat {
fn new(data_header: &flavors::VideoDataHeader,
metadata: &Option<Metadata>,
avc_sequence_header: &Option<Buffer>)
avc_sequence_header: &Option<GstRc<Buffer>>)
-> 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<Caps> {
fn to_caps(&self) -> Option<GstRc<Caps>> {
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<Buffer>) -> Result<HandleBufferResult, FlowError> {
fn handle_buffer(&mut self,
buffer: Option<GstRc<Buffer>>)
-> Result<HandleBufferResult, FlowError> {
if let Some(buffer) = buffer {
self.adapter.push(buffer);
}

View file

@ -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(())
}

View file

@ -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<Buffer>) {
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<Buffer, AdapterError> {
pub fn get_buffer(&mut self, size: usize) -> Result<GstRc<Buffer>, 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;

View file

@ -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)
{

View file

@ -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<Buffer>,
map_info: GstMapInfo,
}
#[derive(Debug)]
pub struct ReadWriteMappedBuffer {
buffer: Buffer,
buffer: GstRc<Buffer>,
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<Buffer> {
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<Buffer> {
pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> {
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<u8>) -> Option<Buffer> {
pub fn new_from_vec(vec: Vec<u8>) -> Option<GstRc<Buffer>> {
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<ReadMappedBuffer> {
pub fn into_read_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadMappedBuffer> {
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<ReadWriteMappedBuffer> {
pub fn into_readwrite_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadWriteMappedBuffer> {
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<Buffer>, other: GstRc<Buffer>) -> GstRc<Buffer> {
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<usize>) -> Option<Buffer> {
pub fn copy_region(&self, offset: usize, size: Option<usize>) -> Option<GstRc<Buffer>> {
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<u64> {
@ -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<u64>) -> Result<(), BufferError> {
if !self.is_writable() {
return Err(BufferError::NotWritable);
}
pub fn set_offset(&mut self, offset: Option<u64>) {
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<u64> {
@ -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<u64>) -> Result<(), BufferError> {
if !self.is_writable() {
return Err(BufferError::NotWritable);
}
pub fn set_offset_end(&mut self, offset_end: Option<u64>) {
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<u64> {
@ -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<u64>) -> Result<(), BufferError> {
if !self.is_writable() {
return Err(BufferError::NotWritable);
}
pub fn set_pts(&mut self, pts: Option<u64>) {
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<u64> {
@ -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<u64>) -> Result<(), BufferError> {
if !self.is_writable() {
return Err(BufferError::NotWritable);
}
pub fn set_dts(&mut self, dts: Option<u64>) {
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<u64> {
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<u64>) {
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 {

View file

@ -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<Self> {
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<Self> {
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<Self> {
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<Self> {
pub fn from_string(value: &str) -> Option<GstRc<Self>> {
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;

View file

@ -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<Stream>),
// TODO need something to replace/add new streams
// TODO should probably directly implement the GstStreams new world order
BufferForStream(StreamIndex, Buffer),
BufferForStream(StreamIndex, GstRc<Buffer>),
Eos(Option<StreamIndex>),
}
@ -69,7 +70,9 @@ pub trait Demuxer {
fn stop(&mut self) -> Result<(), ErrorMessage>;
fn seek(&mut self, start: u64, stop: Option<u64>) -> Result<SeekResult, ErrorMessage>;
fn handle_buffer(&mut self, buffer: Option<Buffer>) -> Result<HandleBufferResult, FlowError>;
fn handle_buffer(&mut self,
buffer: Option<GstRc<Buffer>>)
-> Result<HandleBufferResult, FlowError>;
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<Caps>,
pub stream_id: String,
}
impl Stream {
pub fn new(index: StreamIndex, caps: Caps, stream_id: String) -> Stream {
pub fn new(index: StreamIndex, caps: GstRc<Caps>, 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<Buffer>) -> 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)
})
}

View file

@ -44,3 +44,4 @@ pub mod caps;
pub mod bytes;
pub mod tags;
pub mod streams;
pub mod miniobject;

View file

@ -0,0 +1,231 @@
// Copyright (C) 2016 Sebastian Dröge <sebastian@centricular.com>
//
// 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<T: MiniObject> {
obj: T,
}
impl<T: MiniObject> GstRc<T> {
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<T: MiniObject> ops::Deref for GstRc<T> {
type Target = T;
fn deref(&self) -> &T {
&self.obj
}
}
impl<T: MiniObject> AsRef<T> for GstRc<T> {
fn as_ref(&self) -> &T {
&self.obj
}
}
impl<T: MiniObject> borrow::Borrow<T> for GstRc<T> {
fn borrow(&self) -> &T {
&self.obj
}
}
impl<T: MiniObject> Clone for GstRc<T> {
fn clone(&self) -> GstRc<T> {
unsafe { GstRc::new_from_unowned_ptr(self.obj.as_ptr()) }
}
}
impl<T: MiniObject> Drop for GstRc<T> {
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<T: MiniObject + Sync> Sync for GstRc<T> {}
unsafe impl<T: MiniObject + Send> Send for GstRc<T> {}
impl<T: MiniObject + fmt::Display> fmt::Display for GstRc<T> {
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<T> {
fn from(f: &'a T) -> GstRc<T> {
unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) }
}
}
impl<'a, T: MiniObject> From<&'a mut T> for GstRc<T> {
fn from(f: &'a mut T) -> GstRc<T> {
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<T> {
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<T> for GstRef<'a, T> {
fn as_ref(&self) -> &T {
&self.obj
}
}
impl<'a, T: MiniObject> borrow::Borrow<T> 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)
}
}

View file

@ -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<Buffer> = GstRef::new(&buffer);
wrap.render(buffer.as_ref())
})
}

View file

@ -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<Buffer> = GstRef::new(&buffer);
wrap.fill(offset, length, buffer.get_mut().unwrap())
})
}

View file

@ -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<Caps>, t: StreamType, flags: StreamFlags) -> Self {
pub fn new(stream_id: &str,
caps: Option<GstRc<Caps>>,
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<Caps> {
pub fn get_caps(&self) -> Option<GstRc<Caps>> {
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<Caps>) {
pub fn set_caps(&self, caps: Option<GstRc<Caps>>) {
extern "C" {
fn gst_stream_set_caps(stream: *mut c_void, caps: *mut c_void);
}

View file

@ -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<Self> {
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<T: Tag>(&mut self, value: T::TagType, mode: MergeMode)
@ -104,7 +111,7 @@ impl TagList {
}
}
pub fn get<T: Tag>(&mut self) -> Option<TypedValue<T::TagType>>
pub fn get<T: Tag>(&self) -> Option<TypedValue<T::TagType>>
where Value: From<<T as Tag>::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::<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.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));
}
}

View file

@ -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())
}
}