mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-01-19 07:35:46 +00:00
Implement GstRc/GstRef wrapper for GstMiniObject
Keeps the miniobject specific code local and provides a more similar API to Rc/Arc. Also makes it impossible to accidentially try writing to an unwritable miniobject.
This commit is contained in:
parent
99a9b7fedc
commit
7b5764e759
15 changed files with 505 additions and 493 deletions
|
@ -167,10 +167,7 @@ impl Source for FileSrc {
|
||||||
|
|
||||||
*position += size as u64;
|
*position += size as u64;
|
||||||
|
|
||||||
if let Err(err) = buffer.set_size(size) {
|
buffer.set_size(size);
|
||||||
return Err(FlowError::Error(error_msg!(SourceError::Failure,
|
|
||||||
["Failed to resize buffer: {}", err])));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ use gst_plugin::utils;
|
||||||
use gst_plugin::utils::Element;
|
use gst_plugin::utils::Element;
|
||||||
use gst_plugin::log::*;
|
use gst_plugin::log::*;
|
||||||
use gst_plugin::caps::Caps;
|
use gst_plugin::caps::Caps;
|
||||||
|
use gst_plugin::miniobject::*;
|
||||||
use gst_plugin::value::Rational32;
|
use gst_plugin::value::Rational32;
|
||||||
use gst_plugin::bytes::*;
|
use gst_plugin::bytes::*;
|
||||||
|
|
||||||
|
@ -62,8 +63,8 @@ struct StreamingState {
|
||||||
|
|
||||||
metadata: Option<Metadata>,
|
metadata: Option<Metadata>,
|
||||||
|
|
||||||
aac_sequence_header: Option<Buffer>,
|
aac_sequence_header: Option<GstRc<Buffer>>,
|
||||||
avc_sequence_header: Option<Buffer>,
|
avc_sequence_header: Option<GstRc<Buffer>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StreamingState {
|
impl StreamingState {
|
||||||
|
@ -89,7 +90,7 @@ struct AudioFormat {
|
||||||
width: u8,
|
width: u8,
|
||||||
channels: u8,
|
channels: u8,
|
||||||
bitrate: Option<u32>,
|
bitrate: Option<u32>,
|
||||||
aac_sequence_header: Option<Buffer>,
|
aac_sequence_header: Option<GstRc<Buffer>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignores bitrate
|
// Ignores bitrate
|
||||||
|
@ -104,7 +105,7 @@ impl PartialEq for AudioFormat {
|
||||||
impl AudioFormat {
|
impl AudioFormat {
|
||||||
fn new(data_header: &flavors::AudioDataHeader,
|
fn new(data_header: &flavors::AudioDataHeader,
|
||||||
metadata: &Option<Metadata>,
|
metadata: &Option<Metadata>,
|
||||||
aac_sequence_header: &Option<Buffer>)
|
aac_sequence_header: &Option<GstRc<Buffer>>)
|
||||||
-> AudioFormat {
|
-> AudioFormat {
|
||||||
let numeric_rate = match (data_header.sound_format, data_header.sound_rate) {
|
let numeric_rate = match (data_header.sound_format, data_header.sound_rate) {
|
||||||
(flavors::SoundFormat::NELLYMOSER_16KHZ_MONO, _) => 16000,
|
(flavors::SoundFormat::NELLYMOSER_16KHZ_MONO, _) => 16000,
|
||||||
|
@ -152,7 +153,7 @@ impl AudioFormat {
|
||||||
self.to_caps().map(|c| c.to_string())
|
self.to_caps().map(|c| c.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_caps(&self) -> Option<Caps> {
|
fn to_caps(&self) -> Option<GstRc<Caps>> {
|
||||||
let mut caps = match self.format {
|
let mut caps = match self.format {
|
||||||
flavors::SoundFormat::MP3 |
|
flavors::SoundFormat::MP3 |
|
||||||
flavors::SoundFormat::MP3_8KHZ => {
|
flavors::SoundFormat::MP3_8KHZ => {
|
||||||
|
@ -190,7 +191,7 @@ impl AudioFormat {
|
||||||
&[("mpegversion", &4.into()),
|
&[("mpegversion", &4.into()),
|
||||||
("framed", &true.into()),
|
("framed", &true.into()),
|
||||||
("stream-format", &"raw".into()),
|
("stream-format", &"raw".into()),
|
||||||
("codec_data", &header.into())])
|
("codec_data", &header.as_ref().into())])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
flavors::SoundFormat::SPEEX => {
|
flavors::SoundFormat::SPEEX => {
|
||||||
|
@ -245,11 +246,13 @@ impl AudioFormat {
|
||||||
|
|
||||||
if self.rate != 0 {
|
if self.rate != 0 {
|
||||||
caps.as_mut()
|
caps.as_mut()
|
||||||
.map(|c| c.set_simple(&[("rate", &(self.rate as i32).into())]));
|
.map(|c| c.get_mut().unwrap().set_simple(&[("rate", &(self.rate as i32).into())]));
|
||||||
}
|
}
|
||||||
if self.channels != 0 {
|
if self.channels != 0 {
|
||||||
caps.as_mut()
|
caps.as_mut()
|
||||||
.map(|c| c.set_simple(&[("channels", &(self.channels as i32).into())]));
|
.map(|c| {
|
||||||
|
c.get_mut().unwrap().set_simple(&[("channels", &(self.channels as i32).into())])
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
caps
|
caps
|
||||||
|
@ -264,13 +267,13 @@ struct VideoFormat {
|
||||||
pixel_aspect_ratio: Option<Rational32>,
|
pixel_aspect_ratio: Option<Rational32>,
|
||||||
framerate: Option<Rational32>,
|
framerate: Option<Rational32>,
|
||||||
bitrate: Option<u32>,
|
bitrate: Option<u32>,
|
||||||
avc_sequence_header: Option<Buffer>,
|
avc_sequence_header: Option<GstRc<Buffer>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VideoFormat {
|
impl VideoFormat {
|
||||||
fn new(data_header: &flavors::VideoDataHeader,
|
fn new(data_header: &flavors::VideoDataHeader,
|
||||||
metadata: &Option<Metadata>,
|
metadata: &Option<Metadata>,
|
||||||
avc_sequence_header: &Option<Buffer>)
|
avc_sequence_header: &Option<GstRc<Buffer>>)
|
||||||
-> VideoFormat {
|
-> VideoFormat {
|
||||||
VideoFormat {
|
VideoFormat {
|
||||||
format: data_header.codec_id,
|
format: data_header.codec_id,
|
||||||
|
@ -318,7 +321,7 @@ impl VideoFormat {
|
||||||
self.to_caps().map(|caps| caps.to_string())
|
self.to_caps().map(|caps| caps.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_caps(&self) -> Option<Caps> {
|
fn to_caps(&self) -> Option<GstRc<Caps>> {
|
||||||
let mut caps = match self.format {
|
let mut caps = match self.format {
|
||||||
flavors::CodecId::SORENSON_H263 => {
|
flavors::CodecId::SORENSON_H263 => {
|
||||||
Some(Caps::new_simple("video/x-flash-video", &[("flvversion", &1.into())]))
|
Some(Caps::new_simple("video/x-flash-video", &[("flvversion", &1.into())]))
|
||||||
|
@ -331,7 +334,7 @@ impl VideoFormat {
|
||||||
self.avc_sequence_header.as_ref().map(|header| {
|
self.avc_sequence_header.as_ref().map(|header| {
|
||||||
Caps::new_simple("video/x-h264",
|
Caps::new_simple("video/x-h264",
|
||||||
&[("stream-format", &"avc".into()),
|
&[("stream-format", &"avc".into()),
|
||||||
("codec_data", &header.into())])
|
("codec_data", &header.as_ref().into())])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
flavors::CodecId::H263 => Some(Caps::new_simple("video/x-h263", &[])),
|
flavors::CodecId::H263 => Some(Caps::new_simple("video/x-h263", &[])),
|
||||||
|
@ -348,21 +351,23 @@ impl VideoFormat {
|
||||||
|
|
||||||
if let (Some(width), Some(height)) = (self.width, self.height) {
|
if let (Some(width), Some(height)) = (self.width, self.height) {
|
||||||
caps.as_mut().map(|c| {
|
caps.as_mut().map(|c| {
|
||||||
c.set_simple(&[("width", &(width as i32).into()),
|
c.get_mut().unwrap().set_simple(&[("width", &(width as i32).into()),
|
||||||
("height", &(height as i32).into())])
|
("height", &(height as i32).into())])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(par) = self.pixel_aspect_ratio {
|
if let Some(par) = self.pixel_aspect_ratio {
|
||||||
if *par.numer() != 0 && par.numer() != par.denom() {
|
if *par.numer() != 0 && par.numer() != par.denom() {
|
||||||
caps.as_mut().map(|c| c.set_simple(&[("pixel-aspect-ratio", &par.into())]));
|
caps.as_mut().map(|c| {
|
||||||
|
c.get_mut().unwrap().set_simple(&[("pixel-aspect-ratio", &par.into())])
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fps) = self.framerate {
|
if let Some(fps) = self.framerate {
|
||||||
if *fps.numer() != 0 {
|
if *fps.numer() != 0 {
|
||||||
caps.as_mut()
|
caps.as_mut()
|
||||||
.map(|c| c.set_simple(&[("framerate", &fps.into())]));
|
.map(|c| c.get_mut().unwrap().set_simple(&[("framerate", &fps.into())]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,7 +705,11 @@ impl FlvDemux {
|
||||||
.get_buffer((tag_header.data_size - 1 - offset) as usize)
|
.get_buffer((tag_header.data_size - 1 - offset) as usize)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
buffer.set_pts(Some((tag_header.timestamp as u64) * 1000 * 1000)).unwrap();
|
{
|
||||||
|
let buffer = buffer.get_mut().unwrap();
|
||||||
|
buffer.set_pts(Some((tag_header.timestamp as u64) * 1000 * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
trace!(self.logger,
|
trace!(self.logger,
|
||||||
"Outputting audio buffer {:?} for tag {:?} of size {}",
|
"Outputting audio buffer {:?} for tag {:?} of size {}",
|
||||||
buffer,
|
buffer,
|
||||||
|
@ -850,19 +859,22 @@ impl FlvDemux {
|
||||||
let mut buffer = self.adapter
|
let mut buffer = self.adapter
|
||||||
.get_buffer((tag_header.data_size - 1 - offset) as usize)
|
.get_buffer((tag_header.data_size - 1 - offset) as usize)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if !is_keyframe {
|
|
||||||
buffer.set_flags(BUFFER_FLAG_DELTA_UNIT).unwrap();
|
|
||||||
}
|
|
||||||
buffer.set_dts(Some((tag_header.timestamp as u64) * 1000 * 1000))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Prevent negative numbers
|
{
|
||||||
let pts = if cts < 0 && tag_header.timestamp < (-cts) as u32 {
|
let buffer = buffer.get_mut().unwrap();
|
||||||
0
|
if !is_keyframe {
|
||||||
} else {
|
buffer.set_flags(BUFFER_FLAG_DELTA_UNIT);
|
||||||
((tag_header.timestamp as i64) + (cts as i64)) as u64
|
}
|
||||||
};
|
buffer.set_dts(Some((tag_header.timestamp as u64) * 1000 * 1000));
|
||||||
buffer.set_pts(Some(pts * 1000 * 1000)).unwrap();
|
|
||||||
|
// Prevent negative numbers
|
||||||
|
let pts = if cts < 0 && tag_header.timestamp < (-cts) as u32 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
((tag_header.timestamp as i64) + (cts as i64)) as u64
|
||||||
|
};
|
||||||
|
buffer.set_pts(Some(pts * 1000 * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
trace!(self.logger,
|
trace!(self.logger,
|
||||||
"Outputting video buffer {:?} for tag {:?} of size {}, keyframe: {}",
|
"Outputting video buffer {:?} for tag {:?} of size {}, keyframe: {}",
|
||||||
|
@ -1030,7 +1042,9 @@ impl Demuxer for FlvDemux {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_buffer(&mut self, buffer: Option<Buffer>) -> Result<HandleBufferResult, FlowError> {
|
fn handle_buffer(&mut self,
|
||||||
|
buffer: Option<GstRc<Buffer>>)
|
||||||
|
-> Result<HandleBufferResult, FlowError> {
|
||||||
if let Some(buffer) = buffer {
|
if let Some(buffer) = buffer {
|
||||||
self.adapter.push(buffer);
|
self.adapter.push(buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,11 +243,7 @@ impl Source for HttpSrc {
|
||||||
|
|
||||||
*position += size as u64;
|
*position += size as u64;
|
||||||
|
|
||||||
if let Err(err) = buffer.set_size(size) {
|
buffer.set_size(size);
|
||||||
return Err(FlowError::Error(error_msg!(SourceError::Failure,
|
|
||||||
["Failed to resize buffer: {}", err])));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
use buffer::*;
|
use buffer::*;
|
||||||
|
use miniobject::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -55,7 +56,7 @@ impl Adapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, buffer: Buffer) {
|
pub fn push(&mut self, buffer: GstRc<Buffer>) {
|
||||||
let size = buffer.get_size();
|
let size = buffer.get_size();
|
||||||
|
|
||||||
self.size += size;
|
self.size += size;
|
||||||
|
@ -64,7 +65,7 @@ impl Adapter {
|
||||||
buffer,
|
buffer,
|
||||||
size,
|
size,
|
||||||
self.size);
|
self.size);
|
||||||
self.deque.push_back(buffer.into_read_mapped_buffer().unwrap());
|
self.deque.push_back(Buffer::into_read_mapped_buffer(buffer).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
|
@ -159,7 +160,7 @@ impl Adapter {
|
||||||
Ok(self.scratch.as_slice())
|
Ok(self.scratch.as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_buffer(&mut self, size: usize) -> Result<Buffer, AdapterError> {
|
pub fn get_buffer(&mut self, size: usize) -> Result<GstRc<Buffer>, AdapterError> {
|
||||||
if self.size < size {
|
if self.size < size {
|
||||||
debug!(LOGGER,
|
debug!(LOGGER,
|
||||||
"Get buffer of {} bytes, not enough data: have {}",
|
"Get buffer of {} bytes, not enough data: have {}",
|
||||||
|
@ -172,14 +173,12 @@ impl Adapter {
|
||||||
return Ok(Buffer::new());
|
return Ok(Buffer::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let sub = self.deque.front().and_then(|front| {
|
let sub = self.deque.front().and_then(|front| if front.get_size() - self.skip >= size {
|
||||||
if front.get_size() - self.skip >= size {
|
trace!(LOGGER, "Get buffer of {} bytes, subbuffer of first", size);
|
||||||
trace!(LOGGER, "Get buffer of {} bytes, subbuffer of first", size);
|
let new = front.get_buffer().copy_region(self.skip, Some(size)).unwrap();
|
||||||
let new = front.get_buffer().copy_region(self.skip, Some(size)).unwrap();
|
Some(new)
|
||||||
Some(new)
|
} else {
|
||||||
} else {
|
None
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(s) = sub {
|
if let Some(s) = sub {
|
||||||
|
@ -190,7 +189,7 @@ impl Adapter {
|
||||||
trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size);
|
trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size);
|
||||||
let mut new = Buffer::new_with_size(size).unwrap();
|
let mut new = Buffer::new_with_size(size).unwrap();
|
||||||
{
|
{
|
||||||
let mut map = new.map_readwrite().unwrap();
|
let mut map = new.get_mut().unwrap().map_readwrite().unwrap();
|
||||||
let data = map.as_mut_slice();
|
let data = map.as_mut_slice();
|
||||||
Self::copy_data(&self.deque, self.skip, data, size);
|
Self::copy_data(&self.deque, self.skip, data, size);
|
||||||
}
|
}
|
||||||
|
@ -244,7 +243,6 @@ impl Adapter {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use buffer::*;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,18 @@ gst_rs_buffer_set_dts (GstBuffer * buffer, guint64 dts)
|
||||||
GST_BUFFER_DTS (buffer) = dts;
|
GST_BUFFER_DTS (buffer) = dts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint64
|
||||||
|
gst_rs_buffer_get_duration (GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
return GST_BUFFER_DURATION (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_rs_buffer_set_duration (GstBuffer * buffer, guint64 dts)
|
||||||
|
{
|
||||||
|
GST_BUFFER_DURATION (buffer) = dts;
|
||||||
|
}
|
||||||
|
|
||||||
guint64
|
guint64
|
||||||
gst_rs_buffer_get_offset (GstBuffer * buffer)
|
gst_rs_buffer_get_offset (GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,21 +20,14 @@ use std::ptr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::u64;
|
use std::u64;
|
||||||
use std::usize;
|
use std::usize;
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use std::fmt::Error as FmtError;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
use miniobject::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Buffer {
|
pub struct Buffer(*mut c_void);
|
||||||
raw: *mut c_void,
|
|
||||||
owned: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -62,77 +55,40 @@ pub struct ReadWriteBufferMap<'a> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ReadMappedBuffer {
|
pub struct ReadMappedBuffer {
|
||||||
buffer: Buffer,
|
buffer: GstRc<Buffer>,
|
||||||
map_info: GstMapInfo,
|
map_info: GstMapInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ReadWriteMappedBuffer {
|
pub struct ReadWriteMappedBuffer {
|
||||||
buffer: Buffer,
|
buffer: GstRc<Buffer>,
|
||||||
map_info: GstMapInfo,
|
map_info: GstMapInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
unsafe impl MiniObject for Buffer {
|
||||||
pub enum BufferError {
|
unsafe fn as_ptr(&self) -> *mut c_void {
|
||||||
NotWritable,
|
self.0
|
||||||
NotEnoughSpace,
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for BufferError {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
|
||||||
f.write_str(self.description())
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for BufferError {
|
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) {
|
||||||
fn description(&self) -> &str {
|
self.0 = ptr
|
||||||
match *self {
|
}
|
||||||
BufferError::NotWritable => "Not Writable",
|
|
||||||
BufferError::NotEnoughSpace => "Not Enough Space",
|
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self {
|
||||||
BufferError::Unknown => "Unknown",
|
Buffer(ptr)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
pub unsafe fn new_from_ptr(raw: *mut c_void) -> Buffer {
|
pub fn new() -> GstRc<Buffer> {
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void;
|
|
||||||
};
|
|
||||||
Buffer {
|
|
||||||
raw: gst_mini_object_ref(raw),
|
|
||||||
owned: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn new_from_ptr_owned(raw: *mut c_void) -> Buffer {
|
|
||||||
Buffer {
|
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn new_from_ptr_scoped(raw: *mut c_void) -> Buffer {
|
|
||||||
Buffer {
|
|
||||||
raw: raw,
|
|
||||||
owned: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new() -> Buffer {
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_new() -> *mut c_void;
|
fn gst_buffer_new() -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let raw = unsafe { gst_buffer_new() };
|
unsafe { GstRc::new_from_owned_ptr(gst_buffer_new()) }
|
||||||
Buffer {
|
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_size(size: usize) -> Option<Buffer> {
|
pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_new_allocate(allocator: *const c_void,
|
fn gst_buffer_new_allocate(allocator: *const c_void,
|
||||||
size: usize,
|
size: usize,
|
||||||
|
@ -144,10 +100,7 @@ impl Buffer {
|
||||||
if raw.is_null() {
|
if raw.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Buffer {
|
Some(unsafe { GstRc::new_from_owned_ptr(raw) })
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +109,7 @@ impl Buffer {
|
||||||
drop(vec);
|
drop(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_vec(vec: Vec<u8>) -> Option<Buffer> {
|
pub fn new_from_vec(vec: Vec<u8>) -> Option<GstRc<Buffer>> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_new_wrapped_full(flags: u32,
|
fn gst_buffer_new_wrapped_full(flags: u32,
|
||||||
data: *mut u8,
|
data: *mut u8,
|
||||||
|
@ -186,10 +139,7 @@ impl Buffer {
|
||||||
if raw.is_null() {
|
if raw.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Buffer {
|
Some(unsafe { GstRc::new_from_owned_ptr(raw) })
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +153,7 @@ impl Buffer {
|
||||||
|
|
||||||
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res =
|
let res =
|
||||||
unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) };
|
unsafe { gst_buffer_map(self.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) };
|
||||||
if res.to_bool() {
|
if res.to_bool() {
|
||||||
Some(ReadBufferMap {
|
Some(ReadBufferMap {
|
||||||
buffer: self,
|
buffer: self,
|
||||||
|
@ -223,11 +173,8 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res = unsafe {
|
let res =
|
||||||
gst_buffer_map(self.raw,
|
unsafe { gst_buffer_map(self.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READWRITE) };
|
||||||
&mut map_info as *mut GstMapInfo,
|
|
||||||
MAP_FLAG_READWRITE)
|
|
||||||
};
|
|
||||||
if res.to_bool() {
|
if res.to_bool() {
|
||||||
Some(ReadWriteBufferMap {
|
Some(ReadWriteBufferMap {
|
||||||
buffer: self,
|
buffer: self,
|
||||||
|
@ -238,7 +185,7 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_read_mapped_buffer(self) -> Option<ReadMappedBuffer> {
|
pub fn into_read_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadMappedBuffer> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_map(buffer: *mut c_void,
|
fn gst_buffer_map(buffer: *mut c_void,
|
||||||
map: *mut GstMapInfo,
|
map: *mut GstMapInfo,
|
||||||
|
@ -248,10 +195,10 @@ impl Buffer {
|
||||||
|
|
||||||
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res =
|
let res =
|
||||||
unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) };
|
unsafe { gst_buffer_map(buffer.0, &mut map_info as *mut GstMapInfo, MAP_FLAG_READ) };
|
||||||
if res.to_bool() {
|
if res.to_bool() {
|
||||||
Some(ReadMappedBuffer {
|
Some(ReadMappedBuffer {
|
||||||
buffer: self,
|
buffer: buffer,
|
||||||
map_info: map_info,
|
map_info: map_info,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -259,7 +206,7 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_readwrite_mapped_buffer(self) -> Option<ReadWriteMappedBuffer> {
|
pub fn into_readwrite_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadWriteMappedBuffer> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_map(buffer: *mut c_void,
|
fn gst_buffer_map(buffer: *mut c_void,
|
||||||
map: *mut GstMapInfo,
|
map: *mut GstMapInfo,
|
||||||
|
@ -269,13 +216,13 @@ impl Buffer {
|
||||||
|
|
||||||
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
gst_buffer_map(self.raw,
|
gst_buffer_map(buffer.0,
|
||||||
&mut map_info as *mut GstMapInfo,
|
&mut map_info as *mut GstMapInfo,
|
||||||
MAP_FLAG_READWRITE)
|
MAP_FLAG_READWRITE)
|
||||||
};
|
};
|
||||||
if res.to_bool() {
|
if res.to_bool() {
|
||||||
Some(ReadWriteMappedBuffer {
|
Some(ReadWriteMappedBuffer {
|
||||||
buffer: self,
|
buffer: buffer,
|
||||||
map_info: map_info,
|
map_info: map_info,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -283,67 +230,15 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn into_ptr(mut self) -> *mut c_void {
|
pub fn append(buffer: GstRc<Buffer>, other: GstRc<Buffer>) -> GstRc<Buffer> {
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void;
|
|
||||||
};
|
|
||||||
if !self.owned {
|
|
||||||
gst_mini_object_ref(self.raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.owned = false;
|
|
||||||
|
|
||||||
self.raw
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *mut c_void {
|
|
||||||
self.raw
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_writable(&self) -> bool {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_is_writable(obj: *const c_void) -> GBoolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = unsafe { gst_mini_object_is_writable(self.raw) };
|
|
||||||
|
|
||||||
res.to_bool()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_writable(self: Buffer) -> Buffer {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let raw = unsafe { gst_mini_object_make_writable(self.raw) };
|
|
||||||
|
|
||||||
Buffer {
|
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy(&self) -> Buffer {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
unsafe { Buffer::new_from_ptr_owned(gst_mini_object_copy(self.raw)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append(self, other: Buffer) -> Buffer {
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_append(buf1: *mut c_void, buf2: *mut c_void) -> *mut c_void;
|
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) };
|
unsafe { GstRc::new_from_owned_ptr(gst_buffer_append(buffer.into_ptr(), other.into_ptr())) }
|
||||||
|
|
||||||
Buffer {
|
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_region(&self, offset: usize, size: Option<usize>) -> Option<Buffer> {
|
pub fn copy_region(&self, offset: usize, size: Option<usize>) -> Option<GstRc<Buffer>> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_copy_region(buf: *mut c_void,
|
fn gst_buffer_copy_region(buf: *mut c_void,
|
||||||
flags: BufferCopyFlags,
|
flags: BufferCopyFlags,
|
||||||
|
@ -355,28 +250,20 @@ impl Buffer {
|
||||||
let size_real = size.unwrap_or(usize::MAX);
|
let size_real = size.unwrap_or(usize::MAX);
|
||||||
|
|
||||||
let raw =
|
let raw =
|
||||||
unsafe { gst_buffer_copy_region(self.raw, BUFFER_COPY_FLAG_ALL, offset, size_real) };
|
unsafe { gst_buffer_copy_region(self.0, BUFFER_COPY_FLAG_ALL, offset, size_real) };
|
||||||
|
|
||||||
if raw.is_null() {
|
if raw.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Buffer {
|
Some(unsafe { GstRc::new_from_owned_ptr(raw) })
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), BufferError> {
|
pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), usize> {
|
||||||
if !self.is_writable() {
|
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
let maxsize = self.get_maxsize();
|
let maxsize = self.get_maxsize();
|
||||||
let size = slice.len();
|
let size = slice.len();
|
||||||
if maxsize < offset || maxsize - offset < size {
|
|
||||||
return Err(BufferError::NotEnoughSpace);
|
assert!(maxsize >= offset && maxsize - offset >= size);
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_fill(buffer: *mut c_void,
|
fn gst_buffer_fill(buffer: *mut c_void,
|
||||||
|
@ -388,22 +275,17 @@ impl Buffer {
|
||||||
|
|
||||||
let copied = unsafe {
|
let copied = unsafe {
|
||||||
let src = slice.as_ptr();
|
let src = slice.as_ptr();
|
||||||
gst_buffer_fill(self.raw, offset, src, size)
|
gst_buffer_fill(self.0, offset, src, size)
|
||||||
};
|
};
|
||||||
|
|
||||||
if copied < size {
|
if copied == size { Ok(()) } else { Err(copied) }
|
||||||
Err(BufferError::Unknown)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), BufferError> {
|
pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), usize> {
|
||||||
let maxsize = self.get_size();
|
let maxsize = self.get_size();
|
||||||
let size = slice.len();
|
let size = slice.len();
|
||||||
if maxsize < offset || maxsize - offset < size {
|
|
||||||
return Err(BufferError::NotEnoughSpace);
|
assert!(maxsize >= offset && maxsize - offset >= size);
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_extract(buffer: *mut c_void,
|
fn gst_buffer_extract(buffer: *mut c_void,
|
||||||
|
@ -415,14 +297,10 @@ impl Buffer {
|
||||||
|
|
||||||
let copied = unsafe {
|
let copied = unsafe {
|
||||||
let src = slice.as_mut_ptr();
|
let src = slice.as_mut_ptr();
|
||||||
gst_buffer_extract(self.raw, offset, src, size)
|
gst_buffer_extract(self.0, offset, src, size)
|
||||||
};
|
};
|
||||||
|
|
||||||
if copied < size {
|
if copied == size { Ok(()) } else { Err(copied) }
|
||||||
Err(BufferError::Unknown)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_size(&self) -> usize {
|
pub fn get_size(&self) -> usize {
|
||||||
|
@ -430,7 +308,7 @@ impl Buffer {
|
||||||
fn gst_buffer_get_size(obj: *const c_void) -> usize;
|
fn gst_buffer_get_size(obj: *const c_void) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { gst_buffer_get_size(self.raw) }
|
unsafe { gst_buffer_get_size(self.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_maxsize(&self) -> usize {
|
pub fn get_maxsize(&self) -> usize {
|
||||||
|
@ -446,34 +324,22 @@ impl Buffer {
|
||||||
let mut maxsize: usize = 0;
|
let mut maxsize: usize = 0;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_buffer_get_sizes_range(self.raw,
|
gst_buffer_get_sizes_range(self.0, 0, -1, ptr::null_mut(), &mut maxsize as *mut usize);
|
||||||
0,
|
|
||||||
-1,
|
|
||||||
ptr::null_mut(),
|
|
||||||
&mut maxsize as *mut usize);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
maxsize
|
maxsize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_size(&mut self, size: usize) -> Result<(), BufferError> {
|
pub fn set_size(&mut self, size: usize) {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_buffer_set_size(obj: *const c_void, size: usize);
|
fn gst_buffer_set_size(obj: *const c_void, size: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.is_writable() {
|
assert!(self.get_maxsize() >= size);
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.get_maxsize() < size {
|
|
||||||
return Err(BufferError::NotEnoughSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_buffer_set_size(self.raw, size);
|
gst_buffer_set_size(self.0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_offset(&self) -> Option<u64> {
|
pub fn get_offset(&self) -> Option<u64> {
|
||||||
|
@ -481,7 +347,7 @@ impl Buffer {
|
||||||
fn gst_rs_buffer_get_offset(buf: *const c_void) -> u64;
|
fn gst_rs_buffer_get_offset(buf: *const c_void) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = unsafe { gst_rs_buffer_get_offset(self.raw) };
|
let offset = unsafe { gst_rs_buffer_get_offset(self.0) };
|
||||||
|
|
||||||
if offset == u64::MAX {
|
if offset == u64::MAX {
|
||||||
None
|
None
|
||||||
|
@ -490,11 +356,7 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_offset(&mut self, offset: Option<u64>) -> Result<(), BufferError> {
|
pub fn set_offset(&mut self, offset: Option<u64>) {
|
||||||
if !self.is_writable() {
|
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_buffer_set_offset(buf: *const c_void, offset: u64);
|
fn gst_rs_buffer_set_offset(buf: *const c_void, offset: u64);
|
||||||
}
|
}
|
||||||
|
@ -502,10 +364,8 @@ impl Buffer {
|
||||||
let offset = offset.unwrap_or(u64::MAX);
|
let offset = offset.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_rs_buffer_set_offset(self.raw, offset);
|
gst_rs_buffer_set_offset(self.0, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_offset_end(&self) -> Option<u64> {
|
pub fn get_offset_end(&self) -> Option<u64> {
|
||||||
|
@ -513,7 +373,7 @@ impl Buffer {
|
||||||
fn gst_rs_buffer_get_offset_end(buf: *const c_void) -> u64;
|
fn gst_rs_buffer_get_offset_end(buf: *const c_void) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset_end = unsafe { gst_rs_buffer_get_offset_end(self.raw) };
|
let offset_end = unsafe { gst_rs_buffer_get_offset_end(self.0) };
|
||||||
|
|
||||||
if offset_end == u64::MAX {
|
if offset_end == u64::MAX {
|
||||||
None
|
None
|
||||||
|
@ -522,11 +382,7 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_offset_end(&mut self, offset_end: Option<u64>) -> Result<(), BufferError> {
|
pub fn set_offset_end(&mut self, offset_end: Option<u64>) {
|
||||||
if !self.is_writable() {
|
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_buffer_set_offset_end(buf: *const c_void, offset_end: u64);
|
fn gst_rs_buffer_set_offset_end(buf: *const c_void, offset_end: u64);
|
||||||
}
|
}
|
||||||
|
@ -534,10 +390,8 @@ impl Buffer {
|
||||||
let offset_end = offset_end.unwrap_or(u64::MAX);
|
let offset_end = offset_end.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_rs_buffer_set_offset_end(self.raw, offset_end);
|
gst_rs_buffer_set_offset_end(self.0, offset_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pts(&self) -> Option<u64> {
|
pub fn get_pts(&self) -> Option<u64> {
|
||||||
|
@ -545,16 +399,12 @@ impl Buffer {
|
||||||
fn gst_rs_buffer_get_pts(buf: *const c_void) -> u64;
|
fn gst_rs_buffer_get_pts(buf: *const c_void) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pts = unsafe { gst_rs_buffer_get_pts(self.raw) };
|
let pts = unsafe { gst_rs_buffer_get_pts(self.0) };
|
||||||
|
|
||||||
if pts == u64::MAX { None } else { Some(pts) }
|
if pts == u64::MAX { None } else { Some(pts) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pts(&mut self, pts: Option<u64>) -> Result<(), BufferError> {
|
pub fn set_pts(&mut self, pts: Option<u64>) {
|
||||||
if !self.is_writable() {
|
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_buffer_set_pts(buf: *const c_void, pts: u64);
|
fn gst_rs_buffer_set_pts(buf: *const c_void, pts: u64);
|
||||||
}
|
}
|
||||||
|
@ -562,10 +412,8 @@ impl Buffer {
|
||||||
let pts = pts.unwrap_or(u64::MAX);
|
let pts = pts.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_rs_buffer_set_pts(self.raw, pts);
|
gst_rs_buffer_set_pts(self.0, pts);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_dts(&self) -> Option<u64> {
|
pub fn get_dts(&self) -> Option<u64> {
|
||||||
|
@ -573,16 +421,12 @@ impl Buffer {
|
||||||
fn gst_rs_buffer_get_dts(buf: *const c_void) -> u64;
|
fn gst_rs_buffer_get_dts(buf: *const c_void) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dts = unsafe { gst_rs_buffer_get_dts(self.raw) };
|
let dts = unsafe { gst_rs_buffer_get_dts(self.0) };
|
||||||
|
|
||||||
if dts == u64::MAX { None } else { Some(dts) }
|
if dts == u64::MAX { None } else { Some(dts) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_dts(&mut self, dts: Option<u64>) -> Result<(), BufferError> {
|
pub fn set_dts(&mut self, dts: Option<u64>) {
|
||||||
if !self.is_writable() {
|
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_buffer_set_dts(buf: *const c_void, dts: u64);
|
fn gst_rs_buffer_set_dts(buf: *const c_void, dts: u64);
|
||||||
}
|
}
|
||||||
|
@ -590,10 +434,34 @@ impl Buffer {
|
||||||
let dts = dts.unwrap_or(u64::MAX);
|
let dts = dts.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_rs_buffer_set_dts(self.raw, dts);
|
gst_rs_buffer_set_dts(self.0, dts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_duration(&self) -> Option<u64> {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_rs_buffer_get_duration(buf: *const c_void) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
let duration = unsafe { gst_rs_buffer_get_duration(self.0) };
|
||||||
|
|
||||||
|
if duration == u64::MAX {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_duration(&mut self, duration: Option<u64>) {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_rs_buffer_set_duration(buf: *const c_void, duration: u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
let duration = duration.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gst_rs_buffer_set_duration(self.0, duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_flags(&self) -> BufferFlags {
|
pub fn get_flags(&self) -> BufferFlags {
|
||||||
|
@ -601,34 +469,16 @@ impl Buffer {
|
||||||
fn gst_rs_buffer_get_flags(buf: *const c_void) -> BufferFlags;
|
fn gst_rs_buffer_get_flags(buf: *const c_void) -> BufferFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { gst_rs_buffer_get_flags(self.raw) }
|
unsafe { gst_rs_buffer_get_flags(self.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_flags(&mut self, flags: BufferFlags) -> Result<(), BufferError> {
|
pub fn set_flags(&mut self, flags: BufferFlags) {
|
||||||
if !self.is_writable() {
|
|
||||||
return Err(BufferError::NotWritable);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_buffer_set_flags(buf: *const c_void, flags: BufferFlags);
|
fn gst_rs_buffer_set_flags(buf: *const c_void, flags: BufferFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_rs_buffer_set_flags(self.raw, flags);
|
gst_rs_buffer_set_flags(self.0, flags);
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Buffer {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_unref(obj: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.owned && !self.raw.is_null() {
|
|
||||||
unsafe { gst_mini_object_unref(self.raw) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,21 +486,6 @@ impl Drop for Buffer {
|
||||||
unsafe impl Sync for Buffer {}
|
unsafe impl Sync for Buffer {}
|
||||||
unsafe impl Send for Buffer {}
|
unsafe impl Send for Buffer {}
|
||||||
|
|
||||||
impl Clone for Buffer {
|
|
||||||
fn clone(&self) -> Buffer {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let raw = unsafe { gst_mini_object_ref(self.raw) };
|
|
||||||
|
|
||||||
Buffer {
|
|
||||||
raw: raw,
|
|
||||||
owned: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for Buffer {
|
impl PartialEq for Buffer {
|
||||||
fn eq(&self, other: &Buffer) -> bool {
|
fn eq(&self, other: &Buffer) -> bool {
|
||||||
if self.get_size() != other.get_size() {
|
if self.get_size() != other.get_size() {
|
||||||
|
@ -677,6 +512,10 @@ impl<'a> ReadBufferMap<'a> {
|
||||||
pub fn get_size(&self) -> usize {
|
pub fn get_size(&self) -> usize {
|
||||||
self.map_info.size
|
self.map_info.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_buffer(&self) -> &Buffer {
|
||||||
|
self.buffer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for ReadBufferMap<'a> {
|
impl<'a> Drop for ReadBufferMap<'a> {
|
||||||
|
@ -686,7 +525,7 @@ impl<'a> Drop for ReadBufferMap<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo);
|
gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,6 +542,10 @@ impl<'a> ReadWriteBufferMap<'a> {
|
||||||
pub fn get_size(&self) -> usize {
|
pub fn get_size(&self) -> usize {
|
||||||
self.map_info.size
|
self.map_info.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_buffer(&self) -> &Buffer {
|
||||||
|
self.buffer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for ReadWriteBufferMap<'a> {
|
impl<'a> Drop for ReadWriteBufferMap<'a> {
|
||||||
|
@ -712,7 +555,7 @@ impl<'a> Drop for ReadWriteBufferMap<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo);
|
gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,7 +570,7 @@ impl ReadMappedBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_buffer(&self) -> &Buffer {
|
pub fn get_buffer(&self) -> &Buffer {
|
||||||
&self.buffer
|
self.buffer.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,9 +580,9 @@ impl Drop for ReadMappedBuffer {
|
||||||
fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo);
|
fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.buffer.raw.is_null() {
|
if !self.buffer.0.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo);
|
gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -762,7 +605,7 @@ impl ReadWriteMappedBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_buffer(&self) -> &Buffer {
|
pub fn get_buffer(&self) -> &Buffer {
|
||||||
&self.buffer
|
self.buffer.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,9 +615,9 @@ impl Drop for ReadWriteMappedBuffer {
|
||||||
fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo);
|
fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.buffer.raw.is_null() {
|
if !self.buffer.0.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo);
|
gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut GstMapInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -783,38 +626,6 @@ impl Drop for ReadWriteMappedBuffer {
|
||||||
unsafe impl Sync for ReadWriteMappedBuffer {}
|
unsafe impl Sync for ReadWriteMappedBuffer {}
|
||||||
unsafe impl Send for ReadWriteMappedBuffer {}
|
unsafe impl Send for ReadWriteMappedBuffer {}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ScopedBufferPtr(*mut c_void);
|
|
||||||
|
|
||||||
pub struct ScopedBuffer<'a> {
|
|
||||||
buffer: Buffer,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
phantom: PhantomData<&'a ScopedBufferPtr>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ScopedBuffer<'a> {
|
|
||||||
pub unsafe fn new(ptr: &'a ScopedBufferPtr) -> ScopedBuffer<'a> {
|
|
||||||
ScopedBuffer {
|
|
||||||
buffer: Buffer::new_from_ptr_scoped(ptr.0),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Deref for ScopedBuffer<'a> {
|
|
||||||
type Target = Buffer;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DerefMut for ScopedBuffer<'a> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
flags MapFlags: u32 {
|
flags MapFlags: u32 {
|
||||||
|
|
|
@ -22,28 +22,43 @@ use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use value::*;
|
use value::*;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
use miniobject::*;
|
||||||
|
|
||||||
#[derive(Eq)]
|
#[derive(Eq)]
|
||||||
pub struct Caps(*mut c_void);
|
pub struct Caps(*mut c_void);
|
||||||
|
|
||||||
|
unsafe impl MiniObject for Caps {
|
||||||
|
unsafe fn as_ptr(&self) -> *mut c_void {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) {
|
||||||
|
self.0 = ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self {
|
||||||
|
Caps(ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Caps {
|
impl Caps {
|
||||||
pub fn new_empty() -> Self {
|
pub fn new_empty() -> GstRc<Self> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_caps_new_empty() -> *mut c_void;
|
fn gst_caps_new_empty() -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
Caps(unsafe { gst_caps_new_empty() })
|
unsafe { GstRc::new_from_owned_ptr(gst_caps_new_empty()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_any() -> Self {
|
pub fn new_any() -> GstRc<Self> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_caps_new_any() -> *mut c_void;
|
fn gst_caps_new_any() -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
Caps(unsafe { gst_caps_new_any() })
|
unsafe { GstRc::new_from_owned_ptr(gst_caps_new_any()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> Self {
|
pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_caps_append_structure(caps: *mut c_void, structure: *mut c_void);
|
fn gst_caps_append_structure(caps: *mut c_void, structure: *mut c_void);
|
||||||
fn gst_structure_new_empty(name: *const c_char) -> *mut c_void;
|
fn gst_structure_new_empty(name: *const c_char) -> *mut c_void;
|
||||||
|
@ -55,35 +70,29 @@ impl Caps {
|
||||||
let structure = unsafe { gst_structure_new_empty(name_cstr.as_ptr()) };
|
let structure = unsafe { gst_structure_new_empty(name_cstr.as_ptr()) };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_caps_append_structure(caps.0, structure);
|
gst_caps_append_structure(caps.as_ptr(), structure);
|
||||||
}
|
}
|
||||||
|
|
||||||
caps.set_simple(values);
|
caps.get_mut().unwrap().set_simple(values);
|
||||||
|
|
||||||
caps
|
caps
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn new_from_ptr(ptr: *mut c_void) -> Caps {
|
pub fn from_string(value: &str) -> Option<GstRc<Self>> {
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
Caps(gst_mini_object_ref(ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_string(value: &str) -> Option<Self> {
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_caps_from_string(value: *const c_char) -> *mut c_void;
|
fn gst_caps_from_string(value: *const c_char) -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let value_cstr = CString::new(value).unwrap();
|
let value_cstr = CString::new(value).unwrap();
|
||||||
|
|
||||||
let caps_ptr = unsafe { gst_caps_from_string(value_cstr.as_ptr()) };
|
unsafe {
|
||||||
|
let caps_ptr = gst_caps_from_string(value_cstr.as_ptr());
|
||||||
|
|
||||||
if caps_ptr.is_null() {
|
if caps_ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Caps(caps_ptr))
|
Some(GstRc::new_from_owned_ptr(caps_ptr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,47 +125,6 @@ impl Caps {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const c_void {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_writable(self: Caps) -> Caps {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let raw = unsafe { gst_mini_object_make_writable(self.0) };
|
|
||||||
|
|
||||||
Caps(raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy(&self) -> Caps {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
unsafe { Caps(gst_mini_object_copy(self.0)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for Caps {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { Caps(gst_mini_object_ref(self.0)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Caps {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_unref(mini_object: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_mini_object_unref(self.0) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Caps {
|
impl fmt::Debug for Caps {
|
||||||
|
@ -175,10 +143,12 @@ impl PartialEq for Caps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for Caps {}
|
||||||
|
unsafe impl Send for Caps {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use value::*;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ use slog::*;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
use error::*;
|
use error::*;
|
||||||
use buffer::*;
|
use buffer::*;
|
||||||
|
use miniobject::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use caps::Caps;
|
use caps::Caps;
|
||||||
use plugin::Plugin;
|
use plugin::Plugin;
|
||||||
|
@ -57,7 +58,7 @@ pub enum HandleBufferResult {
|
||||||
StreamsChanged(Vec<Stream>),
|
StreamsChanged(Vec<Stream>),
|
||||||
// TODO need something to replace/add new streams
|
// TODO need something to replace/add new streams
|
||||||
// TODO should probably directly implement the GstStreams new world order
|
// TODO should probably directly implement the GstStreams new world order
|
||||||
BufferForStream(StreamIndex, Buffer),
|
BufferForStream(StreamIndex, GstRc<Buffer>),
|
||||||
Eos(Option<StreamIndex>),
|
Eos(Option<StreamIndex>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +70,9 @@ pub trait Demuxer {
|
||||||
fn stop(&mut self) -> Result<(), ErrorMessage>;
|
fn stop(&mut self) -> Result<(), ErrorMessage>;
|
||||||
|
|
||||||
fn seek(&mut self, start: u64, stop: Option<u64>) -> Result<SeekResult, ErrorMessage>;
|
fn seek(&mut self, start: u64, stop: Option<u64>) -> Result<SeekResult, ErrorMessage>;
|
||||||
fn handle_buffer(&mut self, buffer: Option<Buffer>) -> Result<HandleBufferResult, FlowError>;
|
fn handle_buffer(&mut self,
|
||||||
|
buffer: Option<GstRc<Buffer>>)
|
||||||
|
-> Result<HandleBufferResult, FlowError>;
|
||||||
fn end_of_stream(&mut self) -> Result<(), ErrorMessage>;
|
fn end_of_stream(&mut self) -> Result<(), ErrorMessage>;
|
||||||
|
|
||||||
fn is_seekable(&self) -> bool;
|
fn is_seekable(&self) -> bool;
|
||||||
|
@ -80,12 +83,12 @@ pub trait Demuxer {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Stream {
|
pub struct Stream {
|
||||||
pub index: StreamIndex,
|
pub index: StreamIndex,
|
||||||
pub caps: Caps,
|
pub caps: GstRc<Caps>,
|
||||||
pub stream_id: String,
|
pub stream_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream {
|
impl Stream {
|
||||||
pub fn new(index: StreamIndex, caps: Caps, stream_id: String) -> Stream {
|
pub fn new(index: StreamIndex, caps: GstRc<Caps>, stream_id: String) -> Stream {
|
||||||
Stream {
|
Stream {
|
||||||
index: index,
|
index: index,
|
||||||
caps: caps,
|
caps: caps,
|
||||||
|
@ -250,7 +253,7 @@ impl DemuxerWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_buffer(&self, buffer: Buffer) -> GstFlowReturn {
|
fn handle_buffer(&self, buffer: GstRc<Buffer>) -> GstFlowReturn {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32);
|
fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32);
|
||||||
fn gst_rs_demuxer_add_stream(raw: *mut c_void,
|
fn gst_rs_demuxer_add_stream(raw: *mut c_void,
|
||||||
|
@ -474,7 +477,7 @@ pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper,
|
||||||
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GstFlowReturn::Error, {
|
panic_to_error!(wrap, GstFlowReturn::Error, {
|
||||||
let buffer = Buffer::new_from_ptr_owned(buffer);
|
let buffer = GstRc::new_from_owned_ptr(buffer);
|
||||||
wrap.handle_buffer(buffer)
|
wrap.handle_buffer(buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,3 +44,4 @@ pub mod caps;
|
||||||
pub mod bytes;
|
pub mod bytes;
|
||||||
pub mod tags;
|
pub mod tags;
|
||||||
pub mod streams;
|
pub mod streams;
|
||||||
|
pub mod miniobject;
|
||||||
|
|
231
gst-plugin/src/miniobject.rs
Normal file
231
gst-plugin/src/miniobject.rs
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
// Copyright (C) 2016 Sebastian Dröge <sebastian@centricular.com>
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Library General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Library General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Library General Public
|
||||||
|
// License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
// Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
use std::os::raw::c_void;
|
||||||
|
use std::{fmt, ops, borrow, ptr};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use utils::*;
|
||||||
|
|
||||||
|
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct GstRc<T: MiniObject> {
|
||||||
|
obj: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MiniObject> GstRc<T> {
|
||||||
|
unsafe fn new(obj: T, owned: bool) -> Self {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(!obj.as_ptr().is_null());
|
||||||
|
|
||||||
|
if !owned {
|
||||||
|
gst_mini_object_ref(obj.as_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
GstRc { obj: obj }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn new_from_owned_ptr(ptr: *mut c_void) -> Self {
|
||||||
|
Self::new(T::new_from_ptr(ptr), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn new_from_unowned_ptr(ptr: *mut c_void) -> Self {
|
||||||
|
Self::new(T::new_from_ptr(ptr), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_mut(&mut self) -> &mut T {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let ptr = self.obj.as_ptr();
|
||||||
|
|
||||||
|
if self.is_writable() {
|
||||||
|
return &mut self.obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.obj.replace_ptr(gst_mini_object_make_writable(ptr));
|
||||||
|
assert!(self.is_writable());
|
||||||
|
|
||||||
|
&mut self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self) -> Option<&mut T> {
|
||||||
|
if self.is_writable() {
|
||||||
|
Some(&mut self.obj)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy(&self) -> Self {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
||||||
|
}
|
||||||
|
unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn into_ptr(mut self) -> *mut c_void {
|
||||||
|
self.obj.swap_ptr(ptr::null_mut())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MiniObject> ops::Deref for GstRc<T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MiniObject> AsRef<T> for GstRc<T> {
|
||||||
|
fn as_ref(&self) -> &T {
|
||||||
|
&self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MiniObject> borrow::Borrow<T> for GstRc<T> {
|
||||||
|
fn borrow(&self) -> &T {
|
||||||
|
&self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MiniObject> Clone for GstRc<T> {
|
||||||
|
fn clone(&self) -> GstRc<T> {
|
||||||
|
unsafe { GstRc::new_from_unowned_ptr(self.obj.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MiniObject> Drop for GstRc<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_mini_object_unref(obj: *mut c_void) -> *mut c_void;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if !self.obj.as_ptr().is_null() {
|
||||||
|
gst_mini_object_unref(self.obj.as_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: MiniObject + Sync> Sync for GstRc<T> {}
|
||||||
|
unsafe impl<T: MiniObject + Send> Send for GstRc<T> {}
|
||||||
|
|
||||||
|
impl<T: MiniObject + fmt::Display> fmt::Display for GstRc<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.obj.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Reference counting must not happen in here
|
||||||
|
pub unsafe trait MiniObject {
|
||||||
|
unsafe fn as_ptr(&self) -> *mut c_void;
|
||||||
|
unsafe fn replace_ptr(&mut self, ptr: *mut c_void);
|
||||||
|
unsafe fn swap_ptr(&mut self, new_ptr: *mut c_void) -> *mut c_void {
|
||||||
|
let ptr = self.as_ptr();
|
||||||
|
self.replace_ptr(new_ptr);
|
||||||
|
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self;
|
||||||
|
|
||||||
|
fn is_writable(&self) -> bool {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_mini_object_is_writable(obj: *mut c_void) -> GBoolean;
|
||||||
|
}
|
||||||
|
unsafe { gst_mini_object_is_writable(self.as_ptr()).to_bool() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject> From<&'a T> for GstRc<T> {
|
||||||
|
fn from(f: &'a T) -> GstRc<T> {
|
||||||
|
unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject> From<&'a mut T> for GstRc<T> {
|
||||||
|
fn from(f: &'a mut T) -> GstRc<T> {
|
||||||
|
unsafe { GstRc::new_from_unowned_ptr(f.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct GstRefPtr(*mut c_void);
|
||||||
|
|
||||||
|
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct GstRef<'a, T: MiniObject> {
|
||||||
|
obj: T,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
phantom: PhantomData<&'a GstRefPtr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject> GstRef<'a, T> {
|
||||||
|
pub unsafe fn new(ptr: &'a GstRefPtr) -> GstRef<'a, T> {
|
||||||
|
GstRef {
|
||||||
|
obj: T::new_from_ptr(ptr.0),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self) -> Option<&mut T> {
|
||||||
|
if self.is_writable() {
|
||||||
|
Some(&mut self.obj)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy(&self) -> GstRc<T> {
|
||||||
|
extern "C" {
|
||||||
|
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
||||||
|
}
|
||||||
|
unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn into_ptr(mut self) -> *mut c_void {
|
||||||
|
self.obj.swap_ptr(ptr::null_mut())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject> ops::Deref for GstRef<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject> AsRef<T> for GstRef<'a, T> {
|
||||||
|
fn as_ref(&self) -> &T {
|
||||||
|
&self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject> borrow::Borrow<T> for GstRef<'a, T> {
|
||||||
|
fn borrow(&self) -> &T {
|
||||||
|
&self.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: MiniObject + fmt::Display> fmt::Display for GstRef<'a, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.obj.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ use slog::*;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
use error::*;
|
use error::*;
|
||||||
use buffer::*;
|
use buffer::*;
|
||||||
|
use miniobject::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use plugin::Plugin;
|
use plugin::Plugin;
|
||||||
|
|
||||||
|
@ -270,13 +271,11 @@ pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> GBoolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper,
|
pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, buffer: GstRefPtr) -> GstFlowReturn {
|
||||||
buffer: ScopedBufferPtr)
|
|
||||||
-> GstFlowReturn {
|
|
||||||
let wrap: &SinkWrapper = &*ptr;
|
let wrap: &SinkWrapper = &*ptr;
|
||||||
panic_to_error!(wrap, GstFlowReturn::Error, {
|
panic_to_error!(wrap, GstFlowReturn::Error, {
|
||||||
let buffer = ScopedBuffer::new(&buffer);
|
let buffer: GstRef<Buffer> = GstRef::new(&buffer);
|
||||||
wrap.render(&*buffer)
|
wrap.render(buffer.as_ref())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ use plugin::Plugin;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
use error::*;
|
use error::*;
|
||||||
use buffer::*;
|
use buffer::*;
|
||||||
|
use miniobject::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -323,13 +324,13 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean {
|
||||||
pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
|
pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
length: u32,
|
length: u32,
|
||||||
buffer: ScopedBufferPtr)
|
buffer: GstRefPtr)
|
||||||
-> GstFlowReturn {
|
-> GstFlowReturn {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GstFlowReturn::Error, {
|
panic_to_error!(wrap, GstFlowReturn::Error, {
|
||||||
let mut buffer = ScopedBuffer::new(&buffer);
|
let mut buffer: GstRef<Buffer> = GstRef::new(&buffer);
|
||||||
wrap.fill(offset, length, &mut *buffer)
|
wrap.fill(offset, length, buffer.get_mut().unwrap())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ use std::ptr;
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use caps::Caps;
|
use caps::Caps;
|
||||||
|
use miniobject::*;
|
||||||
use tags::TagList;
|
use tags::TagList;
|
||||||
|
|
||||||
pub struct Stream(*mut c_void);
|
pub struct Stream(*mut c_void);
|
||||||
|
@ -46,7 +47,11 @@ bitflags! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream {
|
impl Stream {
|
||||||
pub fn new(stream_id: &str, caps: Option<Caps>, t: StreamType, flags: StreamFlags) -> Self {
|
pub fn new(stream_id: &str,
|
||||||
|
caps: Option<GstRc<Caps>>,
|
||||||
|
t: StreamType,
|
||||||
|
flags: StreamFlags)
|
||||||
|
-> Self {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_stream_new(stream_id: *const c_char,
|
fn gst_stream_new(stream_id: *const c_char,
|
||||||
caps: *const c_void,
|
caps: *const c_void,
|
||||||
|
@ -65,7 +70,7 @@ impl Stream {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_caps(&self) -> Option<Caps> {
|
pub fn get_caps(&self) -> Option<GstRc<Caps>> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_stream_get_caps(stream: *mut c_void) -> *mut c_void;
|
fn gst_stream_get_caps(stream: *mut c_void) -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +81,7 @@ impl Stream {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(unsafe { Caps::new_from_ptr(ptr) })
|
Some(unsafe { GstRc::new_from_owned_ptr(ptr) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_stream_flags(&self) -> StreamFlags {
|
pub fn get_stream_flags(&self) -> StreamFlags {
|
||||||
|
@ -118,7 +123,7 @@ impl Stream {
|
||||||
Some(unsafe { TagList::new_from_ptr(ptr) })
|
Some(unsafe { TagList::new_from_ptr(ptr) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_caps(&self, caps: Option<Caps>) {
|
pub fn set_caps(&self, caps: Option<GstRc<Caps>>) {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_stream_set_caps(stream: *mut c_void, caps: *mut c_void);
|
fn gst_stream_set_caps(stream: *mut c_void, caps: *mut c_void);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use libc::c_char;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use utils::*;
|
use utils::*;
|
||||||
use value::*;
|
use value::*;
|
||||||
|
use miniobject::*;
|
||||||
|
|
||||||
pub trait Tag {
|
pub trait Tag {
|
||||||
type TagType: ValueType;
|
type TagType: ValueType;
|
||||||
|
@ -65,21 +66,27 @@ pub enum MergeMode {
|
||||||
#[derive(Eq)]
|
#[derive(Eq)]
|
||||||
pub struct TagList(*mut c_void);
|
pub struct TagList(*mut c_void);
|
||||||
|
|
||||||
|
unsafe impl MiniObject for TagList {
|
||||||
|
unsafe fn as_ptr(&self) -> *mut c_void {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) {
|
||||||
|
self.0 = ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self {
|
||||||
|
TagList(ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TagList {
|
impl TagList {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> GstRc<Self> {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_tag_list_new_empty() -> *mut c_void;
|
fn gst_tag_list_new_empty() -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagList(unsafe { gst_tag_list_new_empty() })
|
unsafe { GstRc::new_from_owned_ptr(gst_tag_list_new_empty()) }
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn new_from_ptr(ptr: *mut c_void) -> TagList {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagList(gst_mini_object_ref(ptr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add<T: Tag>(&mut self, value: T::TagType, mode: MergeMode)
|
pub fn add<T: Tag>(&mut self, value: T::TagType, mode: MergeMode)
|
||||||
|
@ -104,7 +111,7 @@ impl TagList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<T: Tag>(&mut self) -> Option<TypedValue<T::TagType>>
|
pub fn get<T: Tag>(&self) -> Option<TypedValue<T::TagType>>
|
||||||
where Value: From<<T as Tag>::TagType>
|
where Value: From<<T as Tag>::TagType>
|
||||||
{
|
{
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -145,47 +152,6 @@ impl TagList {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const c_void {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_writable(self: TagList) -> TagList {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let raw = unsafe { gst_mini_object_make_writable(self.0) };
|
|
||||||
|
|
||||||
TagList(raw)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy(&self) -> TagList {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
unsafe { TagList(gst_mini_object_copy(self.0)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for TagList {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(mini_object: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { TagList(gst_mini_object_ref(self.0)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for TagList {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_unref(mini_object: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_mini_object_unref(self.0) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for TagList {
|
impl fmt::Debug for TagList {
|
||||||
|
@ -204,10 +170,12 @@ impl PartialEq for TagList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for TagList {}
|
||||||
|
unsafe impl Send for TagList {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use value::*;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
|
@ -227,8 +195,11 @@ mod tests {
|
||||||
|
|
||||||
let mut tags = TagList::new();
|
let mut tags = TagList::new();
|
||||||
assert_eq!(tags.to_string(), "taglist;");
|
assert_eq!(tags.to_string(), "taglist;");
|
||||||
tags.add::<Title>("some title".into(), MergeMode::Append);
|
{
|
||||||
tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append);
|
let tags = tags.get_mut().unwrap();
|
||||||
|
tags.add::<Title>("some title".into(), MergeMode::Append);
|
||||||
|
tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append);
|
||||||
|
}
|
||||||
assert_eq!(tags.to_string(),
|
assert_eq!(tags.to_string(),
|
||||||
"taglist, title=(string)\"some\\ title\", duration=(guint64)120000000000;");
|
"taglist, title=(string)\"some\\ title\", duration=(guint64)120000000000;");
|
||||||
}
|
}
|
||||||
|
@ -239,10 +210,14 @@ mod tests {
|
||||||
|
|
||||||
let mut tags = TagList::new();
|
let mut tags = TagList::new();
|
||||||
assert_eq!(tags.to_string(), "taglist;");
|
assert_eq!(tags.to_string(), "taglist;");
|
||||||
tags.add::<Title>("some title".into(), MergeMode::Append);
|
{
|
||||||
tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append);
|
let tags = tags.get_mut().unwrap();
|
||||||
|
tags.add::<Title>("some title".into(), MergeMode::Append);
|
||||||
|
tags.add::<Duration>((1000u64 * 1000 * 1000 * 120).into(), MergeMode::Append);
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(*tags.get::<Title>().unwrap(), "some title");
|
assert_eq!(*tags.get::<Title>().unwrap(), "some title");
|
||||||
assert_eq!(*tags.get::<Duration>().unwrap(), (1000u64 * 1000 * 1000 * 120));
|
assert_eq!(*tags.get::<Duration>().unwrap(),
|
||||||
|
(1000u64 * 1000 * 1000 * 120));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ use std::ops::Deref;
|
||||||
pub use num_rational::Rational32;
|
pub use num_rational::Rational32;
|
||||||
|
|
||||||
use buffer::*;
|
use buffer::*;
|
||||||
|
use miniobject::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
|
@ -35,7 +36,7 @@ pub enum Value {
|
||||||
UInt64(u64),
|
UInt64(u64),
|
||||||
String(String),
|
String(String),
|
||||||
Fraction(Rational32),
|
Fraction(Rational32),
|
||||||
Buffer(Buffer),
|
Buffer(GstRc<Buffer>),
|
||||||
Array(Vec<Value>),
|
Array(Vec<Value>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ impl_value_type!(i64, Int64);
|
||||||
impl_value_type!(u64, UInt64);
|
impl_value_type!(u64, UInt64);
|
||||||
impl_value_type!(String, String);
|
impl_value_type!(String, String);
|
||||||
impl_value_type!(Rational32, Fraction);
|
impl_value_type!(Rational32, Fraction);
|
||||||
impl_value_type!(Buffer, Buffer);
|
impl_value_type!(GstRc<Buffer>, Buffer);
|
||||||
impl_value_type!(Vec<Value>, Array);
|
impl_value_type!(Vec<Value>, Array);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -74,9 +75,7 @@ pub struct GValue {
|
||||||
|
|
||||||
impl GValue {
|
impl GValue {
|
||||||
pub fn new() -> GValue {
|
pub fn new() -> GValue {
|
||||||
let gvalue: GValue = unsafe { mem::zeroed() };
|
unsafe { mem::zeroed() }
|
||||||
|
|
||||||
gvalue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +233,7 @@ impl Value {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Value::Buffer(Buffer::new_from_ptr(b)))
|
Some(Value::Buffer(GstRc::new_from_unowned_ptr(b)))
|
||||||
},
|
},
|
||||||
typ if typ == *TYPE_GST_VALUE_ARRAY => unsafe {
|
typ if typ == *TYPE_GST_VALUE_ARRAY => unsafe {
|
||||||
let n = gst_value_array_get_size(gvalue as *const GValue);
|
let n = gst_value_array_get_size(gvalue as *const GValue);
|
||||||
|
@ -320,15 +319,15 @@ impl From<(i32, i32)> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Buffer> for Value {
|
impl From<GstRc<Buffer>> for Value {
|
||||||
fn from(f: Buffer) -> Value {
|
fn from(f: GstRc<Buffer>) -> Value {
|
||||||
Value::Buffer(f)
|
Value::Buffer(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Buffer> for Value {
|
impl<'a> From<&'a Buffer> for Value {
|
||||||
fn from(f: &'a Buffer) -> Value {
|
fn from(f: &'a Buffer) -> Value {
|
||||||
Value::Buffer(f.clone())
|
Value::Buffer(f.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue