Commit 922af1d6 authored by Vivia Nikolaidou's avatar Vivia Nikolaidou 🦆 Committed by Sebastian Dröge

Add GstMemory bindings

Part of #12
parent 044d931d
......@@ -60,6 +60,7 @@ generate = [
"Gst.PipelineFlags",
"Gst.PluginFlags",
"Gst.MemoryFlags",
"Gst.Allocator",
"Gst.PadLinkCheck",
"Gst.DebugLevel",
"Gst.DebugColorFlags",
......
// Copyright (C) 2019 Vivia Nikolaidou <vivia@ahiru.eu>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::mem;
use glib::translate::*;
use MemoryFlags;
#[derive(Debug, Clone)]
pub struct AllocationParams(gst_sys::GstAllocationParams);
impl AllocationParams {
pub fn get_flags(&self) -> MemoryFlags {
from_glib(self.0.flags)
}
pub fn get_align(&self) -> usize {
self.0.align
}
pub fn get_prefix(&self) -> usize {
self.0.prefix
}
pub fn get_padding(&self) -> usize {
self.0.padding
}
pub fn new(flags: MemoryFlags, align: usize, prefix: usize, padding: usize) -> Self {
assert_initialized_main_thread!();
let allocationparams = unsafe {
let mut allocationparams: gst_sys::GstAllocationParams = mem::zeroed();
allocationparams.flags = flags.to_glib();
allocationparams.align = align;
allocationparams.prefix = prefix;
allocationparams.padding = padding;
allocationparams
};
AllocationParams(allocationparams)
}
pub fn as_ptr(&self) -> *const gst_sys::GstAllocationParams {
&self.0
}
}
impl From<gst_sys::GstAllocationParams> for AllocationParams {
fn from(params: gst_sys::GstAllocationParams) -> Self {
AllocationParams(params)
}
}
......@@ -19,6 +19,8 @@ use meta::*;
use miniobject::*;
use BufferFlags;
use ClockTime;
use Memory;
use MemoryRef;
use glib;
use glib::translate::{from_glib, from_glib_full, FromGlib, ToGlib};
......@@ -404,6 +406,175 @@ impl BufferRef {
pub fn iter_meta_mut<T: MetaAPI>(&mut self) -> MetaIterMut<T> {
MetaIterMut::new(self)
}
pub fn append_memory(&mut self, mem: Memory) {
unsafe { gst_sys::gst_buffer_append_memory(self.as_mut_ptr(), mem.into_ptr()) }
}
pub fn find_memory(&self, offset: usize, size: Option<usize>) -> Option<(u32, u32, usize)> {
let mut idx = 0;
let mut length = 0;
let mut skip = 0;
let res;
unsafe {
res = from_glib(gst_sys::gst_buffer_find_memory(
self.as_mut_ptr(),
offset,
size.unwrap_or(usize::MAX),
&mut idx,
&mut length,
&mut skip,
))
}
if res {
Some((idx, length, skip))
} else {
None
}
}
pub fn get_all_memory(&self) -> Option<Memory> {
unsafe {
let res = gst_sys::gst_buffer_get_all_memory(self.as_mut_ptr());
if res.is_null() {
None
} else {
Some(from_glib_full(res))
}
}
}
pub fn get_max_memory() -> u32 {
unsafe { gst_sys::gst_buffer_get_max_memory() }
}
pub fn get_memory(&self, idx: u32) -> Option<Memory> {
if idx >= self.n_memory() {
None
} else {
unsafe {
let res = gst_sys::gst_buffer_get_memory(self.as_mut_ptr(), idx);
if res.is_null() {
None
} else {
Some(from_glib_full(res))
}
}
}
}
pub fn get_memory_range(&self, idx: u32, length: Option<u32>) -> Option<Memory> {
assert!(idx + length.unwrap_or(0) < self.n_memory());
unsafe {
let res = gst_sys::gst_buffer_get_memory_range(
self.as_mut_ptr(),
idx,
match length {
Some(val) => val as i32,
None => -1,
},
);
if res.is_null() {
None
} else {
Some(from_glib_full(res))
}
}
}
pub fn insert_memory(&mut self, idx: Option<u32>, mem: Memory) {
unsafe {
gst_sys::gst_buffer_insert_memory(
self.as_mut_ptr(),
match idx {
Some(val) => val as i32,
None => -1,
},
mem.into_ptr(),
)
}
}
pub fn is_all_memory_writable(&self) -> bool {
unsafe {
from_glib(gst_sys::gst_buffer_is_all_memory_writable(
self.as_mut_ptr(),
))
}
}
pub fn is_memory_range_writable(&self, idx: u32, length: Option<u16>) -> bool {
unsafe {
from_glib(gst_sys::gst_buffer_is_memory_range_writable(
self.as_mut_ptr(),
idx,
match length {
Some(val) => val as i32,
None => -1,
},
))
}
}
pub fn n_memory(&self) -> u32 {
unsafe { gst_sys::gst_buffer_n_memory(self.as_ptr() as *mut _) }
}
pub fn peek_memory(&self, idx: u32) -> &MemoryRef {
assert!(idx < self.n_memory());
unsafe { MemoryRef::from_ptr(gst_sys::gst_buffer_peek_memory(self.as_mut_ptr(), idx)) }
}
pub fn prepend_memory(&mut self, mem: Memory) {
unsafe { gst_sys::gst_buffer_prepend_memory(self.as_mut_ptr(), mem.into_ptr()) }
}
pub fn remove_all_memory(&mut self) {
unsafe { gst_sys::gst_buffer_remove_all_memory(self.as_mut_ptr()) }
}
pub fn remove_memory(&mut self, idx: u32) {
assert!(idx < self.n_memory());
unsafe { gst_sys::gst_buffer_remove_memory(self.as_mut_ptr(), idx) }
}
pub fn remove_memory_range(&mut self, idx: u32, length: Option<u32>) {
assert!(idx + length.unwrap_or(0) < self.n_memory());
unsafe {
gst_sys::gst_buffer_remove_memory_range(
self.as_mut_ptr(),
idx,
match length {
Some(val) => val as i32,
None => -1,
},
)
}
}
pub fn replace_all_memory(&mut self, mem: Memory) {
unsafe { gst_sys::gst_buffer_replace_all_memory(self.as_mut_ptr(), mem.into_ptr()) }
}
pub fn replace_memory(&mut self, idx: u32, mem: Memory) {
assert!(idx < self.n_memory());
unsafe { gst_sys::gst_buffer_replace_memory(self.as_mut_ptr(), idx, mem.into_ptr()) }
}
pub fn replace_memory_range(&mut self, idx: u32, length: Option<u32>, mem: Memory) {
assert!(idx + length.unwrap_or(0) < self.n_memory());
unsafe {
gst_sys::gst_buffer_replace_memory_range(
self.as_mut_ptr(),
idx,
match length {
Some(val) => val as i32,
None => -1,
},
mem.into_ptr(),
)
}
}
}
macro_rules! define_iter(
......
......@@ -119,6 +119,8 @@ pub mod buffer;
pub use buffer::{
Buffer, BufferMap, BufferRef, MappedBuffer, BUFFER_COPY_ALL, BUFFER_COPY_METADATA,
};
pub mod memory;
pub use memory::{MappedMemory, Memory, MemoryMap, MemoryRef};
#[cfg(feature = "ser_de")]
mod buffer_serde;
......@@ -155,6 +157,9 @@ mod bin;
mod pipeline;
mod allocation_params;
pub use self::allocation_params::AllocationParams;
// OS dependent Bus extensions (also import the other plateform mod for doc)
#[cfg(any(feature = "v1_14", feature = "dox"))]
cfg_if! {
......
// Copyright (C) 2019 Vivia Nikolaidou <vivia@ahiru.eu>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::ops;
use std::ptr;
use std::slice;
use gst_sys;
use glib;
use glib::translate::{from_glib, from_glib_full, from_glib_none, ToGlibPtr};
use miniobject::MiniObject;
use AllocationParams;
use MemoryFlags;
gst_define_mini_object_wrapper!(Memory, MemoryRef, gst_sys::GstMemory, [Debug,], || {
gst_sys::gst_memory_get_type()
});
pub struct MemoryMap<'a, T> {
memory: &'a MemoryRef,
map_info: gst_sys::GstMapInfo,
phantom: PhantomData<T>,
}
pub struct MappedMemory<T> {
memory: Option<Memory>,
map_info: gst_sys::GstMapInfo,
phantom: PhantomData<T>,
}
impl fmt::Debug for MemoryRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Memory")
.field("ptr", unsafe { &self.as_ptr() })
//.field("allocator", &self.get_allocator())
.field("parent", &self.get_parent())
.field("maxsize", &self.get_maxsize())
.field("align", &self.get_align())
.field("offset", &self.get_offset())
.field("size", &self.get_size())
.field("flags", &self.get_flags())
.finish()
}
}
pub enum Readable {}
pub enum Writable {}
impl Memory {
unsafe extern "C" fn drop_box<T>(vec: glib_sys::gpointer) {
let slice: Box<T> = Box::from_raw(vec as *mut T);
drop(slice);
}
pub fn with_size(size: usize) -> Self {
unsafe {
from_glib_full(gst_sys::gst_allocator_alloc(
ptr::null_mut(),
size,
ptr::null_mut(),
))
}
}
pub fn with_size_and_params(size: usize, params: &AllocationParams) -> Self {
unsafe {
from_glib_full(gst_sys::gst_allocator_alloc(
ptr::null_mut(),
size,
params.as_ptr() as *mut _,
))
}
}
pub fn from_slice<T: AsRef<[u8]> + Send + 'static>(slice: T) -> Self {
assert_initialized_main_thread!();
unsafe {
let b = Box::new(slice);
let (size, data) = {
let slice = (*b).as_ref();
(slice.len(), slice.as_ptr())
};
let user_data = Box::into_raw(b);
from_glib_full(gst_sys::gst_memory_new_wrapped(
gst_sys::GST_MEMORY_FLAG_READONLY,
data as glib_sys::gpointer,
size,
0,
size,
user_data as glib_sys::gpointer,
Some(Self::drop_box::<T>),
))
}
}
pub fn from_mut_slice<T: AsMut<[u8]> + Send + 'static>(slice: T) -> Self {
assert_initialized_main_thread!();
unsafe {
let mut b = Box::new(slice);
let (size, data) = {
let slice = (*b).as_mut();
(slice.len(), slice.as_mut_ptr())
};
let user_data = Box::into_raw(b);
from_glib_full(gst_sys::gst_memory_new_wrapped(
0,
data as glib_sys::gpointer,
size,
0,
size,
user_data as glib_sys::gpointer,
Some(Self::drop_box::<T>),
))
}
}
pub fn into_mapped_memory_readable(self) -> Result<MappedMemory<Readable>, Self> {
let mut map_info: gst_sys::GstMapInfo = unsafe { mem::zeroed() };
let res: bool = unsafe {
from_glib(gst_sys::gst_memory_map(
self.as_mut_ptr(),
&mut map_info,
gst_sys::GST_MAP_READ,
))
};
if res {
Ok(MappedMemory {
memory: Some(self),
map_info,
phantom: PhantomData,
})
} else {
Err(self)
}
}
pub fn into_mapped_memory_writable(self) -> Result<MappedMemory<Writable>, Self> {
let mut map_info: gst_sys::GstMapInfo = unsafe { mem::zeroed() };
let res: bool = unsafe {
from_glib(gst_sys::gst_memory_map(
self.as_mut_ptr(),
&mut map_info,
gst_sys::GST_MAP_READWRITE,
))
};
if res {
Ok(MappedMemory {
memory: Some(self),
map_info,
phantom: PhantomData,
})
} else {
Err(self)
}
}
}
impl MemoryRef {
pub fn get_parent(&self) -> Option<&MemoryRef> {
unsafe {
if self.0.parent.is_null() {
None
} else {
Some(MemoryRef::from_ptr(self.0.parent))
}
}
}
pub fn get_maxsize(&self) -> usize {
self.0.maxsize
}
pub fn get_align(&self) -> usize {
self.0.align
}
pub fn get_offset(&self) -> usize {
self.0.offset
}
pub fn get_size(&self) -> usize {
self.0.size
}
pub fn get_flags(&self) -> MemoryFlags {
from_glib(self.0.mini_object.flags)
}
pub fn copy_part(&self, offset: isize, size: Option<usize>) -> Memory {
let pos_sz = match size {
Some(val) => val as isize,
None => 0,
};
assert!(offset + pos_sz < (self.get_maxsize() as isize));
unsafe {
from_glib_full(gst_sys::gst_memory_copy(
self.as_mut_ptr(),
offset,
match size {
Some(val) => val as isize,
None => -1,
},
))
}
}
pub fn is_span(&self, mem2: &MemoryRef) -> Option<usize> {
unsafe {
let mut offset = 0;
let res = from_glib(gst_sys::gst_memory_is_span(
self.as_mut_ptr(),
mem2.as_mut_ptr(),
&mut offset,
));
if res {
Some(offset)
} else {
None
}
}
}
pub fn is_type(&self, mem_type: &str) -> bool {
unsafe {
from_glib(gst_sys::gst_memory_is_type(
self.as_mut_ptr(),
mem_type.to_glib_none().0,
))
}
}
pub fn map_readable(&self) -> Option<MemoryMap<Readable>> {
let mut map_info: gst_sys::GstMapInfo = unsafe { mem::zeroed() };
let res = unsafe {
gst_sys::gst_memory_map(self.as_mut_ptr(), &mut map_info, gst_sys::GST_MAP_READ)
};
if res == glib_sys::GTRUE {
Some(MemoryMap {
memory: self,
map_info,
phantom: PhantomData,
})
} else {
None
}
}
pub fn map_writable(&mut self) -> Option<MemoryMap<Writable>> {
let mut map_info: gst_sys::GstMapInfo = unsafe { mem::zeroed() };
let res = unsafe {
gst_sys::gst_memory_map(self.as_mut_ptr(), &mut map_info, gst_sys::GST_MAP_READWRITE)
};
if res == glib_sys::GTRUE {
Some(MemoryMap {
memory: self,
map_info,
phantom: PhantomData,
})
} else {
None
}
}
pub fn share(&self, offset: isize, size: Option<usize>) -> Memory {
let pos_sz = match size {
Some(val) => val as isize,
None => 0,
};
assert!(offset + pos_sz < (self.get_maxsize() as isize));
unsafe {
from_glib_full(gst_sys::gst_memory_share(
self.as_ptr() as *mut _,
offset,
match size {
Some(val) => val as isize,
None => -1,
},
))
}
}
pub fn resize(&mut self, offset: isize, size: usize) {
assert!(offset + (size as isize) < (self.get_maxsize() as isize));
unsafe { gst_sys::gst_memory_resize(self.as_mut_ptr(), offset, size) }
}
}
impl<'a, T> MemoryMap<'a, T> {
pub fn get_size(&self) -> usize {
self.map_info.size
}
pub fn get_memory(&self) -> &MemoryRef {
self.memory
}
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.map_info.data as *const u8, self.map_info.size) }
}
}
impl<'a> MemoryMap<'a, Writable> {
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) }
}
}
impl<'a, T> AsRef<[u8]> for MemoryMap<'a, T> {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl<'a> AsMut<[u8]> for MemoryMap<'a, Writable> {
fn as_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
}
impl<'a, T> ops::Deref for MemoryMap<'a, T> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.as_slice()
}
}
impl<'a> ops::DerefMut for MemoryMap<'a, Writable> {
fn deref_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
}
impl<'a, T> fmt::Debug for MemoryMap<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("MemoryMap")
.field(&self.get_memory())
.finish()
}
}
impl<'a, T> PartialEq for MemoryMap<'a, T> {
fn eq(&self, other: &MemoryMap<'a, T>) -> bool {
self.as_slice().eq(other.as_slice())
}
}
impl<'a, T> Eq for MemoryMap<'a, T> {}
impl<'a, T> Drop for MemoryMap<'a, T> {
fn drop(&mut self) {
unsafe {
gst_sys::gst_memory_unmap(self.memory.as_mut_ptr(), &mut self.map_info);
}
}
}
impl<T> MappedMemory<T> {
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_memory(&self) -> &MemoryRef {
self.memory.as_ref().unwrap().as_ref()
}
pub fn into_memory(mut self) -> Memory {
let memory = self.memory.take().unwrap();
unsafe {
gst_sys::gst_memory_unmap(memory.as_mut_ptr(), &mut self.map_info);
}
memory
}
}
impl MappedMemory<Writable> {
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) }
}
}
impl<T> AsRef<[u8]> for MappedMemory<T> {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsMut<[u8]> for MappedMemory<Writable> {
fn as_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
}
impl<T> ops::Deref for MappedMemory<T> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.as_slice()
}
}
impl ops::DerefMut for MappedMemory<Writable> {
fn deref_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
}
impl<T> Drop for MappedMemory<T> {
fn drop(&mut self) {
if let Some(ref memory) = self.memory {
unsafe {
gst_sys::gst_memory_unmap(memory.as_mut_ptr(), &mut self.map_info);
}
}
}
}
impl<T> fmt::Debug for MappedMemory<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("MappedMemory")
.field(&self.get_memory())
.finish()