mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-21 15:16:18 +00:00
Add some more Buffer API and use explicit bitflags instead of magic numbers
This commit is contained in:
parent
1ef938b6ec
commit
b23385e88f
6 changed files with 329 additions and 7 deletions
|
@ -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"
|
||||
|
|
317
src/buffer.rs
317
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<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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
extern crate libc;
|
||||
extern crate url;
|
||||
extern crate hyper;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
#[macro_use]
|
||||
pub mod utils;
|
||||
|
|
12
src/plugin.c
12
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;
|
||||
}
|
||||
|
|
|
@ -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"])));
|
||||
|
|
|
@ -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"])));
|
||||
|
|
Loading…
Reference in a new issue