From 5b6a05b5486fb4ee908e778fe7c0b281c13c665e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 14 May 2016 11:31:13 +0300 Subject: [PATCH] Implement some error handling and seek support This now works as a proper replacement of filesrc. --- src/rsfilesrc.c | 4 +-- src/rsfilesrc.rs | 68 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/rsfilesrc.c b/src/rsfilesrc.c index 1e1bf0fe..26be9b1f 100644 --- a/src/rsfilesrc.c +++ b/src/rsfilesrc.c @@ -6,7 +6,7 @@ /* Declarations for Rust code */ extern void * filesrc_new (void); extern void filesrc_drop (void * filesrc); -extern GstFlowReturn filesrc_fill (void * filesrc, void * data, size_t * data_len); +extern GstFlowReturn filesrc_fill (void * filesrc, uint64_t offset, void * data, size_t * data_len); extern void filesrc_set_location (void * filesrc, const char *location); extern char * filesrc_get_location (void * filesrc); extern uint64_t filesrc_get_size (void * filesrc); @@ -149,7 +149,7 @@ gst_rsfile_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, gst_buffer_map (buf, &map, GST_MAP_READWRITE); size = map.size; - ret = filesrc_fill (src->instance, map.data, &size); + ret = filesrc_fill (src->instance, offset, map.data, &size); gst_buffer_unmap (buf, &map); if (ret == GST_FLOW_OK) gst_buffer_resize (buf, 0, size); diff --git a/src/rsfilesrc.rs b/src/rsfilesrc.rs index 4d618019..a922b177 100644 --- a/src/rsfilesrc.rs +++ b/src/rsfilesrc.rs @@ -3,10 +3,19 @@ use std::ffi::{CStr, CString}; use std::ptr; use std::u64; use std::slice; -use std::io::Read; +use std::io::{Read, Seek, SeekFrom}; use std::fs::File; use std::path::Path; +use std::io::Write; + +macro_rules! println_err( + ($($arg:tt)*) => { { + let r = writeln!(&mut ::std::io::stderr(), $($arg)*); + r.expect("failed printing to stderr"); + } } +); + #[repr(C)] pub enum GstFlowReturn { Ok = 0, @@ -36,11 +45,12 @@ impl GBoolean { pub struct FileSrc { location: Option, file: Option, + position: u64, } impl FileSrc { fn new() -> FileSrc { - FileSrc { location: None, file: None } + FileSrc { location: None, file: None, position: 0 } } fn set_location(&mut self, location: &Option) { @@ -59,31 +69,65 @@ impl FileSrc { match self.file { None => return u64::MAX, Some(ref f) => { - return f.metadata().unwrap().len(); + return f.metadata().map(|m| m.len()).unwrap_or(u64::MAX); }, } } fn start(&mut self) -> bool { - if self.location.is_none() { return false; } + self.file = None; + self.position = 0; - self.file = Some(File::open(Path::new(&self.location.clone().unwrap())).unwrap()); - - return true; + match self.location { + None => return false, + Some(ref location) => { + match File::open(Path::new(&location.clone())) { + Ok(file) => { + self.file = Some(file); + return true; + }, + Err(err) => { + println_err!("Failed to open file '{}': {}", location, err.to_string()); + return false; + }, + } + }, + } } fn stop(&mut self) -> bool { self.file = None; + self.position = 0; true } - fn fill(&mut self, data: &mut [u8]) -> Result { + fn fill(&mut self, offset: u64, data: &mut [u8]) -> Result { match self.file { None => return Err(GstFlowReturn::Error), Some(ref mut f) => { - // FIXME: Need to return the actual size, handle EOF, etc - return Ok(f.read(data).unwrap()); + if self.position != offset { + match f.seek(SeekFrom::Start(offset)) { + Ok(_) => { + self.position = offset; + }, + Err(err) => { + println_err!("Failed to seek to {}: {}", offset, err.to_string()); + return Err(GstFlowReturn::Error); + } + } + } + + match f.read(data) { + Ok(size) => { + self.position += size as u64; + return Ok(size) + }, + Err(err) => { + println_err!("Failed to read at {}: {}", offset, err.to_string()); + return Err(GstFlowReturn::Error); + }, + } }, } } @@ -125,12 +169,12 @@ pub extern "C" fn filesrc_get_location(ptr: *mut FileSrc) -> *mut c_char { } #[no_mangle] -pub extern "C" fn filesrc_fill(ptr: *mut FileSrc, data_ptr: *mut u8, data_len_ptr: *mut usize) -> GstFlowReturn { +pub extern "C" fn filesrc_fill(ptr: *mut FileSrc, offset: u64, data_ptr: *mut u8, data_len_ptr: *mut usize) -> GstFlowReturn { let filesrc: &mut FileSrc = unsafe { &mut *ptr }; let mut data_len: &mut usize = unsafe { &mut *data_len_ptr }; let mut data = unsafe { slice::from_raw_parts_mut(data_ptr, *data_len) }; - match filesrc.fill(data) { + match filesrc.fill(offset, data) { Ok(actual_len) => { *data_len = actual_len; GstFlowReturn::Ok