2017-07-25 12:01:24 +00:00
|
|
|
// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
|
|
|
|
//
|
|
|
|
// 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::ptr;
|
|
|
|
use std::mem;
|
|
|
|
use std::fmt;
|
|
|
|
use std::slice;
|
|
|
|
use std::u64;
|
|
|
|
use std::usize;
|
2017-08-11 12:20:43 +00:00
|
|
|
use std::marker::PhantomData;
|
2017-07-25 12:01:24 +00:00
|
|
|
|
|
|
|
use miniobject::*;
|
|
|
|
use BufferFlags;
|
2017-07-25 12:31:45 +00:00
|
|
|
use ClockTime;
|
2017-07-25 12:01:24 +00:00
|
|
|
|
|
|
|
use glib;
|
|
|
|
use glib_ffi;
|
|
|
|
use ffi;
|
2017-11-11 10:21:55 +00:00
|
|
|
use glib::translate::{from_glib, from_glib_full, ToGlib};
|
2017-07-25 12:01:24 +00:00
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub struct Readable;
|
|
|
|
pub struct Writable;
|
|
|
|
|
2017-07-25 12:01:24 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct BufferRef(ffi::GstBuffer);
|
|
|
|
pub type Buffer = GstRc<BufferRef>;
|
|
|
|
|
|
|
|
unsafe impl MiniObject for BufferRef {
|
|
|
|
type GstType = ffi::GstBuffer;
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub struct BufferMap<'a, T> {
|
2017-07-25 12:01:24 +00:00
|
|
|
buffer: &'a BufferRef,
|
|
|
|
map_info: ffi::GstMapInfo,
|
2017-08-11 12:20:43 +00:00
|
|
|
phantom: PhantomData<T>,
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub struct MappedBuffer<T> {
|
|
|
|
buffer: Option<Buffer>,
|
2017-07-25 12:01:24 +00:00
|
|
|
map_info: ffi::GstMapInfo,
|
2017-08-11 12:20:43 +00:00
|
|
|
phantom: PhantomData<T>,
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GstRc<BufferRef> {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
|
|
|
unsafe { from_glib_full(ffi::gst_buffer_new()) }
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn with_size(size: usize) -> Option<Self> {
|
2017-08-30 11:39:09 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
2017-07-25 12:01:24 +00:00
|
|
|
let raw = unsafe { ffi::gst_buffer_new_allocate(ptr::null_mut(), size, ptr::null_mut()) };
|
|
|
|
if raw.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(unsafe { from_glib_full(raw) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-20 16:37:38 +00:00
|
|
|
unsafe extern "C" fn drop_box<T>(vec: glib_ffi::gpointer) {
|
|
|
|
let slice: Box<T> = Box::from_raw(vec as *mut T);
|
|
|
|
drop(slice);
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-10-26 12:02:36 +00:00
|
|
|
pub fn from_mut_slice<T: AsMut<[u8]> + Send + 'static>(slice: T) -> Option<Self> {
|
2017-08-30 11:39:09 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
2017-07-25 12:01:24 +00:00
|
|
|
let raw = unsafe {
|
2017-10-20 16:37:38 +00:00
|
|
|
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);
|
2017-07-25 12:01:24 +00:00
|
|
|
ffi::gst_buffer_new_wrapped_full(
|
|
|
|
ffi::GstMemoryFlags::empty(),
|
|
|
|
data as glib_ffi::gpointer,
|
2017-10-20 16:37:38 +00:00
|
|
|
size,
|
|
|
|
0,
|
|
|
|
size,
|
|
|
|
user_data as glib_ffi::gpointer,
|
|
|
|
Some(Self::drop_box::<T>),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
if raw.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(unsafe { from_glib_full(raw) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-26 12:02:36 +00:00
|
|
|
pub fn from_slice<T: AsRef<[u8]> + Send + 'static>(slice: T) -> Option<Self> {
|
2017-10-20 16:37:38 +00:00
|
|
|
assert_initialized_main_thread!();
|
|
|
|
|
|
|
|
let raw = 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);
|
|
|
|
ffi::gst_buffer_new_wrapped_full(
|
|
|
|
ffi::GST_MEMORY_FLAG_READONLY,
|
|
|
|
data as glib_ffi::gpointer,
|
|
|
|
size,
|
2017-07-25 12:01:24 +00:00
|
|
|
0,
|
|
|
|
size,
|
|
|
|
user_data as glib_ffi::gpointer,
|
2017-10-20 16:37:38 +00:00
|
|
|
Some(Self::drop_box::<T>),
|
2017-07-25 12:01:24 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
if raw.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(unsafe { from_glib_full(raw) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn into_mapped_buffer_readable(self) -> Result<MappedBuffer<Readable>, Self> {
|
2017-07-25 12:01:24 +00:00
|
|
|
let mut map_info: ffi::GstMapInfo = unsafe { mem::zeroed() };
|
|
|
|
let res: bool = unsafe {
|
|
|
|
from_glib(ffi::gst_buffer_map(
|
2017-08-02 16:40:31 +00:00
|
|
|
self.as_mut_ptr(),
|
2017-07-25 12:01:24 +00:00
|
|
|
&mut map_info,
|
|
|
|
ffi::GST_MAP_READ,
|
|
|
|
))
|
|
|
|
};
|
|
|
|
if res {
|
2017-08-11 12:20:43 +00:00
|
|
|
Ok(MappedBuffer {
|
|
|
|
buffer: Some(self),
|
2017-07-25 12:01:24 +00:00
|
|
|
map_info: map_info,
|
2017-08-11 12:20:43 +00:00
|
|
|
phantom: PhantomData,
|
2017-07-25 12:01:24 +00:00
|
|
|
})
|
|
|
|
} else {
|
2017-08-02 16:40:31 +00:00
|
|
|
Err(self)
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn into_mapped_buffer_writable(self) -> Result<MappedBuffer<Writable>, Self> {
|
2017-07-25 12:01:24 +00:00
|
|
|
let mut map_info: ffi::GstMapInfo = unsafe { mem::zeroed() };
|
|
|
|
let res: bool = unsafe {
|
|
|
|
from_glib(ffi::gst_buffer_map(
|
2017-08-02 16:40:31 +00:00
|
|
|
self.as_mut_ptr(),
|
2017-07-25 12:01:24 +00:00
|
|
|
&mut map_info,
|
|
|
|
ffi::GST_MAP_READWRITE,
|
|
|
|
))
|
|
|
|
};
|
|
|
|
if res {
|
2017-08-11 12:20:43 +00:00
|
|
|
Ok(MappedBuffer {
|
|
|
|
buffer: Some(self),
|
2017-07-25 12:01:24 +00:00
|
|
|
map_info: map_info,
|
2017-08-11 12:20:43 +00:00
|
|
|
phantom: PhantomData,
|
2017-07-25 12:01:24 +00:00
|
|
|
})
|
|
|
|
} else {
|
2017-08-02 16:40:31 +00:00
|
|
|
Err(self)
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn append(buffer: Self, other: Self) -> Self {
|
2017-08-30 11:39:09 +00:00
|
|
|
skip_assert_initialized!();
|
2017-07-25 12:01:24 +00:00
|
|
|
unsafe { from_glib_full(ffi::gst_buffer_append(buffer.into_ptr(), other.into_ptr())) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-10 11:54:43 +00:00
|
|
|
impl Default for GstRc<BufferRef> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-25 12:01:24 +00:00
|
|
|
impl BufferRef {
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn map_readable(&self) -> Option<BufferMap<Readable>> {
|
2017-07-25 12:01:24 +00:00
|
|
|
let mut map_info: ffi::GstMapInfo = unsafe { mem::zeroed() };
|
|
|
|
let res =
|
|
|
|
unsafe { ffi::gst_buffer_map(self.as_mut_ptr(), &mut map_info, ffi::GST_MAP_READ) };
|
|
|
|
if res == glib_ffi::GTRUE {
|
2017-08-11 12:20:43 +00:00
|
|
|
Some(BufferMap {
|
2017-07-25 12:01:24 +00:00
|
|
|
buffer: self,
|
|
|
|
map_info: map_info,
|
2017-08-11 12:20:43 +00:00
|
|
|
phantom: PhantomData,
|
2017-07-25 12:01:24 +00:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn map_writable(&mut self) -> Option<BufferMap<Writable>> {
|
2017-07-25 12:01:24 +00:00
|
|
|
let mut map_info: ffi::GstMapInfo = unsafe { mem::zeroed() };
|
|
|
|
let res = unsafe {
|
|
|
|
ffi::gst_buffer_map(self.as_mut_ptr(), &mut map_info, ffi::GST_MAP_READWRITE)
|
|
|
|
};
|
|
|
|
if res == glib_ffi::GTRUE {
|
2017-08-11 12:20:43 +00:00
|
|
|
Some(BufferMap {
|
2017-07-25 12:01:24 +00:00
|
|
|
buffer: self,
|
|
|
|
map_info: map_info,
|
2017-08-11 12:20:43 +00:00
|
|
|
phantom: PhantomData,
|
2017-07-25 12:01:24 +00:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn copy_region(&self, offset: usize, size: Option<usize>) -> Option<Buffer> {
|
|
|
|
let size_real = size.unwrap_or(usize::MAX);
|
|
|
|
let ptr = unsafe {
|
|
|
|
ffi::gst_buffer_copy_region(
|
|
|
|
self.as_mut_ptr(),
|
|
|
|
ffi::GST_BUFFER_COPY_ALL,
|
|
|
|
offset,
|
|
|
|
size_real,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
if ptr.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(unsafe { from_glib_full(ptr) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), usize> {
|
|
|
|
let maxsize = self.get_maxsize();
|
|
|
|
let size = slice.len();
|
|
|
|
|
|
|
|
assert!(maxsize >= offset && maxsize - offset >= size);
|
|
|
|
|
|
|
|
let copied = unsafe {
|
|
|
|
let src = slice.as_ptr();
|
|
|
|
ffi::gst_buffer_fill(
|
|
|
|
self.as_mut_ptr(),
|
|
|
|
offset,
|
|
|
|
src as glib_ffi::gconstpointer,
|
|
|
|
size,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
if copied == size {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(copied)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), usize> {
|
|
|
|
let maxsize = self.get_size();
|
|
|
|
let size = slice.len();
|
|
|
|
|
|
|
|
assert!(maxsize >= offset && maxsize - offset >= size);
|
|
|
|
|
|
|
|
let copied = unsafe {
|
|
|
|
let dest = slice.as_mut_ptr();
|
|
|
|
ffi::gst_buffer_extract(self.as_mut_ptr(), offset, dest as glib_ffi::gpointer, size)
|
|
|
|
};
|
|
|
|
|
|
|
|
if copied == size {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(copied)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-28 17:20:11 +00:00
|
|
|
pub fn copy_deep(&self) -> Buffer {
|
2017-07-31 11:16:42 +00:00
|
|
|
unsafe { from_glib_full(ffi::gst_buffer_copy_deep(self.as_ptr())) }
|
2017-07-28 17:20:11 +00:00
|
|
|
}
|
|
|
|
|
2017-07-25 12:01:24 +00:00
|
|
|
pub fn get_size(&self) -> usize {
|
|
|
|
unsafe { ffi::gst_buffer_get_size(self.as_mut_ptr()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_maxsize(&self) -> usize {
|
|
|
|
let mut maxsize: usize = 0;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
ffi::gst_buffer_get_sizes_range(
|
|
|
|
self.as_mut_ptr(),
|
|
|
|
0,
|
|
|
|
-1,
|
|
|
|
ptr::null_mut(),
|
|
|
|
&mut maxsize,
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
maxsize
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_size(&mut self, size: usize) {
|
|
|
|
assert!(self.get_maxsize() >= size);
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
ffi::gst_buffer_set_size(self.as_mut_ptr(), size as isize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_offset(&self) -> u64 {
|
|
|
|
self.0.offset
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_offset(&mut self, offset: u64) {
|
|
|
|
self.0.offset = offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_offset_end(&self) -> u64 {
|
|
|
|
self.0.offset_end
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_offset_end(&mut self, offset_end: u64) {
|
|
|
|
self.0.offset_end = offset_end;
|
|
|
|
}
|
|
|
|
|
2017-07-25 12:31:45 +00:00
|
|
|
pub fn get_pts(&self) -> ClockTime {
|
2017-11-11 10:21:55 +00:00
|
|
|
from_glib(self.0.pts)
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-07-25 12:31:45 +00:00
|
|
|
pub fn set_pts(&mut self, pts: ClockTime) {
|
2017-11-11 10:21:55 +00:00
|
|
|
self.0.pts = pts.to_glib();
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-07-25 12:31:45 +00:00
|
|
|
pub fn get_dts(&self) -> ClockTime {
|
2017-11-11 10:21:55 +00:00
|
|
|
from_glib(self.0.dts)
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-07-25 12:31:45 +00:00
|
|
|
pub fn set_dts(&mut self, dts: ClockTime) {
|
2017-11-11 10:21:55 +00:00
|
|
|
self.0.dts = dts.to_glib();
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-12-02 10:15:07 +00:00
|
|
|
pub fn get_dts_or_pts(&self) -> ClockTime {
|
|
|
|
let val = self.get_dts();
|
|
|
|
if val.is_none() {
|
|
|
|
self.get_pts()
|
|
|
|
} else {
|
|
|
|
val
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-25 12:31:45 +00:00
|
|
|
pub fn get_duration(&self) -> ClockTime {
|
2017-11-11 10:21:55 +00:00
|
|
|
from_glib(self.0.duration)
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-07-25 12:31:45 +00:00
|
|
|
pub fn set_duration(&mut self, duration: ClockTime) {
|
2017-11-11 10:21:55 +00:00
|
|
|
self.0.duration = duration.to_glib();
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_flags(&self) -> BufferFlags {
|
|
|
|
BufferFlags::from_bits_truncate(self.0.mini_object.flags)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_flags(&mut self, flags: BufferFlags) {
|
|
|
|
self.0.mini_object.flags = flags.bits();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl Sync for BufferRef {}
|
|
|
|
unsafe impl Send for BufferRef {}
|
|
|
|
|
2017-09-16 16:27:46 +00:00
|
|
|
impl glib::types::StaticType for BufferRef {
|
2017-07-25 12:01:24 +00:00
|
|
|
fn static_type() -> glib::types::Type {
|
|
|
|
unsafe { from_glib(ffi::gst_buffer_get_type()) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-04 15:51:27 +00:00
|
|
|
impl ToOwned for BufferRef {
|
|
|
|
type Owned = GstRc<BufferRef>;
|
|
|
|
|
|
|
|
fn to_owned(&self) -> GstRc<BufferRef> {
|
|
|
|
unsafe {
|
2017-10-17 09:06:51 +00:00
|
|
|
from_glib_full(ffi::gst_mini_object_copy(self.as_ptr() as *const _)
|
|
|
|
as *mut _)
|
2017-08-04 15:51:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-25 12:01:24 +00:00
|
|
|
impl fmt::Debug for BufferRef {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2017-12-01 09:21:20 +00:00
|
|
|
f.debug_struct("Buffer")
|
2017-12-01 17:01:18 +00:00
|
|
|
.field("pts", &self.get_pts().to_string())
|
|
|
|
.field("dts", &self.get_dts().to_string())
|
|
|
|
.field("duration", &self.get_duration().to_string())
|
2017-12-01 09:21:20 +00:00
|
|
|
.field("size", &self.get_size())
|
|
|
|
.field("offset", &self.get_offset())
|
|
|
|
.field("offset_end", &self.get_offset_end())
|
|
|
|
.field("flags", &self.get_flags())
|
|
|
|
.finish()
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for BufferRef {
|
|
|
|
fn eq(&self, other: &BufferRef) -> bool {
|
|
|
|
if self.get_size() != other.get_size() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
let self_map = self.map_readable();
|
|
|
|
let other_map = other.map_readable();
|
2017-07-25 12:01:24 +00:00
|
|
|
|
|
|
|
match (self_map, other_map) {
|
|
|
|
(Some(self_map), Some(other_map)) => self_map.as_slice().eq(other_map.as_slice()),
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for BufferRef {}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
impl<'a, T> BufferMap<'a, T> {
|
2017-07-25 12:01:24 +00:00
|
|
|
pub fn get_size(&self) -> usize {
|
|
|
|
self.map_info.size
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_buffer(&self) -> &BufferRef {
|
|
|
|
self.buffer
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn as_slice(&self) -> &[u8] {
|
|
|
|
unsafe { slice::from_raw_parts(self.map_info.data as *const u8, self.map_info.size) }
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
impl<'a> BufferMap<'a, Writable> {
|
2017-07-25 12:01:24 +00:00
|
|
|
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) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
impl<'a, T> Drop for BufferMap<'a, T> {
|
2017-07-25 12:01:24 +00:00
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
ffi::gst_buffer_unmap(self.buffer.as_mut_ptr(), &mut self.map_info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
impl<T> MappedBuffer<T> {
|
2017-07-25 12:01:24 +00:00
|
|
|
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) -> &BufferRef {
|
2017-08-11 12:20:43 +00:00
|
|
|
self.buffer.as_ref().unwrap().as_ref()
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
pub fn into_buffer(mut self) -> Buffer {
|
|
|
|
let buffer = self.buffer.take().unwrap();
|
2017-07-25 12:01:24 +00:00
|
|
|
unsafe {
|
2017-08-11 12:20:43 +00:00
|
|
|
ffi::gst_buffer_unmap(buffer.as_mut_ptr(), &mut self.map_info);
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
2017-08-11 12:20:43 +00:00
|
|
|
|
|
|
|
buffer
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
impl MappedBuffer<Writable> {
|
2017-07-25 12:01:24 +00:00
|
|
|
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) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-13 07:58:41 +00:00
|
|
|
impl<T> AsRef<[u8]> for MappedBuffer<T> {
|
|
|
|
fn as_ref(&self) -> &[u8] {
|
|
|
|
self.as_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsMut<[u8]> for MappedBuffer<Writable> {
|
|
|
|
fn as_mut(&mut self) -> &mut [u8] {
|
|
|
|
self.as_mut_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
impl<T> Drop for MappedBuffer<T> {
|
2017-07-25 12:01:24 +00:00
|
|
|
fn drop(&mut self) {
|
2017-08-11 12:20:43 +00:00
|
|
|
if let Some(ref buffer) = self.buffer {
|
|
|
|
unsafe {
|
|
|
|
ffi::gst_buffer_unmap(buffer.as_mut_ptr(), &mut self.map_info);
|
|
|
|
}
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-13 07:58:41 +00:00
|
|
|
impl<T> fmt::Debug for MappedBuffer<T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
f.debug_tuple("MappedBuffer")
|
|
|
|
.field(&self.get_buffer())
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> PartialEq for MappedBuffer<T> {
|
|
|
|
fn eq(&self, other: &MappedBuffer<T>) -> bool {
|
|
|
|
self.get_buffer().eq(other.get_buffer())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Eq for MappedBuffer<T> {}
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
unsafe impl<T> Send for MappedBuffer<T> {}
|
2017-07-25 12:01:24 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fields() {
|
|
|
|
::init().unwrap();
|
|
|
|
|
|
|
|
let mut buffer = Buffer::new();
|
|
|
|
|
|
|
|
{
|
|
|
|
let buffer = buffer.get_mut().unwrap();
|
2017-11-11 10:21:55 +00:00
|
|
|
buffer.set_pts(1.into());
|
|
|
|
buffer.set_dts(2.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
buffer.set_offset(3);
|
|
|
|
buffer.set_offset_end(4);
|
2017-11-11 10:21:55 +00:00
|
|
|
buffer.set_duration(5.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
2017-11-11 10:21:55 +00:00
|
|
|
assert_eq!(buffer.get_pts(), 1.into());
|
|
|
|
assert_eq!(buffer.get_dts(), 2.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
assert_eq!(buffer.get_offset(), 3);
|
|
|
|
assert_eq!(buffer.get_offset_end(), 4);
|
2017-11-11 10:21:55 +00:00
|
|
|
assert_eq!(buffer.get_duration(), 5.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_writability() {
|
|
|
|
::init().unwrap();
|
|
|
|
|
2017-10-20 16:37:38 +00:00
|
|
|
let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]).unwrap();
|
2017-07-25 12:01:24 +00:00
|
|
|
{
|
2017-08-11 12:20:43 +00:00
|
|
|
let data = buffer.map_readable().unwrap();
|
2017-07-25 12:01:24 +00:00
|
|
|
assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
|
|
|
|
}
|
|
|
|
assert_ne!(buffer.get_mut(), None);
|
|
|
|
{
|
|
|
|
let buffer = buffer.get_mut().unwrap();
|
2017-11-11 10:21:55 +00:00
|
|
|
buffer.set_pts(1.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut buffer2 = buffer.clone();
|
|
|
|
assert_eq!(buffer.get_mut(), None);
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
assert_eq!(buffer2.as_ptr(), buffer.as_ptr());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let buffer2 = buffer2.make_mut();
|
|
|
|
unsafe {
|
|
|
|
assert_ne!(buffer2.as_ptr(), buffer.as_ptr());
|
|
|
|
}
|
|
|
|
|
2017-11-11 10:21:55 +00:00
|
|
|
buffer2.set_pts(2.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
let mut data = buffer2.map_writable().unwrap();
|
2017-07-25 12:01:24 +00:00
|
|
|
assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
|
|
|
|
data.as_mut_slice()[0] = 0;
|
|
|
|
}
|
|
|
|
|
2017-11-11 10:21:55 +00:00
|
|
|
assert_eq!(buffer.get_pts(), 1.into());
|
|
|
|
assert_eq!(buffer2.get_pts(), 2.into());
|
2017-07-25 12:01:24 +00:00
|
|
|
|
|
|
|
{
|
2017-08-11 12:20:43 +00:00
|
|
|
let data = buffer.map_readable().unwrap();
|
2017-07-25 12:01:24 +00:00
|
|
|
assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
|
|
|
|
|
2017-08-11 12:20:43 +00:00
|
|
|
let data = buffer2.map_readable().unwrap();
|
2017-07-25 12:01:24 +00:00
|
|
|
assert_eq!(data.as_slice(), vec![0, 2, 3, 4].as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|