From 61b54201023f4d0d91cd2a7b5cb3ae4ebb6968ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 12 Sep 2016 15:00:28 +0200 Subject: [PATCH] Add wrapper around GstBuffer and use it in the source/sink --- src/buffer.rs | 470 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/plugin.c | 48 +++++ src/rsfilesink.rs | 12 +- src/rsfilesrc.rs | 32 +++- src/rshttpsrc.rs | 33 +++- src/rssink.c | 7 +- src/rssink.rs | 11 +- src/rssource.c | 17 +- src/rssource.rs | 18 +- src/utils.rs | 4 + 11 files changed, 604 insertions(+), 49 deletions(-) create mode 100644 src/buffer.rs diff --git a/src/buffer.rs b/src/buffer.rs new file mode 100644 index 00000000..6ac413e4 --- /dev/null +++ b/src/buffer.rs @@ -0,0 +1,470 @@ +// 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::ptr; +use std::mem; +use std::os::raw::c_void; +use std::slice; +use std::marker::PhantomData; +use std::u64; +use std::fmt::{Display, Formatter}; +use std::fmt::Error as FmtError; +use std::error::Error; +use std::ops::{Deref, DerefMut}; + +use utils::*; + +pub struct Buffer { + raw: *mut c_void, + owned: bool, +} + +#[repr(C)] +struct GstMapInfo { + memory: *mut c_void, + flags: i32, + data: *mut c_void, + size: usize, + maxsize: usize, + user_data: [*mut c_void; 4], + _gst_reserved: [*const c_void; 4], +} + +pub struct ReadBufferMap<'a> { + buffer: &'a Buffer, + map_info: GstMapInfo, +} + +pub struct ReadWriteBufferMap<'a> { + buffer: &'a Buffer, + map_info: GstMapInfo, +} + +#[derive(Debug)] +pub enum BufferError { + NotWritable, + NotEnoughSpace, +} + +impl Display for BufferError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + f.write_str(self.description()) + } +} + +impl Error for BufferError { + fn description(&self) -> &str { + match *self { + BufferError::NotWritable => "Not Writable", + BufferError::NotEnoughSpace => "Not Enough Space", + } + } +} + +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_with_size(size: usize) -> Option { + extern "C" { + fn gst_buffer_new_allocate(allocator: *const c_void, + size: usize, + params: *const c_void) + -> *mut c_void; + } + + let raw = unsafe { gst_buffer_new_allocate(ptr::null(), size, ptr::null()) }; + if raw.is_null() { + None + } else { + Some(Buffer { + raw: raw, + owned: true, + }) + } + } + + pub fn map_read(&self) -> Option { + extern "C" { + fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, flags: i32) -> GBoolean; + } + + let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; + let res = unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, 1) }; + if res.to_bool() { + Some(ReadBufferMap { + buffer: self, + map_info: map_info, + }) + } else { + None + } + } + + pub fn map_readwrite(&mut self) -> Option { + extern "C" { + fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, flags: i32) -> GBoolean; + } + + let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; + let res = unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, 3) }; + if res.to_bool() { + Some(ReadWriteBufferMap { + buffer: self, + map_info: map_info, + }) + } else { + None + } + } + + 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 share(&self) -> Buffer { + unsafe { Buffer::new_from_ptr(self.raw) } + } + + pub fn get_size(&self) -> usize { + extern "C" { + fn gst_buffer_get_size(obj: *const c_void) -> usize; + } + + unsafe { gst_buffer_get_size(self.raw) } + } + + pub fn get_maxsize(&self) -> usize { + extern "C" { + fn gst_buffer_get_sizes_range(obj: *const c_void, + idx: u32, + length: i32, + offset: *mut usize, + maxsize: *mut usize) + -> usize; + } + + let mut maxsize: usize = 0; + + unsafe { + gst_buffer_get_sizes_range(self.raw, + 0, + -1, + ptr::null_mut(), + &mut maxsize as *mut usize); + }; + + maxsize + } + + pub fn set_size(&mut self, size: usize) -> Result<(), BufferError> { + 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); + } + + unsafe { + gst_buffer_set_size(self.raw, size); + } + + Ok(()) + } + + pub fn get_offset(&self) -> Option { + extern "C" { + fn gst_rs_buffer_get_offset(buf: *const c_void) -> u64; + } + + let offset = unsafe { gst_rs_buffer_get_offset(self.raw) }; + + if offset == u64::MAX { + None + } else { + Some(offset) + } + } + + pub fn set_offset(&mut self, offset: Option) -> Result<(), BufferError> { + if !self.is_writable() { + return Err(BufferError::NotWritable); + } + + extern "C" { + fn gst_rs_buffer_set_offset(buf: *const c_void, offset: u64); + } + + let offset = match offset { + None => u64::MAX, + Some(offset) => offset, + }; + + unsafe { + gst_rs_buffer_set_offset(self.raw, offset); + } + + Ok(()) + } + + pub fn get_offset_end(&self) -> Option { + extern "C" { + fn gst_rs_buffer_get_offset_end(buf: *const c_void) -> u64; + } + + let offset_end = unsafe { gst_rs_buffer_get_offset_end(self.raw) }; + + if offset_end == u64::MAX { + None + } else { + Some(offset_end) + } + } + + pub fn set_offset_end(&mut self, offset_end: Option) -> Result<(), BufferError> { + if !self.is_writable() { + return Err(BufferError::NotWritable); + } + + extern "C" { + fn gst_rs_buffer_set_offset_end(buf: *const c_void, offset_end: u64); + } + + let offset_end = match offset_end { + None => u64::MAX, + Some(offset_end) => offset_end, + }; + + unsafe { + gst_rs_buffer_set_offset_end(self.raw, offset_end); + } + + Ok(()) + } + + pub fn get_pts(&self) -> Option { + extern "C" { + fn gst_rs_buffer_get_pts(buf: *const c_void) -> u64; + } + + let pts = unsafe { gst_rs_buffer_get_pts(self.raw) }; + + 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); + } + + extern "C" { + fn gst_rs_buffer_set_pts(buf: *const c_void, pts: u64); + } + + let pts = match pts { + None => u64::MAX, + Some(pts) => pts, + }; + + unsafe { + gst_rs_buffer_set_pts(self.raw, pts); + } + + Ok(()) + } + + pub fn get_dts(&self) -> Option { + extern "C" { + fn gst_rs_buffer_get_dts(buf: *const c_void) -> u64; + } + + let dts = unsafe { gst_rs_buffer_get_dts(self.raw) }; + + 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); + } + + extern "C" { + fn gst_rs_buffer_set_dts(buf: *const c_void, dts: u64); + } + + let dts = match dts { + None => u64::MAX, + Some(dts) => dts, + }; + + unsafe { + gst_rs_buffer_set_dts(self.raw, dts); + } + + Ok(()) + } +} + +impl Drop for Buffer { + fn drop(&mut self) { + extern "C" { + fn gst_mini_object_unref(obj: *mut c_void); + } + + if self.owned { + unsafe { gst_mini_object_unref(self.raw) } + } + } +} + +impl Clone for Buffer { + fn clone(&self) -> Buffer { + extern "C" { + fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void; + } + + let raw = unsafe { gst_mini_object_copy(self.raw) }; + + Buffer { + raw: raw, + owned: true, + } + } +} + +impl<'a> ReadBufferMap<'a> { + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.map_info.data as *const u8, self.map_info.size) } + } + + pub fn get_size(&self) -> usize { + self.map_info.size + } +} + +impl<'a> Drop for ReadBufferMap<'a> { + fn drop(&mut self) { + extern "C" { + fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo); + }; + + unsafe { + gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo); + } + } +} + +impl<'a> ReadWriteBufferMap<'a> { + pub fn as_mut_slice(&self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.map_info.data as *mut u8, self.map_info.size) } + } + + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.map_info.data as *const u8, self.map_info.size) } + } + + pub fn get_size(&self) -> usize { + self.map_info.size + } +} + +impl<'a> Drop for ReadWriteBufferMap<'a> { + fn drop(&mut self) { + extern "C" { + fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo); + }; + + unsafe { + gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo); + } + } +} + +pub struct ScopedBuffer<'a> { + buffer: Buffer, + phantom: PhantomData<&'a c_void>, +} + +impl<'a> ScopedBuffer<'a> { + pub unsafe fn new(ptr: *mut c_void) -> ScopedBuffer<'a> { + ScopedBuffer { + buffer: Buffer::new_from_ptr_scoped(ptr), + 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 + } +} + diff --git a/src/lib.rs b/src/lib.rs index 4f502708..d9292d23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ extern crate hyper; pub mod utils; #[macro_use] pub mod error; +pub mod buffer; pub mod rssource; pub mod rssink; pub mod rsfilesrc; diff --git a/src/plugin.c b/src/plugin.c index 11115fb1..dee83261 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -52,3 +52,51 @@ gst_rs_element_error (GstElement * element, GQuark error_domain, gst_element_message_full (element, GST_MESSAGE_ERROR, error_domain, error_code, g_strdup (message), g_strdup (debug), file, function, line); } + +guint64 +gst_rs_buffer_get_pts (GstBuffer * buffer) +{ + return GST_BUFFER_PTS (buffer); +} + +void +gst_rs_buffer_set_pts (GstBuffer * buffer, guint64 pts) +{ + GST_BUFFER_PTS (buffer) = pts; +} + +guint64 +gst_rs_buffer_get_dts (GstBuffer * buffer) +{ + return GST_BUFFER_DTS (buffer); +} + +void +gst_rs_buffer_set_dts (GstBuffer * buffer, guint64 dts) +{ + GST_BUFFER_DTS (buffer) = dts; +} + +guint64 +gst_rs_buffer_get_offset (GstBuffer * buffer) +{ + return GST_BUFFER_OFFSET (buffer); +} + +void +gst_rs_buffer_set_offset (GstBuffer * buffer, guint64 offset) +{ + GST_BUFFER_OFFSET (buffer) = offset; +} + +guint64 +gst_rs_buffer_get_offset_end (GstBuffer * buffer) +{ + return GST_BUFFER_OFFSET_END (buffer); +} + +void +gst_rs_buffer_set_offset_end (GstBuffer * buffer, guint64 offset_end) +{ + GST_BUFFER_OFFSET_END (buffer) = offset_end; +} diff --git a/src/rsfilesink.rs b/src/rsfilesink.rs index ef5d65d9..32acc1a1 100644 --- a/src/rsfilesink.rs +++ b/src/rsfilesink.rs @@ -24,6 +24,7 @@ use std::convert::From; use error::*; use rssink::*; +use buffer::*; #[derive(Debug)] enum StreamingState { @@ -93,7 +94,7 @@ impl Sink for FileSink { Ok(()) } - fn render(&mut self, data: &[u8]) -> Result<(), FlowError> { + fn render(&mut self, buffer: &Buffer) -> Result<(), FlowError> { let (file, position) = match self.streaming_state { StreamingState::Started { ref mut file, ref mut position } => (file, position), StreamingState::Stopped => { @@ -101,6 +102,15 @@ impl Sink for FileSink { } }; + let map = match buffer.map_read() { + None => { + return Err(FlowError::Error(error_msg!(SinkError::Failure, + ["Failed to map buffer"]))); + } + Some(map) => map, + }; + let data = map.as_slice(); + try!(file.write_all(data).or_else(|err| { Err(FlowError::Error(error_msg!(SinkError::WriteFailed, ["Failed to write: {}", err]))) })); diff --git a/src/rsfilesrc.rs b/src/rsfilesrc.rs index cc50748c..dc07d2ce 100644 --- a/src/rsfilesrc.rs +++ b/src/rsfilesrc.rs @@ -22,6 +22,7 @@ use url::Url; use error::*; use rssource::*; +use buffer::*; #[derive(Debug)] enum StreamingState { @@ -104,7 +105,7 @@ impl Source for FileSrc { Ok(()) } - fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result { + fn fill(&mut self, offset: u64, _: u32, buffer: &mut Buffer) -> Result<(), FlowError> { let (file, position) = match self.streaming_state { StreamingState::Started { ref mut file, ref mut position } => (file, position), StreamingState::Stopped => { @@ -122,14 +123,33 @@ impl Source for FileSrc { *position = offset; } - let size = try!(file.read(data).or_else(|err| { - Err(FlowError::Error(error_msg!(SourceError::ReadFailed, - ["Failed to read at {}: {}", offset, err.to_string()]))) - })); + let size = { + let map = match buffer.map_readwrite() { + None => { + return Err(FlowError::Error(error_msg!(SourceError::Failure, + ["Failed to map buffer"]))); + } + Some(map) => map, + }; + + let data = map.as_mut_slice(); + + try!(file.read(data).or_else(|err| { + Err(FlowError::Error(error_msg!(SourceError::ReadFailed, + ["Failed to read at {}: {}", + offset, + err.to_string()]))) + })) + }; *position += size as u64; - Ok(size) + if let Err(err) = buffer.set_size(size) { + return Err(FlowError::Error(error_msg!(SourceError::Failure, + ["Failed to resize buffer: {}", err]))); + } + + Ok(()) } fn seek(&mut self, _: u64, _: Option) -> Result<(), ErrorMessage> { diff --git a/src/rshttpsrc.rs b/src/rshttpsrc.rs index fb615249..b8447b4b 100644 --- a/src/rshttpsrc.rs +++ b/src/rshttpsrc.rs @@ -25,6 +25,7 @@ use hyper::client::response::Response; use error::*; use rssource::*; +use buffer::*; #[derive(Debug)] enum StreamingState { @@ -186,7 +187,7 @@ impl Source for HttpSrc { Ok(()) } - fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result { + fn fill(&mut self, offset: u64, _: u32, buffer: &mut Buffer) -> Result<(), FlowError> { let (response, position) = match self.streaming_state { StreamingState::Started { ref mut response, ref mut position, .. } => { (response, position) @@ -203,10 +204,24 @@ impl Source for HttpSrc { position]))); } - let size = try!(response.read(data).or_else(|err| { - Err(FlowError::Error(error_msg!(SourceError::ReadFailed, - ["Failed to read at {}: {}", offset, err.to_string()]))) - })); + let size = { + let map = match buffer.map_readwrite() { + None => { + return Err(FlowError::Error(error_msg!(SourceError::Failure, + ["Failed to map buffer"]))); + } + Some(map) => map, + }; + + let data = map.as_mut_slice(); + + try!(response.read(data).or_else(|err| { + Err(FlowError::Error(error_msg!(SourceError::ReadFailed, + ["Failed to read at {}: {}", + offset, + err.to_string()]))) + })) + }; if size == 0 { return Err(FlowError::Eos); @@ -214,6 +229,12 @@ impl Source for HttpSrc { *position += size as u64; - Ok(size) + if let Err(err) = buffer.set_size(size) { + return Err(FlowError::Error(error_msg!(SourceError::Failure, + ["Failed to resize buffer: {}", err]))); + } + + + Ok(()) } } diff --git a/src/rssink.c b/src/rssink.c index dfa0962f..aeade93d 100644 --- a/src/rssink.c +++ b/src/rssink.c @@ -37,7 +37,7 @@ static GHashTable *sinks; /* Declarations for Rust code */ extern gboolean sinks_register (void *plugin); extern void *sink_new (GstRsSink * sink, void *create_instance); -extern GstFlowReturn sink_render (void *rssink, void *data, size_t data_len); +extern GstFlowReturn sink_render (void *rssink, GstBuffer * buffer); extern gboolean sink_set_uri (void *rssink, const char *uri, GError ** err); extern char *sink_get_uri (void *rssink); extern gboolean sink_start (void *rssink); @@ -172,12 +172,9 @@ static GstFlowReturn gst_rs_sink_render (GstBaseSink * basesink, GstBuffer * buffer) { GstRsSink *sink = GST_RS_SINK (basesink); - GstMapInfo map; GstFlowReturn ret; - gst_buffer_map (buffer, &map, GST_MAP_READ); - ret = sink_render (sink->instance, map.data, map.size); - gst_buffer_unmap (buffer, &map); + ret = sink_render (sink->instance, buffer); return ret; } diff --git a/src/rssink.rs b/src/rssink.rs index f3cdf5c9..bd4848ed 100644 --- a/src/rssink.rs +++ b/src/rssink.rs @@ -19,7 +19,6 @@ use libc::c_char; use std::os::raw::c_void; use std::ffi::{CStr, CString}; -use std::slice; use std::ptr; use std::panic::{self, AssertUnwindSafe}; @@ -31,6 +30,7 @@ use url::Url; use utils::*; use error::*; +use buffer::*; #[derive(Debug)] pub enum SinkError { @@ -67,7 +67,7 @@ pub trait Sink { fn start(&mut self, uri: Url) -> Result<(), ErrorMessage>; fn stop(&mut self) -> Result<(), ErrorMessage>; - fn render(&mut self, data: &[u8]) -> Result<(), FlowError>; + fn render(&mut self, buffer: &Buffer) -> Result<(), FlowError>; } impl SinkWrapper { @@ -205,15 +205,14 @@ pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> GBoolean { #[no_mangle] pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, - data_ptr: *const u8, - data_len: usize) + buffer: *mut c_void) -> GstFlowReturn { let wrap: &SinkWrapper = &*ptr; panic_to_error!(wrap, GstFlowReturn::Error, { let sink = &mut wrap.sink.lock().unwrap(); - let data = slice::from_raw_parts(data_ptr, data_len); + let buffer = ScopedBuffer::new(buffer); - match sink.render(data) { + match sink.render(&buffer) { Ok(..) => GstFlowReturn::Ok, Err(flow_error) => { match flow_error { diff --git a/src/rssource.c b/src/rssource.c index 022675af..d4b32518 100644 --- a/src/rssource.c +++ b/src/rssource.c @@ -36,8 +36,8 @@ static GHashTable *sources; extern gboolean sources_register (void *plugin); extern void *source_new (GstRsSrc * source, void *create_instance); extern void source_drop (void *rssource); -extern GstFlowReturn source_fill (void *rssource, - uint64_t offset, void *data, size_t * data_len); +extern GstFlowReturn source_fill (void *rssource, guint64 offset, guint size, + GstBuffer * buffer); extern gboolean source_seek (void *rssource, uint64_t start, uint64_t stop); extern gboolean source_set_uri (void *rssource, const char *uri, GError ** err); extern char *source_get_uri (void *rssource); @@ -182,19 +182,8 @@ gst_rs_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer * buf) { GstRsSrc *src = GST_RS_SRC (basesrc); - GstMapInfo map; - GstFlowReturn ret; - gsize map_size, size; - gst_buffer_map (buf, &map, GST_MAP_READWRITE); - size = length; - map_size = map.size; - ret = source_fill (src->instance, offset, map.data, &size); - gst_buffer_unmap (buf, &map); - if (ret == GST_FLOW_OK && size != map_size) - gst_buffer_resize (buf, 0, size); - - return ret; + return source_fill (src->instance, offset, length, buf); } static gboolean diff --git a/src/rssource.rs b/src/rssource.rs index 6e2dda33..8f6b17e4 100644 --- a/src/rssource.rs +++ b/src/rssource.rs @@ -18,7 +18,6 @@ use libc::c_char; use std::os::raw::c_void; use std::ffi::{CStr, CString}; -use std::slice; use std::ptr; use std::u64; @@ -31,6 +30,7 @@ use url::Url; use utils::*; use error::*; +use buffer::*; #[derive(Debug)] pub enum SourceError { @@ -69,7 +69,7 @@ pub trait Source { fn start(&mut self, uri: Url) -> Result<(), ErrorMessage>; fn stop(&mut self) -> Result<(), ErrorMessage>; - fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result; + fn fill(&mut self, offset: u64, length: u32, buffer: &mut Buffer) -> Result<(), FlowError>; fn seek(&mut self, start: u64, stop: Option) -> Result<(), ErrorMessage>; } @@ -234,21 +234,17 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean { #[no_mangle] pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper, offset: u64, - data_ptr: *mut u8, - data_len_ptr: *mut usize) + length: u32, + buffer: *mut c_void) -> GstFlowReturn { let wrap: &SourceWrapper = &*ptr; panic_to_error!(wrap, GstFlowReturn::Error, { let source = &mut wrap.source.lock().unwrap(); - let mut data_len: &mut usize = &mut *data_len_ptr; - let mut data = slice::from_raw_parts_mut(data_ptr, *data_len); + let mut buffer = ScopedBuffer::new(buffer); - match source.fill(offset, data) { - Ok(actual_len) => { - *data_len = actual_len; - GstFlowReturn::Ok - } + match source.fill(offset, length, &mut buffer) { + Ok(()) => GstFlowReturn::Ok, Err(flow_error) => { match flow_error { FlowError::NotNegotiated(ref msg) | diff --git a/src/utils.rs b/src/utils.rs index ab27be07..07f555bc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -41,6 +41,10 @@ impl GBoolean { pub fn from_bool(v: bool) -> GBoolean { if v { GBoolean::True } else { GBoolean::False } } + + pub fn to_bool(&self) -> bool { + !(*self == GBoolean::False) + } } #[no_mangle]