mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-09-27 14:30:27 +00:00
Add wrapper around GstBuffer and use it in the source/sink
This commit is contained in:
parent
a2ff32d0be
commit
61b5420102
11 changed files with 604 additions and 49 deletions
470
src/buffer.rs
Normal file
470
src/buffer.rs
Normal file
|
@ -0,0 +1,470 @@
|
|||
// 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::ptr;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::slice;
|
||||
use std::marker::PhantomData;
|
||||
use std::u64;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fmt::Error as FmtError;
|
||||
use std::error::Error;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use utils::*;
|
||||
|
||||
pub struct Buffer {
|
||||
raw: *mut c_void,
|
||||
owned: bool,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct GstMapInfo {
|
||||
memory: *mut c_void,
|
||||
flags: i32,
|
||||
data: *mut c_void,
|
||||
size: usize,
|
||||
maxsize: usize,
|
||||
user_data: [*mut c_void; 4],
|
||||
_gst_reserved: [*const c_void; 4],
|
||||
}
|
||||
|
||||
pub struct ReadBufferMap<'a> {
|
||||
buffer: &'a Buffer,
|
||||
map_info: GstMapInfo,
|
||||
}
|
||||
|
||||
pub struct ReadWriteBufferMap<'a> {
|
||||
buffer: &'a Buffer,
|
||||
map_info: GstMapInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BufferError {
|
||||
NotWritable,
|
||||
NotEnoughSpace,
|
||||
}
|
||||
|
||||
impl Display for BufferError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
f.write_str(self.description())
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for BufferError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
BufferError::NotWritable => "Not Writable",
|
||||
BufferError::NotEnoughSpace => "Not Enough Space",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub unsafe fn new_from_ptr(raw: *mut c_void) -> 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_with_size(size: usize) -> Option<Buffer> {
|
||||
extern "C" {
|
||||
fn gst_buffer_new_allocate(allocator: *const c_void,
|
||||
size: usize,
|
||||
params: *const c_void)
|
||||
-> *mut c_void;
|
||||
}
|
||||
|
||||
let raw = unsafe { gst_buffer_new_allocate(ptr::null(), size, ptr::null()) };
|
||||
if raw.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Buffer {
|
||||
raw: raw,
|
||||
owned: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_read(&self) -> Option<ReadBufferMap> {
|
||||
extern "C" {
|
||||
fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, flags: i32) -> GBoolean;
|
||||
}
|
||||
|
||||
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
||||
let res = unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, 1) };
|
||||
if res.to_bool() {
|
||||
Some(ReadBufferMap {
|
||||
buffer: self,
|
||||
map_info: map_info,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_readwrite(&mut self) -> Option<ReadWriteBufferMap> {
|
||||
extern "C" {
|
||||
fn gst_buffer_map(buffer: *mut c_void, map: *mut GstMapInfo, flags: i32) -> GBoolean;
|
||||
}
|
||||
|
||||
let mut map_info: GstMapInfo = unsafe { mem::zeroed() };
|
||||
let res = unsafe { gst_buffer_map(self.raw, &mut map_info as *mut GstMapInfo, 3) };
|
||||
if res.to_bool() {
|
||||
Some(ReadWriteBufferMap {
|
||||
buffer: self,
|
||||
map_info: map_info,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_writable(&self) -> bool {
|
||||
extern "C" {
|
||||
fn gst_mini_object_is_writable(obj: *const c_void) -> GBoolean;
|
||||
}
|
||||
|
||||
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 share(&self) -> Buffer {
|
||||
unsafe { Buffer::new_from_ptr(self.raw) }
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> usize {
|
||||
extern "C" {
|
||||
fn gst_buffer_get_size(obj: *const c_void) -> usize;
|
||||
}
|
||||
|
||||
unsafe { gst_buffer_get_size(self.raw) }
|
||||
}
|
||||
|
||||
pub fn get_maxsize(&self) -> usize {
|
||||
extern "C" {
|
||||
fn gst_buffer_get_sizes_range(obj: *const c_void,
|
||||
idx: u32,
|
||||
length: i32,
|
||||
offset: *mut usize,
|
||||
maxsize: *mut usize)
|
||||
-> usize;
|
||||
}
|
||||
|
||||
let mut maxsize: usize = 0;
|
||||
|
||||
unsafe {
|
||||
gst_buffer_get_sizes_range(self.raw,
|
||||
0,
|
||||
-1,
|
||||
ptr::null_mut(),
|
||||
&mut maxsize as *mut usize);
|
||||
};
|
||||
|
||||
maxsize
|
||||
}
|
||||
|
||||
pub fn set_size(&mut self, size: usize) -> Result<(), BufferError> {
|
||||
extern "C" {
|
||||
fn gst_buffer_set_size(obj: *const c_void, size: usize);
|
||||
}
|
||||
|
||||
if !self.is_writable() {
|
||||
return Err(BufferError::NotWritable);
|
||||
}
|
||||
|
||||
if self.get_maxsize() < size {
|
||||
return Err(BufferError::NotEnoughSpace);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gst_buffer_set_size(self.raw, size);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_offset(&self) -> Option<u64> {
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_get_offset(buf: *const c_void) -> u64;
|
||||
}
|
||||
|
||||
let offset = unsafe { gst_rs_buffer_get_offset(self.raw) };
|
||||
|
||||
if offset == u64::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(offset)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_offset(&mut self, offset: Option<u64>) -> Result<(), BufferError> {
|
||||
if !self.is_writable() {
|
||||
return Err(BufferError::NotWritable);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_set_offset(buf: *const c_void, offset: u64);
|
||||
}
|
||||
|
||||
let offset = match offset {
|
||||
None => u64::MAX,
|
||||
Some(offset) => offset,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
gst_rs_buffer_set_offset(self.raw, offset);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_offset_end(&self) -> Option<u64> {
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_get_offset_end(buf: *const c_void) -> u64;
|
||||
}
|
||||
|
||||
let offset_end = unsafe { gst_rs_buffer_get_offset_end(self.raw) };
|
||||
|
||||
if offset_end == u64::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(offset_end)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_offset_end(&mut self, offset_end: Option<u64>) -> Result<(), BufferError> {
|
||||
if !self.is_writable() {
|
||||
return Err(BufferError::NotWritable);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_set_offset_end(buf: *const c_void, offset_end: u64);
|
||||
}
|
||||
|
||||
let offset_end = match offset_end {
|
||||
None => u64::MAX,
|
||||
Some(offset_end) => offset_end,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
gst_rs_buffer_set_offset_end(self.raw, offset_end);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_pts(&self) -> Option<u64> {
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_get_pts(buf: *const c_void) -> u64;
|
||||
}
|
||||
|
||||
let pts = unsafe { gst_rs_buffer_get_pts(self.raw) };
|
||||
|
||||
if pts == u64::MAX { None } else { Some(pts) }
|
||||
}
|
||||
|
||||
pub fn set_pts(&mut self, pts: Option<u64>) -> Result<(), BufferError> {
|
||||
if !self.is_writable() {
|
||||
return Err(BufferError::NotWritable);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_set_pts(buf: *const c_void, pts: u64);
|
||||
}
|
||||
|
||||
let pts = match pts {
|
||||
None => u64::MAX,
|
||||
Some(pts) => pts,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
gst_rs_buffer_set_pts(self.raw, pts);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_dts(&self) -> Option<u64> {
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_get_dts(buf: *const c_void) -> u64;
|
||||
}
|
||||
|
||||
let dts = unsafe { gst_rs_buffer_get_dts(self.raw) };
|
||||
|
||||
if dts == u64::MAX { None } else { Some(dts) }
|
||||
}
|
||||
|
||||
pub fn set_dts(&mut self, dts: Option<u64>) -> Result<(), BufferError> {
|
||||
if !self.is_writable() {
|
||||
return Err(BufferError::NotWritable);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn gst_rs_buffer_set_dts(buf: *const c_void, dts: u64);
|
||||
}
|
||||
|
||||
let dts = match dts {
|
||||
None => u64::MAX,
|
||||
Some(dts) => dts,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
gst_rs_buffer_set_dts(self.raw, dts);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Buffer {
|
||||
fn drop(&mut self) {
|
||||
extern "C" {
|
||||
fn gst_mini_object_unref(obj: *mut c_void);
|
||||
}
|
||||
|
||||
if self.owned {
|
||||
unsafe { gst_mini_object_unref(self.raw) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Buffer {
|
||||
fn clone(&self) -> Buffer {
|
||||
extern "C" {
|
||||
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
||||
}
|
||||
|
||||
let raw = unsafe { gst_mini_object_copy(self.raw) };
|
||||
|
||||
Buffer {
|
||||
raw: raw,
|
||||
owned: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ReadBufferMap<'a> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for ReadBufferMap<'a> {
|
||||
fn drop(&mut self) {
|
||||
extern "C" {
|
||||
fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo);
|
||||
};
|
||||
|
||||
unsafe {
|
||||
gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ReadWriteBufferMap<'a> {
|
||||
pub fn as_mut_slice(&self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.map_info.data as *mut u8, self.map_info.size) }
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.map_info.data as *const u8, self.map_info.size) }
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> usize {
|
||||
self.map_info.size
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for ReadWriteBufferMap<'a> {
|
||||
fn drop(&mut self) {
|
||||
extern "C" {
|
||||
fn gst_buffer_unmap(buffer: *mut c_void, map: *mut GstMapInfo);
|
||||
};
|
||||
|
||||
unsafe {
|
||||
gst_buffer_unmap(self.buffer.raw, &mut self.map_info as *mut GstMapInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScopedBuffer<'a> {
|
||||
buffer: Buffer,
|
||||
phantom: PhantomData<&'a c_void>,
|
||||
}
|
||||
|
||||
impl<'a> ScopedBuffer<'a> {
|
||||
pub unsafe fn new(ptr: *mut c_void) -> ScopedBuffer<'a> {
|
||||
ScopedBuffer {
|
||||
buffer: Buffer::new_from_ptr_scoped(ptr),
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ extern crate hyper;
|
|||
pub mod utils;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
pub mod buffer;
|
||||
pub mod rssource;
|
||||
pub mod rssink;
|
||||
pub mod rsfilesrc;
|
||||
|
|
48
src/plugin.c
48
src/plugin.c
|
@ -52,3 +52,51 @@ gst_rs_element_error (GstElement * element, GQuark error_domain,
|
|||
gst_element_message_full (element, GST_MESSAGE_ERROR, error_domain,
|
||||
error_code, g_strdup (message), g_strdup (debug), file, function, line);
|
||||
}
|
||||
|
||||
guint64
|
||||
gst_rs_buffer_get_pts (GstBuffer * buffer)
|
||||
{
|
||||
return GST_BUFFER_PTS (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
gst_rs_buffer_set_pts (GstBuffer * buffer, guint64 pts)
|
||||
{
|
||||
GST_BUFFER_PTS (buffer) = pts;
|
||||
}
|
||||
|
||||
guint64
|
||||
gst_rs_buffer_get_dts (GstBuffer * buffer)
|
||||
{
|
||||
return GST_BUFFER_DTS (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
gst_rs_buffer_set_dts (GstBuffer * buffer, guint64 dts)
|
||||
{
|
||||
GST_BUFFER_DTS (buffer) = dts;
|
||||
}
|
||||
|
||||
guint64
|
||||
gst_rs_buffer_get_offset (GstBuffer * buffer)
|
||||
{
|
||||
return GST_BUFFER_OFFSET (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
gst_rs_buffer_set_offset (GstBuffer * buffer, guint64 offset)
|
||||
{
|
||||
GST_BUFFER_OFFSET (buffer) = offset;
|
||||
}
|
||||
|
||||
guint64
|
||||
gst_rs_buffer_get_offset_end (GstBuffer * buffer)
|
||||
{
|
||||
return GST_BUFFER_OFFSET_END (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
gst_rs_buffer_set_offset_end (GstBuffer * buffer, guint64 offset_end)
|
||||
{
|
||||
GST_BUFFER_OFFSET_END (buffer) = offset_end;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ use std::convert::From;
|
|||
|
||||
use error::*;
|
||||
use rssink::*;
|
||||
use buffer::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum StreamingState {
|
||||
|
@ -93,7 +94,7 @@ impl Sink for FileSink {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn render(&mut self, data: &[u8]) -> Result<(), FlowError> {
|
||||
fn render(&mut self, buffer: &Buffer) -> Result<(), FlowError> {
|
||||
let (file, position) = match self.streaming_state {
|
||||
StreamingState::Started { ref mut file, ref mut position } => (file, position),
|
||||
StreamingState::Stopped => {
|
||||
|
@ -101,6 +102,15 @@ impl Sink for FileSink {
|
|||
}
|
||||
};
|
||||
|
||||
let map = match buffer.map_read() {
|
||||
None => {
|
||||
return Err(FlowError::Error(error_msg!(SinkError::Failure,
|
||||
["Failed to map buffer"])));
|
||||
}
|
||||
Some(map) => map,
|
||||
};
|
||||
let data = map.as_slice();
|
||||
|
||||
try!(file.write_all(data).or_else(|err| {
|
||||
Err(FlowError::Error(error_msg!(SinkError::WriteFailed, ["Failed to write: {}", err])))
|
||||
}));
|
||||
|
|
|
@ -22,6 +22,7 @@ use url::Url;
|
|||
|
||||
use error::*;
|
||||
use rssource::*;
|
||||
use buffer::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum StreamingState {
|
||||
|
@ -104,7 +105,7 @@ impl Source for FileSrc {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result<usize, FlowError> {
|
||||
fn fill(&mut self, offset: u64, _: u32, buffer: &mut Buffer) -> Result<(), FlowError> {
|
||||
let (file, position) = match self.streaming_state {
|
||||
StreamingState::Started { ref mut file, ref mut position } => (file, position),
|
||||
StreamingState::Stopped => {
|
||||
|
@ -122,14 +123,33 @@ impl Source for FileSrc {
|
|||
*position = offset;
|
||||
}
|
||||
|
||||
let size = try!(file.read(data).or_else(|err| {
|
||||
let size = {
|
||||
let map = match buffer.map_readwrite() {
|
||||
None => {
|
||||
return Err(FlowError::Error(error_msg!(SourceError::Failure,
|
||||
["Failed to map buffer"])));
|
||||
}
|
||||
Some(map) => map,
|
||||
};
|
||||
|
||||
let data = map.as_mut_slice();
|
||||
|
||||
try!(file.read(data).or_else(|err| {
|
||||
Err(FlowError::Error(error_msg!(SourceError::ReadFailed,
|
||||
["Failed to read at {}: {}", offset, err.to_string()])))
|
||||
}));
|
||||
["Failed to read at {}: {}",
|
||||
offset,
|
||||
err.to_string()])))
|
||||
}))
|
||||
};
|
||||
|
||||
*position += size as u64;
|
||||
|
||||
Ok(size)
|
||||
if let Err(err) = buffer.set_size(size) {
|
||||
return Err(FlowError::Error(error_msg!(SourceError::Failure,
|
||||
["Failed to resize buffer: {}", err])));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn seek(&mut self, _: u64, _: Option<u64>) -> Result<(), ErrorMessage> {
|
||||
|
|
|
@ -25,6 +25,7 @@ use hyper::client::response::Response;
|
|||
|
||||
use error::*;
|
||||
use rssource::*;
|
||||
use buffer::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum StreamingState {
|
||||
|
@ -186,7 +187,7 @@ impl Source for HttpSrc {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result<usize, FlowError> {
|
||||
fn fill(&mut self, offset: u64, _: u32, buffer: &mut Buffer) -> Result<(), FlowError> {
|
||||
let (response, position) = match self.streaming_state {
|
||||
StreamingState::Started { ref mut response, ref mut position, .. } => {
|
||||
(response, position)
|
||||
|
@ -203,10 +204,24 @@ impl Source for HttpSrc {
|
|||
position])));
|
||||
}
|
||||
|
||||
let size = try!(response.read(data).or_else(|err| {
|
||||
let size = {
|
||||
let map = match buffer.map_readwrite() {
|
||||
None => {
|
||||
return Err(FlowError::Error(error_msg!(SourceError::Failure,
|
||||
["Failed to map buffer"])));
|
||||
}
|
||||
Some(map) => map,
|
||||
};
|
||||
|
||||
let data = map.as_mut_slice();
|
||||
|
||||
try!(response.read(data).or_else(|err| {
|
||||
Err(FlowError::Error(error_msg!(SourceError::ReadFailed,
|
||||
["Failed to read at {}: {}", offset, err.to_string()])))
|
||||
}));
|
||||
["Failed to read at {}: {}",
|
||||
offset,
|
||||
err.to_string()])))
|
||||
}))
|
||||
};
|
||||
|
||||
if size == 0 {
|
||||
return Err(FlowError::Eos);
|
||||
|
@ -214,6 +229,12 @@ impl Source for HttpSrc {
|
|||
|
||||
*position += size as u64;
|
||||
|
||||
Ok(size)
|
||||
if let Err(err) = buffer.set_size(size) {
|
||||
return Err(FlowError::Error(error_msg!(SourceError::Failure,
|
||||
["Failed to resize buffer: {}", err])));
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ static GHashTable *sinks;
|
|||
/* Declarations for Rust code */
|
||||
extern gboolean sinks_register (void *plugin);
|
||||
extern void *sink_new (GstRsSink * sink, void *create_instance);
|
||||
extern GstFlowReturn sink_render (void *rssink, void *data, size_t data_len);
|
||||
extern GstFlowReturn sink_render (void *rssink, GstBuffer * buffer);
|
||||
extern gboolean sink_set_uri (void *rssink, const char *uri, GError ** err);
|
||||
extern char *sink_get_uri (void *rssink);
|
||||
extern gboolean sink_start (void *rssink);
|
||||
|
@ -172,12 +172,9 @@ static GstFlowReturn
|
|||
gst_rs_sink_render (GstBaseSink * basesink, GstBuffer * buffer)
|
||||
{
|
||||
GstRsSink *sink = GST_RS_SINK (basesink);
|
||||
GstMapInfo map;
|
||||
GstFlowReturn ret;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
ret = sink_render (sink->instance, map.data, map.size);
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
ret = sink_render (sink->instance, buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
use libc::c_char;
|
||||
use std::os::raw::c_void;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::slice;
|
||||
use std::ptr;
|
||||
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
|
@ -31,6 +30,7 @@ use url::Url;
|
|||
|
||||
use utils::*;
|
||||
use error::*;
|
||||
use buffer::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SinkError {
|
||||
|
@ -67,7 +67,7 @@ pub trait Sink {
|
|||
fn start(&mut self, uri: Url) -> Result<(), ErrorMessage>;
|
||||
fn stop(&mut self) -> Result<(), ErrorMessage>;
|
||||
|
||||
fn render(&mut self, data: &[u8]) -> Result<(), FlowError>;
|
||||
fn render(&mut self, buffer: &Buffer) -> Result<(), FlowError>;
|
||||
}
|
||||
|
||||
impl SinkWrapper {
|
||||
|
@ -205,15 +205,14 @@ pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> GBoolean {
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper,
|
||||
data_ptr: *const u8,
|
||||
data_len: usize)
|
||||
buffer: *mut c_void)
|
||||
-> GstFlowReturn {
|
||||
let wrap: &SinkWrapper = &*ptr;
|
||||
panic_to_error!(wrap, GstFlowReturn::Error, {
|
||||
let sink = &mut wrap.sink.lock().unwrap();
|
||||
let data = slice::from_raw_parts(data_ptr, data_len);
|
||||
let buffer = ScopedBuffer::new(buffer);
|
||||
|
||||
match sink.render(data) {
|
||||
match sink.render(&buffer) {
|
||||
Ok(..) => GstFlowReturn::Ok,
|
||||
Err(flow_error) => {
|
||||
match flow_error {
|
||||
|
|
|
@ -36,8 +36,8 @@ static GHashTable *sources;
|
|||
extern gboolean sources_register (void *plugin);
|
||||
extern void *source_new (GstRsSrc * source, void *create_instance);
|
||||
extern void source_drop (void *rssource);
|
||||
extern GstFlowReturn source_fill (void *rssource,
|
||||
uint64_t offset, void *data, size_t * data_len);
|
||||
extern GstFlowReturn source_fill (void *rssource, guint64 offset, guint size,
|
||||
GstBuffer * buffer);
|
||||
extern gboolean source_seek (void *rssource, uint64_t start, uint64_t stop);
|
||||
extern gboolean source_set_uri (void *rssource, const char *uri, GError ** err);
|
||||
extern char *source_get_uri (void *rssource);
|
||||
|
@ -182,19 +182,8 @@ gst_rs_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
|
|||
GstBuffer * buf)
|
||||
{
|
||||
GstRsSrc *src = GST_RS_SRC (basesrc);
|
||||
GstMapInfo map;
|
||||
GstFlowReturn ret;
|
||||
gsize map_size, size;
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READWRITE);
|
||||
size = length;
|
||||
map_size = map.size;
|
||||
ret = source_fill (src->instance, offset, map.data, &size);
|
||||
gst_buffer_unmap (buf, &map);
|
||||
if (ret == GST_FLOW_OK && size != map_size)
|
||||
gst_buffer_resize (buf, 0, size);
|
||||
|
||||
return ret;
|
||||
return source_fill (src->instance, offset, length, buf);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
use libc::c_char;
|
||||
use std::os::raw::c_void;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::slice;
|
||||
use std::ptr;
|
||||
use std::u64;
|
||||
|
||||
|
@ -31,6 +30,7 @@ use url::Url;
|
|||
|
||||
use utils::*;
|
||||
use error::*;
|
||||
use buffer::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SourceError {
|
||||
|
@ -69,7 +69,7 @@ pub trait Source {
|
|||
|
||||
fn start(&mut self, uri: Url) -> Result<(), ErrorMessage>;
|
||||
fn stop(&mut self) -> Result<(), ErrorMessage>;
|
||||
fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result<usize, FlowError>;
|
||||
fn fill(&mut self, offset: u64, length: u32, buffer: &mut Buffer) -> Result<(), FlowError>;
|
||||
fn seek(&mut self, start: u64, stop: Option<u64>) -> Result<(), ErrorMessage>;
|
||||
}
|
||||
|
||||
|
@ -234,21 +234,17 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean {
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
|
||||
offset: u64,
|
||||
data_ptr: *mut u8,
|
||||
data_len_ptr: *mut usize)
|
||||
length: u32,
|
||||
buffer: *mut c_void)
|
||||
-> GstFlowReturn {
|
||||
let wrap: &SourceWrapper = &*ptr;
|
||||
|
||||
panic_to_error!(wrap, GstFlowReturn::Error, {
|
||||
let source = &mut wrap.source.lock().unwrap();
|
||||
let mut data_len: &mut usize = &mut *data_len_ptr;
|
||||
let mut data = slice::from_raw_parts_mut(data_ptr, *data_len);
|
||||
let mut buffer = ScopedBuffer::new(buffer);
|
||||
|
||||
match source.fill(offset, data) {
|
||||
Ok(actual_len) => {
|
||||
*data_len = actual_len;
|
||||
GstFlowReturn::Ok
|
||||
}
|
||||
match source.fill(offset, length, &mut buffer) {
|
||||
Ok(()) => GstFlowReturn::Ok,
|
||||
Err(flow_error) => {
|
||||
match flow_error {
|
||||
FlowError::NotNegotiated(ref msg) |
|
||||
|
|
|
@ -41,6 +41,10 @@ impl GBoolean {
|
|||
pub fn from_bool(v: bool) -> GBoolean {
|
||||
if v { GBoolean::True } else { GBoolean::False }
|
||||
}
|
||||
|
||||
pub fn to_bool(&self) -> bool {
|
||||
!(*self == GBoolean::False)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
Loading…
Reference in a new issue