diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 08175f7697..d21e7c6504 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -296,6 +296,8 @@ static gboolean gst_base_src_default_do_seek (GstBaseSrc * src, static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query); static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event, GstSegment * segment); +static GstFlowReturn gst_base_src_default_create (GstBaseSrc * basesrc, + guint64 offset, guint size, GstBuffer ** buf); static gboolean gst_base_src_set_flushing (GstBaseSrc * basesrc, gboolean flushing, gboolean live_play, gboolean unlock, gboolean * playing); @@ -334,10 +336,9 @@ gst_base_src_class_init (GstBaseSrcClass * klass) gobject_class->set_property = gst_base_src_set_property; gobject_class->get_property = gst_base_src_get_property; -/* FIXME 0.11: blocksize property should be int, not ulong (min is >max here) */ g_object_class_install_property (gobject_class, PROP_BLOCKSIZE, - g_param_spec_ulong ("blocksize", "Block size", - "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG, + g_param_spec_uint ("blocksize", "Block size", + "Size in bytes to read per buffer (-1 = default)", 0, G_MAXUINT, DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, g_param_spec_int ("num-buffers", "num-buffers", @@ -365,6 +366,7 @@ gst_base_src_class_init (GstBaseSrcClass * klass) klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query); klass->prepare_seek_segment = GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment); + klass->create = GST_DEBUG_FUNCPTR (gst_base_src_default_create); /* Registering debug symbols for function pointers */ GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_push); @@ -643,9 +645,8 @@ gst_base_src_query_latency (GstBaseSrc * src, gboolean * live, * * Since: 0.10.22 */ -/* FIXME 0.11: blocksize property should be int, not ulong */ void -gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize) +gst_base_src_set_blocksize (GstBaseSrc * src, guint blocksize) { g_return_if_fail (GST_IS_BASE_SRC (src)); @@ -664,11 +665,10 @@ gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize) * * Since: 0.10.22 */ -/* FIXME 0.11: blocksize property should be int, not ulong */ -gulong +guint gst_base_src_get_blocksize (GstBaseSrc * src) { - gulong res; + gint res; g_return_val_if_fail (GST_IS_BASE_SRC (src), 0); @@ -1246,6 +1246,55 @@ gst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event, return result; } +static GstFlowReturn +gst_base_src_default_create (GstBaseSrc * src, guint64 offset, + guint size, GstBuffer ** buffer) +{ + GstBaseSrcClass *bclass; + GstFlowReturn ret; + GstBuffer *buf; + + bclass = GST_BASE_SRC_GET_CLASS (src); + + if (G_UNLIKELY (!bclass->fill)) + goto no_function; + + buf = gst_buffer_new_and_alloc (size); + if (G_UNLIKELY (buf == NULL)) + goto alloc_failed; + + if (G_LIKELY (size > 0)) { + /* only call fill when there is a size */ + ret = bclass->fill (src, offset, size, buf); + + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto not_ok; + } + + *buffer = buf; + + return GST_FLOW_OK; + + /* ERRORS */ +no_function: + { + GST_DEBUG_OBJECT (src, "no fill function"); + return GST_FLOW_NOT_SUPPORTED; + } +alloc_failed: + { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size); + return GST_FLOW_ERROR; + } +not_ok: + { + GST_DEBUG_OBJECT (src, "fill returned %d (%s)", ret, + gst_flow_get_name (ret)); + gst_buffer_unref (buf); + return ret; + } +} + /* this code implements the seeking. It is a good example * handling all cases. * @@ -1770,7 +1819,7 @@ gst_base_src_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_BLOCKSIZE: - gst_base_src_set_blocksize (src, g_value_get_ulong (value)); + gst_base_src_set_blocksize (src, g_value_get_uint (value)); break; case PROP_NUM_BUFFERS: src->num_buffers = g_value_get_int (value); @@ -1797,7 +1846,7 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value, switch (prop_id) { case PROP_BLOCKSIZE: - g_value_set_ulong (value, gst_base_src_get_blocksize (src)); + g_value_set_uint (value, gst_base_src_get_blocksize (src)); break; case PROP_NUM_BUFFERS: g_value_set_int (value, src->num_buffers); @@ -2211,7 +2260,7 @@ not_started: no_function: { GST_DEBUG_OBJECT (src, "no create function"); - return GST_FLOW_ERROR; + return GST_FLOW_NOT_SUPPORTED; } unexpected_length: { @@ -2290,7 +2339,7 @@ gst_base_src_loop (GstPad * pad) GstFlowReturn ret; gint64 position; gboolean eos; - gulong blocksize; + guint blocksize; GList *pending_events = NULL, *tmp; gboolean reconfigure; @@ -2333,7 +2382,7 @@ gst_base_src_loop (GstPad * pad) } else position = -1; - GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %lu", + GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %u", GST_TIME_ARGS (position), blocksize); ret = gst_base_src_get_range (src, position, blocksize, &buf); diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h index d4bbd67824..c44b38ba57 100644 --- a/libs/gst/base/gstbasesrc.h +++ b/libs/gst/base/gstbasesrc.h @@ -81,7 +81,7 @@ struct _GstBaseSrc { gboolean live_running; /* MT-protected (with LOCK) */ - gint blocksize; /* size of buffers when operating push based */ + guint blocksize; /* size of buffers when operating push based */ gboolean can_activate_push; /* some scheduling properties */ GstActivateMode pad_mode; gboolean seekable; /* not used anymore */ @@ -117,6 +117,8 @@ struct _GstBaseSrc { * @get_caps: Called to get the caps to report * @set_caps: Notify subclass of changed output caps * @negotiate: Negotiated the caps with the peer. + * @fixate: Called during negotiation if caps need fixating. Implement instead of + * setting a fixate function on the source pad. * @start: Start processing. Subclasses should open resources and prepare * to produce data. * @stop: Stop processing. Subclasses should use this to close resources. @@ -125,6 +127,13 @@ struct _GstBaseSrc { * these times. * @get_size: Return the total size of the resource, in the configured format. * @is_seekable: Check if the source can seek + * @prepare_seek_segment: Prepare the GstSegment that will be passed to the + * do_seek vmethod for executing a seek request. Sub-classes should override + * this if they support seeking in formats other than the configured native + * format. By default, it tries to convert the seek arguments to the + * configured native format and prepare a segment in that format. + * Since: 0.10.13 + * @do_seek: Perform seeking on the resource to the indicated segment. * @unlock: Unlock any pending access to the resource. Subclasses should * unblock any blocked function ASAP. In particular, any create() function in * progress should be unblocked and should return GST_FLOW_WRONG_STATE. Any @@ -132,23 +141,17 @@ struct _GstBaseSrc { * until the @unlock_stop() function has been called. * @unlock_stop: Clear the previous unlock request. Subclasses should clear * any state they set during unlock(), such as clearing command queues. + * @query: Handle a requested query. * @event: Override this to implement custom event handling. * @create: Ask the subclass to create a buffer with offset and size. * When the subclass returns GST_FLOW_OK, it MUST return a buffer of the * requested size unless fewer bytes are available because an EOS condition * is near. No buffer should be returned when the return value is different * from GST_FLOW_OK. A return value of GST_FLOW_UNEXPECTED signifies that the - * end of stream is reached. - * @do_seek: Perform seeking on the resource to the indicated segment. - * @prepare_seek_segment: Prepare the GstSegment that will be passed to the - * do_seek vmethod for executing a seek request. Sub-classes should override - * this if they support seeking in formats other than the configured native - * format. By default, it tries to convert the seek arguments to the - * configured native format and prepare a segment in that format. - * Since: 0.10.13 - * @query: Handle a requested query. - * @fixate: Called during negotiation if caps need fixating. Implement instead of - * setting a fixate function on the source pad. + * end of stream is reached. The default implementation will create a new + * buffer from the negotiated allocator and will call @fill. + * @fill: Ask the subclass to fill the buffer with data for offset and size. The + * passed buffer is guaranteed to hold the requested amount of bytes. * * Subclasses can override any of the available virtual methods or not, as * needed. At the minimum, the @create method should be overridden to produce @@ -204,9 +207,13 @@ struct _GstBaseSrcClass { /* notify subclasses of an event */ gboolean (*event) (GstBaseSrc *src, GstEvent *event); - /* ask the subclass to create a buffer with offset and size */ + /* ask the subclass to create a buffer with offset and size, the default + * implementation will use the negotiated allocator and call fill. */ GstFlowReturn (*create) (GstBaseSrc *src, guint64 offset, guint size, GstBuffer **buf); + /* ask the subclass to fill the buffer with data from offset and size */ + GstFlowReturn (*fill) (GstBaseSrc *src, guint64 offset, guint size, + GstBuffer *buf); /*< private >*/ gpointer _gst_reserved[GST_PADDING_LARGE]; @@ -227,8 +234,8 @@ gboolean gst_base_src_query_latency (GstBaseSrc *src, gboolean * live, GstClockTime * min_latency, GstClockTime * max_latency); -void gst_base_src_set_blocksize (GstBaseSrc *src, gulong blocksize); -gulong gst_base_src_get_blocksize (GstBaseSrc *src); +void gst_base_src_set_blocksize (GstBaseSrc *src, guint blocksize); +guint gst_base_src_get_blocksize (GstBaseSrc *src); void gst_base_src_set_do_timestamp (GstBaseSrc *src, gboolean timestamp); gboolean gst_base_src_get_do_timestamp (GstBaseSrc *src); diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index b005392c4e..bed3590ad8 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -146,8 +146,8 @@ static gboolean gst_file_src_stop (GstBaseSrc * basesrc); static gboolean gst_file_src_is_seekable (GstBaseSrc * src); static gboolean gst_file_src_get_size (GstBaseSrc * src, guint64 * size); -static GstFlowReturn gst_file_src_create (GstBaseSrc * src, guint64 offset, - guint length, GstBuffer ** buffer); +static GstFlowReturn gst_file_src_fill (GstBaseSrc * src, guint64 offset, + guint length, GstBuffer * buf); static gboolean gst_file_src_query (GstBaseSrc * src, GstQuery * query); static void gst_file_src_uri_handler_init (gpointer g_iface, @@ -197,7 +197,7 @@ gst_file_src_class_init (GstFileSrcClass * klass) gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_file_src_stop); gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable); gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size); - gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_file_src_create); + gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_file_src_fill); gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_file_src_query); if (sizeof (off_t) < 8) { @@ -325,13 +325,14 @@ gst_file_src_get_property (GObject * object, guint prop_id, GValue * value, * */ static GstFlowReturn -gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length, - GstBuffer ** buffer) +gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length, + GstBuffer * buf) { + GstFileSrc *src; int ret; - GstBuffer *buf; guint8 *data; - gsize size; + + src = GST_FILE_SRC_CAST (basesrc); if (G_UNLIKELY (src->read_position != offset)) { off_t res; @@ -343,39 +344,31 @@ gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length, src->read_position = offset; } - buf = gst_buffer_new_and_alloc (length); - if (G_UNLIKELY (buf == NULL && length > 0)) - goto alloc_failed; + data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); - /* No need to read anything if length is 0 */ - if (length > 0) { - data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE); + GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x", + length, offset); - GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x", - length, offset); - ret = read (src->fd, data, length); - if (G_UNLIKELY (ret < 0)) - goto could_not_read; + ret = read (src->fd, data, length); + if (G_UNLIKELY (ret < 0)) + goto could_not_read; - /* seekable regular files should have given us what we expected */ - if (G_UNLIKELY ((guint) ret < length && src->seekable)) - goto unexpected_eos; + /* seekable regular files should have given us what we expected */ + if (G_UNLIKELY ((guint) ret < length && src->seekable)) + goto unexpected_eos; - /* other files should eos if they read 0 and more was requested */ - if (G_UNLIKELY (ret == 0 && length > 0)) - goto eos; + /* other files should eos if they read 0 and more was requested */ + if (G_UNLIKELY (ret == 0)) + goto eos; - length = ret; + length = ret; - gst_buffer_unmap (buf, data, length); + gst_buffer_unmap (buf, data, length); - GST_BUFFER_OFFSET (buf) = offset; - GST_BUFFER_OFFSET_END (buf) = offset + length; + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + length; - src->read_position += length; - } - - *buffer = buf; + src->read_position += length; return GST_FLOW_OK; @@ -385,16 +378,10 @@ seek_failed: GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); return GST_FLOW_ERROR; } -alloc_failed: - { - GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length); - return GST_FLOW_ERROR; - } could_not_read: { GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); gst_buffer_unmap (buf, data, 0); - gst_buffer_unref (buf); return GST_FLOW_ERROR; } unexpected_eos: @@ -402,32 +389,16 @@ unexpected_eos: GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("unexpected end of file.")); gst_buffer_unmap (buf, data, 0); - gst_buffer_unref (buf); return GST_FLOW_ERROR; } eos: { GST_DEBUG ("non-regular file hits EOS"); gst_buffer_unmap (buf, data, 0); - gst_buffer_unref (buf); return GST_FLOW_UNEXPECTED; } } -static GstFlowReturn -gst_file_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, - GstBuffer ** buffer) -{ - GstFileSrc *src; - GstFlowReturn ret; - - src = GST_FILE_SRC_CAST (basesrc); - - ret = gst_file_src_create_read (src, offset, length, buffer); - - return ret; -} - static gboolean gst_file_src_query (GstBaseSrc * basesrc, GstQuery * query) {