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 <gst/base/gsttypefindhelper.h>
GST_DEBUG_CATEGORY_STATIC (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)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
gobject_class = (GObjectClass *) klass;
@ -125,16 +125,19 @@ static gboolean
gst_gio_base_src_start (GstBaseSrc * base_src)
{
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
if (!G_IS_INPUT_STREAM (src->stream)) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
("No stream given yet"));
return FALSE;
}
GstGioBaseSrcClass *gbsrc_class = GST_GIO_BASE_SRC_GET_CLASS (src);
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;
}
@ -143,9 +146,7 @@ static gboolean
gst_gio_base_src_stop (GstBaseSrc * base_src)
{
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
gboolean success;
GError *err = NULL;
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)) {
GFileInfo *info;
GError *err = NULL;
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)) {
goffset old;
goffset stream_size;
gboolean ret;
GSeekable *seekable = G_SEEKABLE (src->stream);
GError *err = NULL;
old = g_seekable_tell (seekable);
@ -231,7 +227,6 @@ gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
} else {
GST_WARNING_OBJECT (src, "Seeking to end of stream failed");
}
return FALSE;
}
@ -249,7 +244,6 @@ gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
} else {
GST_ERROR_OBJECT (src, "Seeking to the old position faile");
}
return FALSE;
}
@ -266,7 +260,6 @@ static gboolean
gst_gio_base_src_is_seekable (GstBaseSrc * base_src)
{
GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
gboolean seekable;
seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream);
@ -303,8 +296,6 @@ gst_gio_base_src_unlock_stop (GstBaseSrc * base_src)
static gboolean
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,
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. */
if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) &&
offset + size <= GST_BUFFER_OFFSET_END (src->cache)) {
GST_DEBUG_OBJECT (src, "Creating subbuffer from cached buffer: offset %"
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;
} else {
guint cachesize = MAX (4096, size);
gssize read, res;
gboolean success, eos;
GError *err = NULL;
if (src->cache) {
@ -452,39 +439,3 @@ gst_gio_base_src_query (GstBaseSrc * base_src, GstQuery * query)
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())
#define GST_GIO_BASE_SRC(obj) \
(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) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass))
#define GST_IS_GIO_BASE_SRC(obj) \
@ -56,12 +58,12 @@ struct _GstGioBaseSrc
struct _GstGioBaseSrcClass
{
GstBaseSrcClass parent_class;
GInputStream * (*get_stream) (GstGioBaseSrc *bsrc);
};
GType gst_gio_base_src_get_type (void);
void gst_gio_base_src_set_stream (GstGioBaseSrc *src, GInputStream *stream);
G_END_DECLS
#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,
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);
@ -103,14 +103,12 @@ static void
gst_gio_src_class_init (GstGioSrcClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
GstGioBaseSrcClass *gstgiobasesrc_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
gstgiobasesrc_class = (GstGioBaseSrcClass *) klass;
gobject_class->finalize = gst_gio_src_finalize;
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_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_src_start);
gstbasesrc_class->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
@ -279,23 +278,19 @@ done:
}
static gboolean
gst_gio_src_start (GstBaseSrc * base_src)
static GInputStream *
gst_gio_src_get_stream (GstGioBaseSrc * bsrc)
{
GstGioSrc *src = GST_GIO_SRC (base_src);
GstGioSrc *src = GST_GIO_SRC (bsrc);
GError *err = NULL;
GInputStream *stream;
GCancellable *cancel = GST_GIO_BASE_SRC (src)->cancel;
GCancellable *cancel = bsrc->cancel;
gchar *uri = NULL;
if (src->file == NULL) {
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
("No location or GFile given"));
return FALSE;
return NULL;
}
uri = g_file_get_uri (src->file);
@ -315,16 +310,14 @@ gst_gio_src_start (GstBaseSrc * base_src)
g_free (uri);
g_clear_error (&err);
return FALSE;
return NULL;
} else if (stream == NULL) {
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);
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
{
ARG_0,
ARG_STREAM
PROP_0,
PROP_STREAM
};
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);
static void gst_gio_stream_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GInputStream *gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc);
static void
gst_gio_stream_src_base_init (gpointer gclass)
@ -107,20 +108,21 @@ static void
gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
GstGioBaseSrcClass *gstgiobasesrc_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
gstgiobasesrc_class = (GstGioBaseSrcClass *) klass;
gobject_class->finalize = gst_gio_stream_src_finalize;
gobject_class->set_property = gst_gio_stream_src_set_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_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
@ -131,6 +133,13 @@ gst_gio_stream_src_init (GstGioStreamSrc * src, GstGioStreamSrcClass * gclass)
static void
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));
}
@ -141,18 +150,20 @@ gst_gio_stream_src_set_property (GObject * object, guint prop_id,
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
switch (prop_id) {
case ARG_STREAM:{
case PROP_STREAM:{
GObject *stream;
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;
}
stream = g_value_dup_object (value);
if (G_IS_INPUT_STREAM (stream))
gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src),
G_INPUT_STREAM (stream));
if (src->stream)
g_object_unref (src->stream);
src->stream = G_INPUT_STREAM (stream);
break;
}
default:
@ -168,11 +179,19 @@ gst_gio_stream_src_get_property (GObject * object, guint prop_id,
GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
switch (prop_id) {
case ARG_STREAM:
g_value_set_object (value, GST_GIO_BASE_SRC (src)->stream);
case PROP_STREAM:
g_value_set_object (value, src->stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
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
{
GstGioBaseSrc src;
/* < private > */
GInputStream *stream;
};
struct _GstGioStreamSrcClass