Merge branch 'master' into 0.11

Conflicts:
	gst/gstminiobject.c
	gst/gstpad.c
	gst/gstpad.h
	gst/gstplugin.h
	libs/gst/base/gstbaseparse.c
This commit is contained in:
Wim Taymans 2011-05-18 13:14:57 +02:00
commit e39182a085
12 changed files with 135 additions and 56 deletions

2
common

@ -1 +1 @@
Subproject commit 46dfcea233cf6df83e3771d8a8066e87d614f893
Subproject commit fd3507359e845119d199b348c7779b987cee1c45

View file

@ -242,5 +242,10 @@ extern GstDebugCategory *_priv_GST_CAT_POLL;
#endif
#ifdef GST_DISABLE_DEPRECATED
typedef GList* (*GstPadIntLinkFunction) (GstPad *pad);
#endif
G_END_DECLS
#endif /* __GST_PRIVATE_H__ */

View file

@ -1144,7 +1144,7 @@ had_right_state:
* take an indeterminate amount of time.
* You can pass NULL as the callback to make this call block. Be careful with
* this blocking call as it might not return for reasons stated above.
*
*
* <note>
* Pad block handlers are only called for source pads in push mode
* and sink pads in pull mode.
@ -1988,7 +1988,7 @@ no_format:
* @sinkpad: the sink #GstPad.
*
* Checks if the source pad and the sink pad are compatible so they can be
* linked.
* linked.
*
* Returns: TRUE if the pads can be linked.
*/

View file

@ -157,7 +157,7 @@ GQuark gst_flow_to_quark (GstFlowReturn ret);
* @GST_PAD_LINK_CHECK_NOTHING: Don't check hierarchy or caps compatibility.
* @GST_PAD_LINK_CHECK_HIERARCHY: Check the pads have same parents/grandparents.
* Could be omitted if it is already known that the two elements that own the
* pads are in the same bin.
* pads are in the same bin.
* @GST_PAD_LINK_CHECK_TEMPLATE_CAPS: Check if the pads are compatible by using
* their template caps. This is much faster than @GST_PAD_LINK_CHECK_CAPS, but
* would be unsafe e.g. if one pad has %GST_CAPS_ANY.
@ -188,7 +188,7 @@ typedef enum {
/**
* GST_PAD_LINK_CHECK_DEFAULT:
*
* The default checks done when linking pads (i.e. the ones used by
* The default checks done when linking pads (i.e. the ones used by
* gst_pad_link()).
*
* Since: 0.10.30

View file

@ -65,7 +65,6 @@ gst_plugin_feature_finalize (GObject * object)
GST_DEBUG ("finalizing feature %p: '%s'", feature,
GST_PLUGIN_FEATURE_NAME (feature));
g_free (feature->name);
if (feature->plugin != NULL) {
g_object_remove_weak_pointer ((GObject *) feature->plugin,
@ -85,7 +84,7 @@ gst_plugin_feature_finalize (GObject * object)
* Normally this function is used like this:
* |[
* GstPluginFeature *loaded_feature;
*
*
* loaded_feature = gst_plugin_feature_load (feature);
* // presumably, we're no longer interested in the potentially-unloaded feature
* gst_object_unref (feature);
@ -184,12 +183,12 @@ gst_plugin_feature_set_name (GstPluginFeature * feature, const gchar * name)
g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature));
g_return_if_fail (name != NULL);
if (feature->name) {
if (G_UNLIKELY (feature->name)) {
g_return_if_fail (strcmp (feature->name, name) == 0);
} else {
feature->name = g_strdup (name);
gst_object_set_name (GST_OBJECT (feature), name);
feature->name = GST_OBJECT_NAME (GST_OBJECT (feature));
}
gst_object_set_name (GST_OBJECT_CAST (feature), feature->name);
}
/**

View file

@ -81,7 +81,7 @@ struct _GstPluginFeature {
/*< private >*/
gboolean loaded;
gchar *name;
gchar *name; /* FIXME-0.11: remove variable, we use GstObject:name */
guint rank;
const gchar *plugin_name;

View file

@ -46,7 +46,7 @@
* means of doing so is to load every plugin and look at the resulting
* information that is gathered in the default registry. Clearly, this is a time
* consuming process, so we cache information in the registry file. The format
* and location of the cache file is internal to gstreamer.
* and location of the cache file is internal to gstreamer.
*
* On startup, plugins are searched for in the plugin search path. The following
* locations are checked in this order:
@ -280,7 +280,7 @@ gst_registry_finalize (GObject * object)
if (feature) {
GST_LOG_OBJECT (registry, "removing feature %p (%s)",
feature, gst_plugin_feature_get_name (feature));
gst_object_unref (feature);
gst_object_unparent (GST_OBJECT_CAST (feature));
}
f = g_list_next (f);
}
@ -485,7 +485,7 @@ gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry,
registry->features = g_list_delete_link (registry->features, f);
g_hash_table_remove (registry->feature_hash, feature->name);
gst_object_unref (feature);
gst_object_unparent (GST_OBJECT_CAST (feature));
}
f = next;
}
@ -561,10 +561,10 @@ gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
if (G_UNLIKELY (existing_feature)) {
/* We unref now. No need to remove the feature name from the hash table, it
* got replaced by the new feature */
gst_object_unref (existing_feature);
gst_object_unparent (GST_OBJECT_CAST (existing_feature));
}
gst_object_ref_sink (feature);
gst_object_set_parent (GST_OBJECT_CAST (feature), GST_OBJECT_CAST (registry));
registry->priv->cookie++;
GST_OBJECT_UNLOCK (registry);
@ -598,7 +598,8 @@ gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
g_hash_table_remove (registry->feature_hash, feature->name);
registry->priv->cookie++;
GST_OBJECT_UNLOCK (registry);
gst_object_unref (feature);
gst_object_unparent ((GstObject *) feature);
}
/**

View file

@ -524,8 +524,9 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
GstRegistryChunkPluginFeature *pf = NULL;
GstPluginFeature *feature = NULL;
const gchar *const_str, *type_name;
const gchar *feature_name;
const gchar *plugin_name;
gchar *str, *feature_name;
gchar *str;
GType type;
guint i;
@ -540,7 +541,7 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
}
/* unpack more plugin feature strings */
unpack_string (*in, feature_name, end, fail);
unpack_string_nocopy (*in, feature_name, end, fail);
GST_DEBUG ("Plugin '%s' feature '%s' typename : '%s'", plugin_name,
feature_name, type_name);
@ -548,16 +549,13 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) {
GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name,
plugin_name);
g_free (feature_name);
return FALSE;
}
if (G_UNLIKELY ((feature = g_object_newv (type, 0, NULL)) == NULL)) {
GST_ERROR ("Can't create feature from type");
g_free (feature_name);
return FALSE;
}
feature->name = feature_name;
gst_plugin_feature_set_name (feature, feature_name);
if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
GST_ERROR ("typename : '%s' is not a plugin feature", type_name);

View file

@ -82,7 +82,11 @@
* contain a valid frame, this call must return FALSE and optionally
* set the @skipsize value to inform base class that how many bytes
* it needs to skip in order to find a valid frame. @framesize can always
* indicate a new minimum for current frame parsing. The passed buffer
* indicate a new minimum for current frame parsing. Indicating G_MAXUINT
* for requested amount means subclass simply needs best available
* subsequent data. In push mode this amounts to an additional input buffer
* (thus minimal additional latency), in pull mode this amounts to some
* arbitrary reasonable buffer size increase. The passed buffer
* is read-only. Note that @check_valid_frame might receive any small
* amount of input data when leftover data is being drained (e.g. at EOS).
* </para></listitem>
@ -237,6 +241,7 @@ struct _GstBaseParsePrivate
guint bitrate;
guint lead_in, lead_out;
GstClockTime lead_in_ts, lead_out_ts;
GstClockTime min_latency, max_latency;
gboolean discont;
gboolean flushing;
@ -306,6 +311,9 @@ struct _GstBaseParsePrivate
/* Segment event that closes the running segment prior to SEEK */
GstEvent *close_segment;
/* push mode helper frame */
GstBaseParseFrame frame;
};
typedef struct _GstBaseParseSeek
@ -566,8 +574,11 @@ gst_base_parse_frame_free (GstBaseParseFrame * frame)
frame->buffer = NULL;
}
if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC))
if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
g_slice_free (GstBaseParseFrame, frame);
} else {
memset (frame, 0, sizeof (*frame));
}
}
GType
@ -720,6 +731,11 @@ gst_base_parse_reset (GstBaseParse * parse)
g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL);
g_slist_free (parse->priv->pending_seeks);
parse->priv->pending_seeks = NULL;
/* we know it is not alloc'ed, but maybe other stuff to free, some day ... */
parse->priv->frame._private_flags |=
GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
gst_base_parse_frame_free (&parse->priv->frame);
GST_OBJECT_UNLOCK (parse);
}
@ -1036,6 +1052,9 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
parse->priv->flushing = FALSE;
parse->priv->discont = TRUE;
parse->priv->last_ts = GST_CLOCK_TIME_NONE;
parse->priv->frame._private_flags |=
GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
gst_base_parse_frame_free (&parse->priv->frame);
break;
case GST_EVENT_EOS:
@ -2152,19 +2171,17 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
const guint8 *data;
guint old_min_size = 0, min_size, av;
GstClockTime timestamp;
GstBaseParseFrame _frame;
GstBaseParseFrame *frame;
parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
bclass = GST_BASE_PARSE_GET_CLASS (parse);
frame = &_frame;
gst_base_parse_frame_init (frame);
frame = &parse->priv->frame;
if (G_LIKELY (buffer)) {
GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer));
if (G_UNLIKELY (parse->priv->passthrough)) {
gst_base_parse_frame_init (frame);
frame->buffer = gst_buffer_make_writable (buffer);
return gst_base_parse_push_frame (parse, frame);
}
@ -2181,16 +2198,29 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
gst_adapter_push (parse->priv->adapter, buffer);
}
if (G_UNLIKELY (buffer &&
GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
frame->_private_flags |= GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
gst_base_parse_frame_free (frame);
}
/* Parse and push as many frames as possible */
/* Stop either when adapter is empty or we are flushing */
while (!parse->priv->flushing) {
gboolean res;
/* maintain frame state for a single frame parsing round across _chain calls,
* so only init when needed */
if (!frame->_private_flags)
gst_base_parse_frame_init (frame);
tmpbuf = gst_buffer_new ();
old_min_size = 0;
/* Synchronization loop */
for (;;) {
/* note: if subclass indicates MAX fsize,
* this will not likely be available anyway ... */
min_size = MAX (parse->priv->min_frame_size, fsize);
av = gst_adapter_available (parse->priv->adapter);
@ -2220,7 +2250,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
data = gst_adapter_map (parse->priv->adapter, av);
gst_buffer_take_memory (tmpbuf,
gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
(gpointer) data, NULL, min_size, 0, min_size));
(gpointer) data, NULL, av, 0, av));
GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset;
if (parse->priv->discont) {
@ -2496,6 +2526,12 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
" (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
/* let's make this efficient for all subclass once and for all;
* maybe it does not need this much, but in the latter case, we know we are
* in pull mode here and might as well try to read and supply more anyway
* (so does the buffer caching mechanism) */
fsize = 64 * 1024;
while (TRUE) {
gboolean res;
@ -2546,7 +2582,9 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
if (!parse->priv->discont)
parse->priv->sync_offset = parse->priv->offset;
parse->priv->discont = TRUE;
/* something changed least; nullify loop check */
/* something changed at least; nullify loop check */
if (fsize == G_MAXUINT)
fsize = old_min_size + 64 * 1024;
old_min_size = 0;
}
/* skip == 0 should imply subclass set min_size to need more data;
@ -3015,6 +3053,31 @@ gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
GST_INFO_OBJECT (parse, "passthrough: %s", (passthrough) ? "yes" : "no");
}
/**
* gst_base_parse_set_latency:
* @parse: a #GstBaseParse
* @min_latency: minimum parse latency
* @max_latency: maximum parse latency
*
* Sets the minimum and maximum (which may likely be equal) latency introduced
* by the parsing process. If there is such a latency, which depends on the
* particular parsing of the format, it typically corresponds to 1 frame duration.
*
* Since: 0.10.34
*/
void
gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency,
GstClockTime max_latency)
{
GST_OBJECT_LOCK (parse);
parse->priv->min_latency = min_latency;
parse->priv->max_latency = max_latency;
GST_OBJECT_UNLOCK (parse);
GST_INFO_OBJECT (parse, "min/max latency %" GST_TIME_FORMAT ", %"
GST_TIME_FORMAT, GST_TIME_ARGS (min_latency),
GST_TIME_ARGS (max_latency));
}
static gboolean
gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
GstClockTime * duration)
@ -3175,6 +3238,29 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
}
break;
}
case GST_QUERY_LATENCY:
{
if ((res = gst_pad_peer_query (parse->sinkpad, query))) {
gboolean live;
GstClockTime min_latency, max_latency;
gst_query_parse_latency (query, &live, &min_latency, &max_latency);
GST_DEBUG_OBJECT (parse, "Peer latency: live %d, min %"
GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
GST_OBJECT_LOCK (parse);
/* add our latency */
if (min_latency != -1)
min_latency += parse->priv->min_latency;
if (max_latency != -1)
max_latency += parse->priv->max_latency;
GST_OBJECT_UNLOCK (parse);
gst_query_set_latency (query, live, min_latency, max_latency);
}
break;
}
default:
res = gst_pad_query_default (pad, query);
break;

View file

@ -297,6 +297,10 @@ void gst_base_parse_set_frame_rate (GstBaseParse * parse,
guint lead_in,
guint lead_out);
void gst_base_parse_set_latency (GstBaseParse * parse,
GstClockTime min_latency,
GstClockTime max_latency);
gboolean gst_base_parse_convert_default (GstBaseParse * parse,
GstFormat src_format,
gint64 src_value,

View file

@ -47,48 +47,34 @@ LDADD = $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(GST_OBJ_LIBS)
elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c: $(top_srcdir)/docs/manual/basics-elements.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/basics-elements.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
bin.c : $(top_srcdir)/docs/manual/basics-bins.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/basics-bins.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
pad.c ghostpad.c: $(top_srcdir)/docs/manual/basics-pads.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/basics-pads.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
gnome.c: $(top_srcdir)/docs/manual/appendix-integration.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/appendix-integration.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
helloworld.c: $(top_srcdir)/docs/manual/basics-helloworld.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/basics-helloworld.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
init.c: $(top_srcdir)/docs/manual/basics-init.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/basics-init.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
query.c: $(top_srcdir)/docs/manual/advanced-position.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/advanced-position.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
typefind.c dynamic.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/advanced-autoplugging.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
fakesrc.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/advanced-dataaccess.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ $<
playbin.c decodebin.c: $(top_srcdir)/docs/manual/highlevel-components.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/highlevel-components.xml
xml-mp3.c: $(top_srcdir)/docs/manual/highlevel-xml.xml
$(PERL_PATH) $(srcdir)/extract.pl $@ \
$(top_srcdir)/docs/manual/highlevel-xml.xml
$(PERL_PATH) $(srcdir)/extract.pl $@$<
TESTS = bin \
elementcreate elementfactory elementget elementlink elementmake \

View file

@ -300,7 +300,7 @@ flags_to_string (GFlagsValue * vals, guint flags)
--i;
if (vals[i].value != 0 && (flags_left & vals[i].value) == vals[i].value) {
if (s->len > 0)
g_string_append (s, " | ");
g_string_append_c (s, '+');
g_string_append (s, vals[i].value_nick);
flags_left -= vals[i].value;
if (flags_left == 0)