Add some more Buffer API and use explicit bitflags instead of magic numbers

This commit is contained in:
Sebastian Dröge 2016-09-17 08:31:10 -04:00
parent 1ef938b6ec
commit b23385e88f
6 changed files with 329 additions and 7 deletions

View file

@ -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"

View file

@ -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<Buffer> {
extern "C" {
fn gst_buffer_new_allocate(allocator: *const c_void,
@ -122,11 +153,15 @@ impl Buffer {
pub fn map_read(&self) -> Option<ReadBufferMap> {
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<ReadWriteBufferMap> {
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<ReadMappedBuffer> {
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<ReadWriteMappedBuffer> {
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<usize>) -> Option<Buffer> {
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,
}
}

View file

@ -21,6 +21,8 @@
extern crate libc;
extern crate url;
extern crate hyper;
#[macro_use]
extern crate bitflags;
#[macro_use]
pub mod utils;

View file

@ -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;
}

View file

@ -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"])));

View file

@ -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"])));