mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
docs/design/part-TODO.txt: Update TODO.
Original commit message from CVS: * docs/design/part-TODO.txt: Update TODO. * gst/gstbin.c: (message_check), (bin_replace_message), (bin_remove_messages), (is_eos), (gst_bin_add_func), (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler), (bin_query_duration_init), (bin_query_duration_fold), (bin_query_duration_done), (bin_query_generic_fold), (gst_bin_query): Handle SEGMENT_START/DONE messages correctly. More evolved query algorithm that handles duration queries correctly. * gst/gstelement.c: (gst_element_send_event), (gst_element_query), (gst_element_get_state_func), (gst_element_abort_state), (gst_element_commit_state), (gst_element_lost_state): Some more debugging. * gst/gstmessage.h: Added doc.
This commit is contained in:
parent
b204604572
commit
2803a5587e
5 changed files with 186 additions and 22 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2005-10-25 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* docs/design/part-TODO.txt:
|
||||
Update TODO.
|
||||
|
||||
* gst/gstbin.c: (message_check), (bin_replace_message),
|
||||
(bin_remove_messages), (is_eos), (gst_bin_add_func),
|
||||
(update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler),
|
||||
(bin_query_duration_init), (bin_query_duration_fold),
|
||||
(bin_query_duration_done), (bin_query_generic_fold),
|
||||
(gst_bin_query):
|
||||
Handle SEGMENT_START/DONE messages correctly.
|
||||
More evolved query algorithm that handles duration queries
|
||||
correctly.
|
||||
|
||||
* gst/gstelement.c: (gst_element_send_event), (gst_element_query),
|
||||
(gst_element_get_state_func), (gst_element_abort_state),
|
||||
(gst_element_commit_state), (gst_element_lost_state):
|
||||
Some more debugging.
|
||||
|
||||
* gst/gstmessage.h:
|
||||
Added doc.
|
||||
|
||||
2005-10-25 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/base/gstbasesink.c: (gst_base_sink_get_position):
|
||||
|
|
|
@ -31,3 +31,4 @@
|
|||
- make bin_bus_handler a vmethod so subclasses can use their own implementation
|
||||
or chain to the parent.
|
||||
|
||||
- make it possible to seek on other formats than bytes in basesrc.
|
||||
|
|
179
gst/gstbin.c
179
gst/gstbin.c
|
@ -442,13 +442,20 @@ message_check (GstMessage * message, MessageFind * target)
|
|||
}
|
||||
|
||||
/* with LOCK, returns TRUE if message had a valid SRC, takes ref on
|
||||
* the message. */
|
||||
* the message.
|
||||
*
|
||||
* A message that is cached and has the same SRC and type is replaced
|
||||
* by the given message.
|
||||
*/
|
||||
static gboolean
|
||||
bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
|
||||
{
|
||||
GList *previous;
|
||||
GstObject *src;
|
||||
gboolean res = TRUE;
|
||||
const gchar *name;
|
||||
|
||||
name = gst_message_type_get_name (GST_MESSAGE_TYPE (message));
|
||||
|
||||
if ((src = GST_MESSAGE_SRC (message))) {
|
||||
MessageFind find;
|
||||
|
@ -465,19 +472,16 @@ bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
|
|||
previous->data = message;
|
||||
|
||||
GST_DEBUG_OBJECT (bin, "replace old message %s from %s",
|
||||
gst_message_type_get_name (GST_MESSAGE_TYPE (message)),
|
||||
GST_ELEMENT_NAME (src));
|
||||
name, GST_ELEMENT_NAME (src));
|
||||
} else {
|
||||
/* keep new message */
|
||||
bin->messages = g_list_prepend (bin->messages, message);
|
||||
|
||||
GST_DEBUG_OBJECT (bin, "got new message %s from %s",
|
||||
gst_message_type_get_name (GST_MESSAGE_TYPE (message)),
|
||||
GST_ELEMENT_NAME (src));
|
||||
name, GST_ELEMENT_NAME (src));
|
||||
}
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing",
|
||||
gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
|
||||
GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing", name);
|
||||
res = FALSE;
|
||||
gst_message_unref (message);
|
||||
}
|
||||
|
@ -1756,6 +1760,8 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
|
|||
GST_UNLOCK (bin);
|
||||
break;
|
||||
|
||||
/* non toplevel bins just forward the message and don't start
|
||||
* a recalc themselves */
|
||||
not_toplevel:
|
||||
{
|
||||
GST_UNLOCK (bin);
|
||||
|
@ -1769,15 +1775,54 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
|
|||
}
|
||||
case GST_MESSAGE_SEGMENT_START:
|
||||
GST_LOCK (bin);
|
||||
/* replace any previous segment_start message from this source
|
||||
* with the new segment start message */
|
||||
bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
|
||||
GST_UNLOCK (bin);
|
||||
break;
|
||||
case GST_MESSAGE_SEGMENT_DONE:
|
||||
{
|
||||
MessageFind find;
|
||||
gboolean post = FALSE;
|
||||
GstFormat format;
|
||||
gint64 position;
|
||||
|
||||
gst_message_parse_segment_done (message, &format, &position);
|
||||
|
||||
GST_LOCK (bin);
|
||||
bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
|
||||
/* if there are no more segment_start messages, everybody posted
|
||||
* a segment_done and we can post one on the bus. */
|
||||
|
||||
/* we don't care who still has a pending segment start */
|
||||
find.src = NULL;
|
||||
find.types = GST_MESSAGE_SEGMENT_START;
|
||||
|
||||
if (!g_list_find_custom (bin->messages, &find,
|
||||
(GCompareFunc) message_check)) {
|
||||
/* nothing found */
|
||||
post = TRUE;
|
||||
/* remove all old segment_done messages */
|
||||
bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
|
||||
}
|
||||
GST_UNLOCK (bin);
|
||||
if (post) {
|
||||
/* post segment done with latest format and position. */
|
||||
gst_element_post_message (GST_ELEMENT_CAST (bin),
|
||||
gst_message_new_segment_done (GST_OBJECT_CAST (bin),
|
||||
format, position));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_DURATION:
|
||||
{
|
||||
/* remove all cached duration messages, next time somebody asks
|
||||
* for duration, we will recalculate. */
|
||||
GST_LOCK (bin);
|
||||
bin_remove_messages (bin, NULL, GST_MESSAGE_DURATION);
|
||||
GST_UNLOCK (bin);
|
||||
/* fallthrough */
|
||||
}
|
||||
default:
|
||||
/* Send all other messages upward */
|
||||
GST_DEBUG_OBJECT (bin, "posting message upward");
|
||||
|
@ -1788,40 +1833,130 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
|
|||
return GST_BUS_DROP;
|
||||
}
|
||||
|
||||
/* generic struct passed to all query fold methods */
|
||||
typedef struct
|
||||
{
|
||||
GstQuery *query;
|
||||
gint64 max;
|
||||
} QueryFold;
|
||||
|
||||
typedef void (*QueryInitFunction) (GstBin * bin, QueryFold * fold);
|
||||
typedef void (*QueryDoneFunction) (GstBin * bin, QueryFold * fold);
|
||||
|
||||
/* for duration we collect all durations and take the MAX of
|
||||
* all valid results */
|
||||
static void
|
||||
bin_query_duration_init (GstBin * bin, QueryFold * fold)
|
||||
{
|
||||
fold->max = -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
bin_query_duration_fold (GstElement * item, GValue * ret, QueryFold * fold)
|
||||
{
|
||||
if (gst_element_query (item, fold->query)) {
|
||||
gint64 duration;
|
||||
|
||||
g_value_set_boolean (ret, TRUE);
|
||||
|
||||
gst_query_parse_duration (fold->query, NULL, &duration);
|
||||
|
||||
GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration);
|
||||
|
||||
if (duration > fold->max)
|
||||
fold->max = duration;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
static void
|
||||
bin_query_duration_done (GstBin * bin, QueryFold * fold)
|
||||
{
|
||||
GstFormat format;
|
||||
|
||||
gst_query_parse_duration (fold->query, &format, NULL);
|
||||
/* store max in query result */
|
||||
gst_query_set_duration (fold->query, format, fold->max);
|
||||
|
||||
GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
|
||||
}
|
||||
|
||||
/* generic fold, return first valid result */
|
||||
static gboolean
|
||||
bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
if ((res = gst_element_query (item, fold->query))) {
|
||||
g_value_set_boolean (ret, TRUE);
|
||||
GST_DEBUG_OBJECT (item, "answered query");
|
||||
}
|
||||
|
||||
/* and stop as soon as we have a valid result */
|
||||
return !res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_bin_query (GstElement * element, GstQuery * query)
|
||||
{
|
||||
GstBin *bin = GST_BIN (element);
|
||||
GstIterator *iter;
|
||||
gboolean res = FALSE, done = FALSE;
|
||||
gboolean res = FALSE;
|
||||
GstIteratorFoldFunction fold_func;
|
||||
QueryInitFunction fold_init = NULL;
|
||||
QueryDoneFunction fold_done = NULL;
|
||||
QueryFold fold_data;
|
||||
GValue ret = { 0 };
|
||||
|
||||
fold_data.query = query;
|
||||
|
||||
g_value_init (&ret, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean (&ret, FALSE);
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_DURATION:
|
||||
fold_func = (GstIteratorFoldFunction) bin_query_duration_fold;
|
||||
fold_init = bin_query_duration_init;
|
||||
fold_done = bin_query_duration_done;
|
||||
break;
|
||||
default:
|
||||
fold_func = (GstIteratorFoldFunction) bin_query_generic_fold;
|
||||
break;
|
||||
}
|
||||
|
||||
iter = gst_bin_iterate_sinks (bin);
|
||||
GST_DEBUG_OBJECT (bin, "Sending query to sink children");
|
||||
|
||||
while (!(res || done)) {
|
||||
gpointer data;
|
||||
if (fold_init)
|
||||
fold_init (bin, &fold_data);
|
||||
|
||||
switch (gst_iterator_next (iter, &data)) {
|
||||
case GST_ITERATOR_OK:
|
||||
{
|
||||
GstElement *sink;
|
||||
while (TRUE) {
|
||||
GstIteratorResult ires;
|
||||
|
||||
sink = GST_ELEMENT_CAST (data);
|
||||
res = gst_element_query (sink, query);
|
||||
gst_object_unref (sink);
|
||||
break;
|
||||
}
|
||||
ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data);
|
||||
|
||||
switch (ires) {
|
||||
case GST_ITERATOR_RESYNC:
|
||||
gst_iterator_resync (iter);
|
||||
if (fold_init)
|
||||
fold_init (bin, &fold_data);
|
||||
g_value_set_boolean (&ret, FALSE);
|
||||
break;
|
||||
default:
|
||||
case GST_ITERATOR_OK:
|
||||
case GST_ITERATOR_DONE:
|
||||
done = TRUE;
|
||||
break;
|
||||
if (fold_done)
|
||||
fold_done (bin, &fold_data);
|
||||
res = g_value_get_boolean (&ret);
|
||||
goto done;
|
||||
default:
|
||||
res = FALSE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
gst_iterator_free (iter);
|
||||
|
||||
GST_DEBUG_OBJECT (bin, "query result %d", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -1185,6 +1185,8 @@ gst_element_send_event (GstElement * element, GstEvent * event)
|
|||
oclass = GST_ELEMENT_GET_CLASS (element);
|
||||
|
||||
if (oclass->send_event) {
|
||||
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send event on element %s",
|
||||
GST_ELEMENT_NAME (element));
|
||||
result = oclass->send_event (element, event);
|
||||
} else {
|
||||
GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
|
||||
|
@ -1306,6 +1308,8 @@ gst_element_query (GstElement * element, GstQuery * query)
|
|||
oclass = GST_ELEMENT_GET_CLASS (element);
|
||||
|
||||
if (oclass->query) {
|
||||
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
|
||||
GST_ELEMENT_NAME (element));
|
||||
result = oclass->query (element, query);
|
||||
} else {
|
||||
GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
|
||||
|
|
|
@ -37,6 +37,7 @@ typedef struct _GstMessageClass GstMessageClass;
|
|||
* @GST_MESSAGE_TAG: a tag was found.
|
||||
* @GST_MESSAGE_BUFFERING: the pipeline is buffering
|
||||
* @GST_MESSAGE_STATE_CHANGED: a state change happened
|
||||
* @GST_MESSAGE_STATE_DIRTY: an element changed state in a streaming thread
|
||||
* @GST_MESSAGE_STEP_DONE: a framestep finished.
|
||||
* @GST_MESSAGE_CLOCK_PROVIDE: an element notifies its capability of providing
|
||||
* a clock.
|
||||
|
|
Loading…
Reference in a new issue