mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-09-02 09:43:48 +00:00
Implement GstURIHandler interface and handle short reads
This commit is contained in:
parent
924b105147
commit
98c015281e
3 changed files with 116 additions and 17 deletions
|
@ -6,7 +6,7 @@
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
if (!gst_element_register (plugin, "rsfilesrc", GST_RANK_NONE,
|
if (!gst_element_register (plugin, "rsfilesrc", GST_RANK_PRIMARY+100,
|
||||||
GST_TYPE_RSFILE_SRC)) {
|
GST_TYPE_RSFILE_SRC)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
104
src/rsfilesrc.c
104
src/rsfilesrc.c
|
@ -1,11 +1,12 @@
|
||||||
#include "rsfilesrc.h"
|
#include "rsfilesrc.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Declarations for Rust code */
|
/* Declarations for Rust code */
|
||||||
extern void * filesrc_new (void);
|
extern void * filesrc_new (void);
|
||||||
extern void filesrc_drop (void * filesrc);
|
extern void filesrc_drop (void * filesrc);
|
||||||
extern GstFlowReturn filesrc_fill (void * filesrc, void * data, size_t data_len);
|
extern GstFlowReturn filesrc_fill (void * filesrc, void * data, size_t * data_len);
|
||||||
extern void filesrc_set_location (void * filesrc, const char *location);
|
extern void filesrc_set_location (void * filesrc, const char *location);
|
||||||
extern char * filesrc_get_location (void * filesrc);
|
extern char * filesrc_get_location (void * filesrc);
|
||||||
extern uint64_t filesrc_get_size (void * filesrc);
|
extern uint64_t filesrc_get_size (void * filesrc);
|
||||||
|
@ -27,6 +28,9 @@ enum
|
||||||
PROP_LOCATION
|
PROP_LOCATION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void gst_rsfile_src_uri_handler_init (gpointer g_iface,
|
||||||
|
gpointer iface_data);
|
||||||
|
|
||||||
static void gst_rsfile_src_finalize (GObject * object);
|
static void gst_rsfile_src_finalize (GObject * object);
|
||||||
|
|
||||||
static void gst_rsfile_src_set_property (GObject * object, guint prop_id,
|
static void gst_rsfile_src_set_property (GObject * object, guint prop_id,
|
||||||
|
@ -43,6 +47,7 @@ static GstFlowReturn gst_rsfile_src_fill (GstBaseSrc * src, guint64 offset,
|
||||||
guint length, GstBuffer * buf);
|
guint length, GstBuffer * buf);
|
||||||
|
|
||||||
#define _do_init \
|
#define _do_init \
|
||||||
|
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_rsfile_src_uri_handler_init); \
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_rsfile_src_debug, "rsfilesrc", 0, "rsfilesrc element");
|
GST_DEBUG_CATEGORY_INIT (gst_rsfile_src_debug, "rsfilesrc", 0, "rsfilesrc element");
|
||||||
#define gst_rsfile_src_parent_class parent_class
|
#define gst_rsfile_src_parent_class parent_class
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstRsfileSrc, gst_rsfile_src, GST_TYPE_BASE_SRC, _do_init);
|
G_DEFINE_TYPE_WITH_CODE (GstRsfileSrc, gst_rsfile_src, GST_TYPE_BASE_SRC, _do_init);
|
||||||
|
@ -140,10 +145,14 @@ gst_rsfile_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
|
||||||
GstRsfileSrc *src = GST_RSFILE_SRC (basesrc);
|
GstRsfileSrc *src = GST_RSFILE_SRC (basesrc);
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
gst_buffer_map (buf, &map, GST_MAP_READWRITE);
|
gst_buffer_map (buf, &map, GST_MAP_READWRITE);
|
||||||
ret = filesrc_fill (src->instance, map.data, map.size);
|
size = map.size;
|
||||||
|
ret = filesrc_fill (src->instance, map.data, &size);
|
||||||
gst_buffer_unmap (buf, &map);
|
gst_buffer_unmap (buf, &map);
|
||||||
|
if (ret == GST_FLOW_OK)
|
||||||
|
gst_buffer_resize (buf, 0, size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -184,4 +193,95 @@ gst_rsfile_src_stop (GstBaseSrc * basesrc)
|
||||||
return filesrc_stop (src->instance);
|
return filesrc_stop (src->instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstURIType
|
||||||
|
gst_rsfile_src_uri_get_type (GType type)
|
||||||
|
{
|
||||||
|
return GST_URI_SRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *const *
|
||||||
|
gst_rsfile_src_uri_get_protocols (GType type)
|
||||||
|
{
|
||||||
|
static const gchar *protocols[] = { "file", NULL };
|
||||||
|
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
gst_rsfile_src_uri_get_uri (GstURIHandler * handler)
|
||||||
|
{
|
||||||
|
GstRsfileSrc *src = GST_RSFILE_SRC (handler);
|
||||||
|
gchar *location, *uri;
|
||||||
|
|
||||||
|
location = filesrc_get_location (src->instance);
|
||||||
|
if (!location)
|
||||||
|
return NULL;
|
||||||
|
uri = gst_filename_to_uri (location, NULL);
|
||||||
|
g_free (location);
|
||||||
|
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_rsfile_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
|
||||||
|
GError ** err)
|
||||||
|
{
|
||||||
|
gchar *location, *hostname = NULL;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
GstRsfileSrc *src = GST_RSFILE_SRC (handler);
|
||||||
|
|
||||||
|
if (strcmp (uri, "file://") == 0) {
|
||||||
|
/* Special case for "file://" as this is used by some applications
|
||||||
|
* to test with gst_element_make_from_uri if there's an element
|
||||||
|
* that supports the URI protocol. */
|
||||||
|
filesrc_set_location (src->instance, location);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = g_filename_from_uri (uri, &hostname, err);
|
||||||
|
|
||||||
|
if (!location || (err != NULL && *err != NULL)) {
|
||||||
|
GST_WARNING_OBJECT (src, "Invalid URI '%s' for filesrc: %s", uri,
|
||||||
|
(err != NULL && *err != NULL) ? (*err)->message : "unknown error");
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hostname) && (strcmp (hostname, "localhost"))) {
|
||||||
|
/* Only 'localhost' is permitted */
|
||||||
|
GST_WARNING_OBJECT (src, "Invalid hostname '%s' for filesrc", hostname);
|
||||||
|
g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
|
||||||
|
"File URI with invalid hostname '%s'", hostname);
|
||||||
|
goto beach;
|
||||||
|
}
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
/* Unfortunately, g_filename_from_uri() doesn't handle some UNC paths
|
||||||
|
* correctly on windows, it leaves them with an extra backslash
|
||||||
|
* at the start if they're of the mozilla-style file://///host/path/file
|
||||||
|
* form. Correct this.
|
||||||
|
*/
|
||||||
|
if (location[0] == '\\' && location[1] == '\\' && location[2] == '\\')
|
||||||
|
memmove (location, location + 1, strlen (location + 1) + 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
filesrc_set_location (src->instance, location);
|
||||||
|
|
||||||
|
beach:
|
||||||
|
if (location)
|
||||||
|
g_free (location);
|
||||||
|
if (hostname)
|
||||||
|
g_free (hostname);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rsfile_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
|
||||||
|
{
|
||||||
|
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
|
||||||
|
|
||||||
|
iface->get_type = gst_rsfile_src_uri_get_type;
|
||||||
|
iface->get_protocols = gst_rsfile_src_uri_get_protocols;
|
||||||
|
iface->get_uri = gst_rsfile_src_uri_get_uri;
|
||||||
|
iface->set_uri = gst_rsfile_src_uri_set_uri;
|
||||||
|
}
|
||||||
|
|
|
@ -78,24 +78,17 @@ impl FileSrc {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill(&mut self, data: &mut [u8]) -> GstFlowReturn {
|
fn fill(&mut self, data: &mut [u8]) -> Result<usize, GstFlowReturn> {
|
||||||
match self.file {
|
match self.file {
|
||||||
None => return GstFlowReturn::Error,
|
None => return Err(GstFlowReturn::Error),
|
||||||
Some(ref mut f) => {
|
Some(ref mut f) => {
|
||||||
// FIXME: Need to return the actual size, handle EOF, etc
|
// FIXME: Need to return the actual size, handle EOF, etc
|
||||||
f.read(data);
|
return Ok(f.read(data).unwrap());
|
||||||
return GstFlowReturn::Ok;
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for FileSrc {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
println!("drop");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn filesrc_new() -> *mut FileSrc {
|
pub extern "C" fn filesrc_new() -> *mut FileSrc {
|
||||||
let instance = Box::new(FileSrc::new());
|
let instance = Box::new(FileSrc::new());
|
||||||
|
@ -132,12 +125,18 @@ pub extern "C" fn filesrc_get_location(ptr: *mut FileSrc) -> *mut c_char {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn filesrc_fill(ptr: *mut FileSrc, data_ptr: *mut u8, data_len: usize) -> GstFlowReturn {
|
pub extern "C" fn filesrc_fill(ptr: *mut FileSrc, data_ptr: *mut u8, data_len_ptr: *mut usize) -> GstFlowReturn {
|
||||||
let filesrc: &mut FileSrc = unsafe { &mut *ptr };
|
let filesrc: &mut FileSrc = unsafe { &mut *ptr };
|
||||||
|
|
||||||
println!("{:?}", filesrc);
|
let mut data_len: &mut usize = unsafe { &mut *data_len_ptr };
|
||||||
let mut data = unsafe { slice::from_raw_parts_mut(data_ptr, data_len) };
|
let mut data = unsafe { slice::from_raw_parts_mut(data_ptr, *data_len) };
|
||||||
return filesrc.fill(data);
|
match filesrc.fill(data) {
|
||||||
|
Ok(actual_len) => {
|
||||||
|
*data_len = actual_len;
|
||||||
|
GstFlowReturn::Ok
|
||||||
|
},
|
||||||
|
Err(ret) => ret,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Reference in a new issue