diff --git a/Cargo.toml b/Cargo.toml index 957d9112..bd0e37c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ license = "LGPL-2.1+" libc = "0.2" url = "1.1" hyper = "0.9" +bitflags = "0.7" [build-dependencies] gcc = "0.3" diff --git a/src/buffer.rs b/src/buffer.rs index a661203f..9bf6b11d 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -22,6 +22,7 @@ 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; @@ -29,12 +30,14 @@ use std::ops::{Deref, DerefMut}; use utils::*; +#[derive(Debug)] pub struct Buffer { raw: *mut c_void, owned: bool, } #[repr(C)] +#[derive(Debug)] struct GstMapInfo { memory: *mut c_void, flags: i32, @@ -45,20 +48,35 @@ struct GstMapInfo { _gst_reserved: [*const c_void; 4], } +#[derive(Debug)] pub struct ReadBufferMap<'a> { buffer: &'a Buffer, map_info: GstMapInfo, } +#[derive(Debug)] pub struct ReadWriteBufferMap<'a> { buffer: &'a Buffer, map_info: GstMapInfo, } #[derive(Debug)] +pub struct ReadMappedBuffer { + buffer: Buffer, + map_info: GstMapInfo, +} + +#[derive(Debug)] +pub struct ReadWriteMappedBuffer { + buffer: Buffer, + map_info: GstMapInfo, +} + +#[derive(Debug, PartialEq, Eq)] pub enum BufferError { NotWritable, NotEnoughSpace, + Unknown, } impl Display for BufferError { @@ -72,6 +90,7 @@ impl Error for BufferError { match *self { BufferError::NotWritable => "Not Writable", BufferError::NotEnoughSpace => "Not Enough Space", + BufferError::Unknown => "Unknown", } } } @@ -101,6 +120,18 @@ impl Buffer { } } + pub fn new() -> Buffer { + extern "C" { + fn gst_buffer_new() -> *mut c_void; + } + + let raw = unsafe { gst_buffer_new() }; + Buffer { + raw: raw, + owned: true, + } + } + pub fn new_with_size(size: usize) -> Option { extern "C" { fn gst_buffer_new_allocate(allocator: *const c_void, @@ -122,11 +153,15 @@ impl Buffer { pub fn map_read(&self) -> Option { extern "C" { - fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, flags: i32) -> GBoolean; + fn gst_buffer_map(buffer: *mut c_void, + map: *mut GstMapInfo, + flags: MapFlags) + -> GBoolean; } let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; - let res = unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, 1) }; + let res = + unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) }; if res.to_bool() { Some(ReadBufferMap { buffer: self, @@ -139,11 +174,18 @@ impl Buffer { pub fn map_readwrite(&mut self) -> Option { extern "C" { - fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, flags: i32) -> GBoolean; + fn gst_buffer_map(buffer: *mut c_void, + map: *mut GstMapInfo, + flags: MapFlags) + -> GBoolean; } let mut map_info: GstMapInfo = unsafe { mem::zeroed() }; - let res = unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, 3) }; + let res = unsafe { + gst_buffer_map(self.raw, + &mut map_info as *mut GstMapInfo, + MAP_FLAG_READWRITE) + }; if res.to_bool() { Some(ReadWriteBufferMap { buffer: self, @@ -154,6 +196,51 @@ impl Buffer { } } + pub fn into_read_mapped_buffer(self) -> Option { + extern "C" { + fn gst_buffer_map(buffer: *mut c_void, + map: *mut GstMapInfo, + flags: MapFlags) + -> GBoolean; + } + + 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) }; + if res.to_bool() { + Some(ReadMappedBuffer { + buffer: self, + map_info: map_info, + }) + } else { + None + } + } + + pub fn into_readwrite_mapped_buffer(self) -> Option { + extern "C" { + fn gst_buffer_map(buffer: *mut c_void, + map: *mut GstMapInfo, + flags: MapFlags) + -> GBoolean; + } + + 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) + }; + if res.to_bool() { + Some(ReadWriteMappedBuffer { + 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; @@ -181,6 +268,101 @@ impl Buffer { unsafe { Buffer::new_from_ptr(self.raw) } } + pub fn append(self, other: Buffer) -> 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, + } + } + + pub fn copy_region(&self, offset: usize, size: Option) -> Option { + extern "C" { + fn gst_buffer_copy_region(buf: *mut c_void, + flags: BufferCopyFlags, + offset: usize, + size: usize) + -> *mut c_void; + } + + let size_real = size.unwrap_or(usize::MAX); + + let raw = + unsafe { gst_buffer_copy_region(self.raw, BUFFER_COPY_FLAG_ALL, offset, size_real) }; + + if raw.is_null() { + None + } else { + Some(Buffer { + raw: raw, + owned: true, + }) + } + } + + pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), BufferError> { + if !self.is_writable() { + return Err(BufferError::NotWritable); + } + + let maxsize = self.get_maxsize(); + let size = slice.len(); + if maxsize < offset || maxsize - offset < size { + return Err(BufferError::NotEnoughSpace); + } + + extern "C" { + fn gst_buffer_fill(buffer: *mut c_void, + offset: usize, + src: *const u8, + size: usize) + -> usize; + }; + + let copied = unsafe { + let src = slice.as_ptr(); + gst_buffer_fill(self.raw, offset, src, size) + }; + + if copied < size { + Err(BufferError::Unknown) + } else { + Ok(()) + } + } + + pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), BufferError> { + let maxsize = self.get_size(); + let size = slice.len(); + if maxsize < offset || maxsize - offset < size { + return Err(BufferError::NotEnoughSpace); + } + + extern "C" { + fn gst_buffer_extract(buffer: *mut c_void, + offset: usize, + src: *mut u8, + size: usize) + -> usize; + }; + + let copied = unsafe { + let src = slice.as_mut_ptr(); + gst_buffer_extract(self.raw, offset, src, size) + }; + + if copied < size { + Err(BufferError::Unknown) + } else { + Ok(()) + } + } + pub fn get_size(&self) -> usize { extern "C" { fn gst_buffer_get_size(obj: *const c_void) -> usize; @@ -363,6 +545,30 @@ impl Buffer { Ok(()) } + + pub fn get_flags(&self) -> BufferFlags { + extern "C" { + fn gst_rs_buffer_get_flags(buf: *const c_void) -> BufferFlags; + } + + unsafe { gst_rs_buffer_get_flags(self.raw) } + } + + pub fn set_flags(&mut self, flags: BufferFlags) -> Result<(), BufferError> { + if !self.is_writable() { + return Err(BufferError::NotWritable); + } + + 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 { @@ -415,7 +621,7 @@ impl<'a> Drop for ReadBufferMap<'a> { } impl<'a> ReadWriteBufferMap<'a> { - pub fn as_mut_slice(&self) -> &mut [u8] { + pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.map_info.data as *mut u8, self.map_info.size) } } @@ -440,6 +646,62 @@ impl<'a> Drop for ReadWriteBufferMap<'a> { } } +impl ReadMappedBuffer { + 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 + } + + pub fn get_buffer(&self) -> &Buffer { + &self.buffer + } +} + +impl Drop for ReadMappedBuffer { + 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 ReadWriteMappedBuffer { + pub fn as_mut_slice(&mut 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 + } + + pub fn get_buffer(&self) -> &Buffer { + &self.buffer + } +} + +impl Drop for ReadWriteMappedBuffer { + 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); + } + } +} + #[repr(C)] pub struct ScopedBufferPtr(*mut c_void); @@ -471,3 +733,48 @@ impl<'a> DerefMut for ScopedBuffer<'a> { &mut self.buffer } } + +bitflags! { + #[repr(C)] + flags MapFlags: u32 { + const MAP_FLAG_READ = 0b00000001, + const MAP_FLAG_WRITE = 0b00000010, + const MAP_FLAG_READWRITE = MAP_FLAG_READ.bits + | MAP_FLAG_WRITE.bits, + } +} + +bitflags! { + #[repr(C)] + pub flags BufferFlags: u32 { + const BUFFER_FLAG_LIVE = 0b0000000000010000, + const BUFFER_FLAG_DECODE_ONLY = 0b0000000000100000, + const BUFFER_FLAG_DISCONT = 0b0000000001000000, + const BUFFER_FLAG_RESYNC = 0b0000000010000000, + const BUFFER_FLAG_CORRUPTED = 0b0000000100000000, + const BUFFER_FLAG_MARKER = 0b0000001000000000, + const BUFFER_FLAG_HEADER = 0b0000010000000000, + const BUFFER_FLAG_GAP = 0b0000100000000000, + const BUFFER_FLAG_DROPPABLE = 0b0001000000000000, + const BUFFER_FLAG_DELTA_UNIT = 0b0010000000000000, + const BUFFER_FLAG_TAG_MEMORY = 0b0100000000000000, + const BUFFER_FLAG_SYNC_AFTER = 0b1000000000000000, + } +} + +bitflags! { + #[repr(C)] + flags BufferCopyFlags: u32 { + const BUFFER_COPY_FLAG_FLAGS = 0b00000001, + const BUFFER_COPY_FLAG_TIMESTAMPS = 0b00000010, + const BUFFER_COPY_FLAG_META = 0b00000100, + const BUFFER_COPY_FLAG_MEMORY = 0b00001000, + const BUFFER_COPY_FLAG_MERGE = 0b00010000, + const BUFFER_COPY_FLAG_DEEP = 0b00100000, + const BUFFER_COPY_FLAG_METADATA = BUFFER_COPY_FLAG_FLAGS.bits + | BUFFER_COPY_FLAG_TIMESTAMPS.bits + | BUFFER_COPY_FLAG_META.bits, + const BUFFER_COPY_FLAG_ALL = BUFFER_COPY_FLAG_METADATA.bits + | BUFFER_COPY_FLAG_MEMORY.bits, + } +} diff --git a/src/lib.rs b/src/lib.rs index d9292d23..094ef898 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,8 @@ extern crate libc; extern crate url; extern crate hyper; +#[macro_use] +extern crate bitflags; #[macro_use] pub mod utils; diff --git a/src/plugin.c b/src/plugin.c index dee83261..2a3f9e00 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -100,3 +100,15 @@ gst_rs_buffer_set_offset_end (GstBuffer * buffer, guint64 offset_end) { GST_BUFFER_OFFSET_END (buffer) = offset_end; } + +GstBufferFlags +gst_rs_buffer_get_buffer_flags (GstBuffer * buffer) +{ + return GST_MINI_OBJECT_FLAGS (buffer); +} + +void +gst_rs_buffer_set_buffer_flags (GstBuffer * buffer, GstBufferFlags flags) +{ + GST_MINI_OBJECT_FLAGS (buffer) = flags; +} diff --git a/src/rsfilesrc.rs b/src/rsfilesrc.rs index dc07d2ce..3bfacb8b 100644 --- a/src/rsfilesrc.rs +++ b/src/rsfilesrc.rs @@ -124,7 +124,7 @@ impl Source for FileSrc { } let size = { - let map = match buffer.map_readwrite() { + let mut map = match buffer.map_readwrite() { None => { return Err(FlowError::Error(error_msg!(SourceError::Failure, ["Failed to map buffer"]))); diff --git a/src/rshttpsrc.rs b/src/rshttpsrc.rs index b8447b4b..bda289da 100644 --- a/src/rshttpsrc.rs +++ b/src/rshttpsrc.rs @@ -205,7 +205,7 @@ impl Source for HttpSrc { } let size = { - let map = match buffer.map_readwrite() { + let mut map = match buffer.map_readwrite() { None => { return Err(FlowError::Error(error_msg!(SourceError::Failure, ["Failed to map buffer"])));