gio: General clean up and simplification

The GInputStreams are now requested by a vfunc from
the subclasses instead of relying that the subclass
sets it until it's needed.

This might also fix bug #587896.
This commit is contained in:
Sebastian Dröge 2009-07-07 20:18:00 +02:00
parent da27fd57e8
commit 160b70e841
5 changed files with 66 additions and 98 deletions

View File

@ -25,6 +25,8 @@
#include "gstgiobasesrc.h" #include "gstgiobasesrc.h"
#include <gst/base/gsttypefindhelper.h>
GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug); GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug);
#define GST_CAT_DEFAULT gst_gio_base_src_debug #define GST_CAT_DEFAULT gst_gio_base_src_debug
@ -67,9 +69,7 @@ static void
gst_gio_base_src_class_init (GstGioBaseSrcClass * klass) gst_gio_base_src_class_init (GstGioBaseSrcClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class; GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class; GstBaseSrcClass *gstbasesrc_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
@ -125,16 +125,19 @@ static gboolean
gst_gio_base_src_start (GstBaseSrc * base_src) gst_gio_base_src_start (GstBaseSrc * base_src)
{ {
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
GstGioBaseSrcClass *gbsrc_class = GST_GIO_BASE_SRC_GET_CLASS (src);
if (!G_IS_INPUT_STREAM (src->stream)) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
("No stream given yet"));
return FALSE;
}
src->position = 0; src->position = 0;
GST_DEBUG_OBJECT (src, "started stream"); /* FIXME: This will likely block */
src->stream = gbsrc_class->get_stream (src);
if (G_UNLIKELY (!G_IS_INPUT_STREAM (src->stream))) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
("No input stream provided by subclass"));
return FALSE;
}
GST_DEBUG_OBJECT (src, "started source");
return TRUE; return TRUE;
} }
@ -143,9 +146,7 @@ static gboolean
gst_gio_base_src_stop (GstBaseSrc * base_src) gst_gio_base_src_stop (GstBaseSrc * base_src)
{ {
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
gboolean success; gboolean success;
GError *err = NULL; GError *err = NULL;
if (G_IS_INPUT_STREAM (src->stream)) { if (G_IS_INPUT_STREAM (src->stream)) {
@ -180,7 +181,6 @@ gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
if (G_IS_FILE_INPUT_STREAM (src->stream)) { if (G_IS_FILE_INPUT_STREAM (src->stream)) {
GFileInfo *info; GFileInfo *info;
GError *err = NULL; GError *err = NULL;
info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream), info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream),
@ -207,13 +207,9 @@ gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) { if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) {
goffset old; goffset old;
goffset stream_size; goffset stream_size;
gboolean ret; gboolean ret;
GSeekable *seekable = G_SEEKABLE (src->stream); GSeekable *seekable = G_SEEKABLE (src->stream);
GError *err = NULL; GError *err = NULL;
old = g_seekable_tell (seekable); old = g_seekable_tell (seekable);
@ -231,7 +227,6 @@ gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
} else { } else {
GST_WARNING_OBJECT (src, "Seeking to end of stream failed"); GST_WARNING_OBJECT (src, "Seeking to end of stream failed");
} }
return FALSE; return FALSE;
} }
@ -249,7 +244,6 @@ gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
} else { } else {
GST_ERROR_OBJECT (src, "Seeking to the old position faile"); GST_ERROR_OBJECT (src, "Seeking to the old position faile");
} }
return FALSE; return FALSE;
} }
@ -266,7 +260,6 @@ static gboolean
gst_gio_base_src_is_seekable (GstBaseSrc * base_src) gst_gio_base_src_is_seekable (GstBaseSrc * base_src)
{ {
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
gboolean seekable; gboolean seekable;
seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream); seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream);
@ -303,8 +296,6 @@ gst_gio_base_src_unlock_stop (GstBaseSrc * base_src)
static gboolean static gboolean
gst_gio_base_src_check_get_range (GstBaseSrc * base_src) gst_gio_base_src_check_get_range (GstBaseSrc * base_src)
{ {
/* FIXME: Implement dry-run variant using guesswork like gnomevfssrc? */
return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS, return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS,
check_get_range, (base_src), FALSE); check_get_range, (base_src), FALSE);
} }
@ -327,7 +318,6 @@ gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size,
* over DBus if our backend is GVfs and this is painfully slow. */ * over DBus if our backend is GVfs and this is painfully slow. */
if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) && if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) &&
offset + size <= GST_BUFFER_OFFSET_END (src->cache)) { offset + size <= GST_BUFFER_OFFSET_END (src->cache)) {
GST_DEBUG_OBJECT (src, "Creating subbuffer from cached buffer: offset %" GST_DEBUG_OBJECT (src, "Creating subbuffer from cached buffer: offset %"
G_GUINT64_FORMAT " length %u", offset, size); G_GUINT64_FORMAT " length %u", offset, size);
@ -339,11 +329,8 @@ gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size,
GST_BUFFER_SIZE (buf) = size; GST_BUFFER_SIZE (buf) = size;
} else { } else {
guint cachesize = MAX (4096, size); guint cachesize = MAX (4096, size);
gssize read, res; gssize read, res;
gboolean success, eos; gboolean success, eos;
GError *err = NULL; GError *err = NULL;
if (src->cache) { if (src->cache) {
@ -452,39 +439,3 @@ gst_gio_base_src_query (GstBaseSrc * base_src, GstQuery * query)
return ret; return ret;
} }
void
gst_gio_base_src_set_stream (GstGioBaseSrc * src, GInputStream * stream)
{
gboolean success;
GError *err = NULL;
g_return_if_fail (G_IS_INPUT_STREAM (stream));
g_return_if_fail ((GST_STATE (src) != GST_STATE_PLAYING &&
GST_STATE (src) != GST_STATE_PAUSED));
if (G_IS_INPUT_STREAM (src->stream)) {
GST_DEBUG_OBJECT (src, "closing old stream");
/* FIXME: can block but unfortunately we can't use async operations
* here because they require a running main loop */
success = g_input_stream_close (src->stream, src->cancel, &err);
if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
("g_input_stream_close failed: %s", err->message));
g_clear_error (&err);
} else if (!success) {
GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
("g_input_stream_close failed"));
} else {
GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
}
g_object_unref (src->stream);
src->stream = NULL;
}
src->stream = stream;
}

View File

@ -32,6 +32,8 @@ G_BEGIN_DECLS
(gst_gio_base_src_get_type()) (gst_gio_base_src_get_type())
#define GST_GIO_BASE_SRC(obj) \ #define GST_GIO_BASE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrc)) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrc))
#define GST_GIO_BASE_SRC_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GIO_BASE_SRC, GstGioBaseSrcClass))
#define GST_GIO_BASE_SRC_CLASS(klass) \ #define GST_GIO_BASE_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass)) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass))
#define GST_IS_GIO_BASE_SRC(obj) \ #define GST_IS_GIO_BASE_SRC(obj) \
@ -56,12 +58,12 @@ struct _GstGioBaseSrc
struct _GstGioBaseSrcClass struct _GstGioBaseSrcClass
{ {
GstBaseSrcClass parent_class; GstBaseSrcClass parent_class;
GInputStream * (*get_stream) (GstGioBaseSrc *bsrc);
}; };
GType gst_gio_base_src_get_type (void); GType gst_gio_base_src_get_type (void);
void gst_gio_base_src_set_stream (GstGioBaseSrc *src, GInputStream *stream);
G_END_DECLS G_END_DECLS
#endif /* __GST_GIO_BASE_SRC_H__ */ #endif /* __GST_GIO_BASE_SRC_H__ */

View File

@ -81,7 +81,7 @@ static void gst_gio_src_set_property (GObject * object, guint prop_id,
static void gst_gio_src_get_property (GObject * object, guint prop_id, static void gst_gio_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static gboolean gst_gio_src_start (GstBaseSrc * base_src); static GInputStream *gst_gio_src_get_stream (GstGioBaseSrc * bsrc);
static gboolean gst_gio_src_check_get_range (GstBaseSrc * base_src); static gboolean gst_gio_src_check_get_range (GstBaseSrc * base_src);
@ -103,14 +103,12 @@ static void
gst_gio_src_class_init (GstGioSrcClass * klass) gst_gio_src_class_init (GstGioSrcClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class; GstBaseSrcClass *gstbasesrc_class;
GstGioBaseSrcClass *gstgiobasesrc_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class = (GstBaseSrcClass *) klass;
gstgiobasesrc_class = (GstGioBaseSrcClass *) klass;
gobject_class->finalize = gst_gio_src_finalize; gobject_class->finalize = gst_gio_src_finalize;
gobject_class->set_property = gst_gio_src_set_property; gobject_class->set_property = gst_gio_src_set_property;
@ -131,9 +129,10 @@ gst_gio_src_class_init (GstGioSrcClass * klass)
g_param_spec_object ("file", "File", "GFile to read from", g_param_spec_object ("file", "File", "GFile to read from",
G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_src_start);
gstbasesrc_class->check_get_range = gstbasesrc_class->check_get_range =
GST_DEBUG_FUNCPTR (gst_gio_src_check_get_range); GST_DEBUG_FUNCPTR (gst_gio_src_check_get_range);
gstgiobasesrc_class->get_stream = GST_DEBUG_FUNCPTR (gst_gio_src_get_stream);
} }
static void static void
@ -279,23 +278,19 @@ done:
} }
static gboolean static GInputStream *
gst_gio_src_start (GstBaseSrc * base_src) gst_gio_src_get_stream (GstGioBaseSrc * bsrc)
{ {
GstGioSrc *src = GST_GIO_SRC (base_src); GstGioSrc *src = GST_GIO_SRC (bsrc);
GError *err = NULL; GError *err = NULL;
GInputStream *stream; GInputStream *stream;
GCancellable *cancel = bsrc->cancel;
GCancellable *cancel = GST_GIO_BASE_SRC (src)->cancel;
gchar *uri = NULL; gchar *uri = NULL;
if (src->file == NULL) { if (src->file == NULL) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
("No location or GFile given")); ("No location or GFile given"));
return FALSE; return NULL;
} }
uri = g_file_get_uri (src->file); uri = g_file_get_uri (src->file);
@ -315,16 +310,14 @@ gst_gio_src_start (GstBaseSrc * base_src)
g_free (uri); g_free (uri);
g_clear_error (&err); g_clear_error (&err);
return FALSE; return NULL;
} else if (stream == NULL) { } else if (stream == NULL) {
g_free (uri); g_free (uri);
return FALSE; return NULL;
} }
gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src), stream);
GST_DEBUG_OBJECT (src, "opened location %s", uri); GST_DEBUG_OBJECT (src, "opened location %s", uri);
g_free (uri); g_free (uri);
return GST_BASE_SRC_CLASS (parent_class)->start (base_src); return stream;
} }

View File

@ -73,8 +73,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_src_debug);
enum enum
{ {
ARG_0, PROP_0,
ARG_STREAM PROP_STREAM
}; };
GST_BOILERPLATE (GstGioStreamSrc, gst_gio_stream_src, GstGioBaseSrc, GST_BOILERPLATE (GstGioStreamSrc, gst_gio_stream_src, GstGioBaseSrc,
@ -85,6 +85,7 @@ static void gst_gio_stream_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gio_stream_src_get_property (GObject * object, guint prop_id, static void gst_gio_stream_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static GInputStream *gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc);
static void static void
gst_gio_stream_src_base_init (gpointer gclass) gst_gio_stream_src_base_init (gpointer gclass)
@ -107,20 +108,21 @@ static void
gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass) gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class; GstGioBaseSrcClass *gstgiobasesrc_class;
GstBaseSrcClass *gstbasesrc_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass; gstgiobasesrc_class = (GstGioBaseSrcClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
gobject_class->finalize = gst_gio_stream_src_finalize; gobject_class->finalize = gst_gio_stream_src_finalize;
gobject_class->set_property = gst_gio_stream_src_set_property; gobject_class->set_property = gst_gio_stream_src_set_property;
gobject_class->get_property = gst_gio_stream_src_get_property; gobject_class->get_property = gst_gio_stream_src_get_property;
g_object_class_install_property (gobject_class, ARG_STREAM, g_object_class_install_property (gobject_class, PROP_STREAM,
g_param_spec_object ("stream", "Stream", "Stream to read from", g_param_spec_object ("stream", "Stream", "Stream to read from",
G_TYPE_INPUT_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_TYPE_INPUT_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstgiobasesrc_class->get_stream =
GST_DEBUG_FUNCPTR (gst_gio_stream_src_get_stream);
} }
static void static void
@ -131,6 +133,13 @@ gst_gio_stream_src_init (GstGioStreamSrc * src, GstGioStreamSrcClass * gclass)
static void static void
gst_gio_stream_src_finalize (GObject * object) gst_gio_stream_src_finalize (GObject * object)
{ {
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
if (src->stream) {
g_object_unref (src->stream);
src->stream = NULL;
}
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
} }
@ -141,18 +150,20 @@ gst_gio_stream_src_set_property (GObject * object, guint prop_id,
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object); GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
switch (prop_id) { switch (prop_id) {
case ARG_STREAM:{ case PROP_STREAM:{
GObject *stream; GObject *stream;
if (GST_STATE (src) == GST_STATE_PLAYING || if (GST_STATE (src) == GST_STATE_PLAYING ||
GST_STATE (src) == GST_STATE_PAUSED) GST_STATE (src) == GST_STATE_PAUSED) {
GST_WARNING
("Setting a new stream not supported in PLAYING or PAUSED state");
break; break;
}
stream = g_value_dup_object (value); stream = g_value_dup_object (value);
if (G_IS_INPUT_STREAM (stream)) if (src->stream)
gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src), g_object_unref (src->stream);
G_INPUT_STREAM (stream)); src->stream = G_INPUT_STREAM (stream);
break; break;
} }
default: default:
@ -168,11 +179,19 @@ gst_gio_stream_src_get_property (GObject * object, guint prop_id,
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object); GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
switch (prop_id) { switch (prop_id) {
case ARG_STREAM: case PROP_STREAM:
g_value_set_object (value, GST_GIO_BASE_SRC (src)->stream); g_value_set_object (value, src->stream);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static GInputStream *
gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc)
{
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (bsrc);
return (src->stream) ? g_object_ref (src->stream) : NULL;
}

View File

@ -51,6 +51,9 @@ typedef struct _GstGioStreamSrcClass GstGioStreamSrcClass;
struct _GstGioStreamSrc struct _GstGioStreamSrc
{ {
GstGioBaseSrc src; GstGioBaseSrc src;
/* < private > */
GInputStream *stream;
}; };
struct _GstGioStreamSrcClass struct _GstGioStreamSrcClass