2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3 * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sourceforge.net>
4 * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 * SECTION:gstcollectpads2
25 * @short_description: manages a set of pads that operate in collect mode
28 * Manages a set of pads that operate in collect mode. This means that control
29 * is given to the manager of this object when all pads have data.
32 * Collectpads are created with gst_collect_pads2_new(). A callback should then
33 * be installed with gst_collect_pads2_set_function ().
36 * Pads are added to the collection with gst_collect_pads2_add_pad()/
37 * gst_collect_pads2_remove_pad(). The pad
38 * has to be a sinkpad. The chain and event functions of the pad are
39 * overridden. The element_private of the pad is used to store
40 * private information for the collectpads.
43 * For each pad, data is queued in the _chain function or by
44 * performing a pull_range.
47 * When data is queued on all pads in waiting mode, the callback function is called.
50 * Data can be dequeued from the pad with the gst_collect_pads2_pop() method.
51 * One can peek at the data with the gst_collect_pads2_peek() function.
52 * These functions will return NULL if the pad received an EOS event. When all
53 * pads return NULL from a gst_collect_pads2_peek(), the element can emit an EOS
57 * Data can also be dequeued in byte units using the gst_collect_pads2_available(),
58 * gst_collect_pads2_read() and gst_collect_pads2_flush() calls.
61 * Elements should call gst_collect_pads2_start() and gst_collect_pads2_stop() in
62 * their state change functions to start and stop the processing of the collectpads.
63 * The gst_collect_pads2_stop() call should be called before calling the parent
64 * element state change function in the PAUSED_TO_READY state change to ensure
65 * no pad is blocked and the element can finish streaming.
68 * gst_collect_pads2_collect() and gst_collect_pads2_collect_range() can be used by
69 * elements that start a #GstTask to drive the collect_pads2. This feature is however
70 * not yet implemented.
73 * gst_collect_pads2_set_waiting() sets a pad to waiting or non-waiting mode.
74 * CollectPads element is not waiting for data to be collected on non-waiting pads.
75 * Thus these pads may but need not have data when the callback is called.
76 * All pads are in waiting mode by default.
80 * Last reviewed on 2011-10-28 (0.10.36)
89 #include <gst/gst_private.h>
91 #include "gstcollectpads2.h"
93 #include "../../../gst/glib-compat-private.h"
95 GST_DEBUG_CATEGORY_STATIC (collect_pads2_debug);
96 #define GST_CAT_DEFAULT collect_pads2_debug
98 #define parent_class gst_collect_pads2_parent_class
99 G_DEFINE_TYPE (GstCollectPads2, gst_collect_pads2, GST_TYPE_OBJECT);
101 static void gst_collect_pads2_clear (GstCollectPads2 * pads,
102 GstCollectData2 * data);
103 static GstFlowReturn gst_collect_pads2_chain (GstPad * pad, GstObject * parent,
105 static gboolean gst_collect_pads2_event (GstPad * pad, GstObject * parent,
107 static void gst_collect_pads2_finalize (GObject * object);
108 static GstFlowReturn gst_collect_pads2_default_collected (GstCollectPads2 *
109 pads, gpointer user_data);
110 static gint gst_collect_pads2_default_compare_func (GstCollectPads2 * pads,
111 GstCollectData2 * data1, GstClockTime timestamp1, GstCollectData2 * data2,
112 GstClockTime timestamp2, gpointer user_data);
113 static gboolean gst_collect_pads2_recalculate_full (GstCollectPads2 * pads);
114 static void ref_data (GstCollectData2 * data);
115 static void unref_data (GstCollectData2 * data);
117 /* Some properties are protected by LOCK, others by STREAM_LOCK
118 * However, manipulating either of these partitions may require
119 * to signal/wake a _WAIT, so use a separate (sort of) event to prevent races
120 * Alternative implementations are possible, e.g. some low-level re-implementing
121 * of the 2 above locks to drop both of them atomically when going into _WAIT.
123 #define GST_COLLECT_PADS2_GET_EVT_COND(pads) (&((GstCollectPads2 *)pads)->evt_cond)
124 #define GST_COLLECT_PADS2_GET_EVT_LOCK(pads) (&((GstCollectPads2 *)pads)->evt_lock)
125 #define GST_COLLECT_PADS2_EVT_WAIT(pads, cookie) G_STMT_START { \
126 g_mutex_lock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
127 /* should work unless a lot of event'ing and thread starvation */\
128 while (cookie == ((GstCollectPads2 *) pads)->evt_cookie) \
129 g_cond_wait (GST_COLLECT_PADS2_GET_EVT_COND (pads), \
130 GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
131 cookie = ((GstCollectPads2 *) pads)->evt_cookie; \
132 g_mutex_unlock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
134 #define GST_COLLECT_PADS2_EVT_WAIT_TIMED(pads, cookie, timeout) G_STMT_START { \
137 g_get_current_time (&tv); \
138 g_time_val_add (&tv, timeout); \
140 g_mutex_lock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
141 /* should work unless a lot of event'ing and thread starvation */\
142 while (cookie == ((GstCollectPads2 *) pads)->evt_cookie) \
143 g_cond_timed_wait (GST_COLLECT_PADS2_GET_EVT_COND (pads), \
144 GST_COLLECT_PADS2_GET_EVT_LOCK (pads), &tv); \
145 cookie = ((GstCollectPads2 *) pads)->evt_cookie; \
146 g_mutex_unlock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
148 #define GST_COLLECT_PADS2_EVT_BROADCAST(pads) G_STMT_START { \
149 g_mutex_lock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
150 /* never mind wrap-around */ \
151 ++(((GstCollectPads2 *) pads)->evt_cookie); \
152 g_cond_broadcast (GST_COLLECT_PADS2_GET_EVT_COND (pads)); \
153 g_mutex_unlock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
155 #define GST_COLLECT_PADS2_EVT_INIT(cookie) G_STMT_START { \
156 g_mutex_lock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
157 cookie = ((GstCollectPads2 *) pads)->evt_cookie; \
158 g_mutex_unlock (GST_COLLECT_PADS2_GET_EVT_LOCK (pads)); \
162 gst_collect_pads2_class_init (GstCollectPads2Class * klass)
164 GObjectClass *gobject_class = (GObjectClass *) klass;
166 GST_DEBUG_CATEGORY_INIT (collect_pads2_debug, "collectpads2", 0,
169 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_collect_pads2_finalize);
173 gst_collect_pads2_init (GstCollectPads2 * pads)
178 pads->queuedpads = 0;
180 pads->started = FALSE;
182 g_rec_mutex_init (&pads->stream_lock);
184 pads->func = gst_collect_pads2_default_collected;
185 pads->user_data = NULL;
186 pads->event_func = NULL;
187 pads->event_user_data = NULL;
189 /* members for default muxing */
190 pads->buffer_func = NULL;
191 pads->buffer_user_data = NULL;
192 pads->compare_func = gst_collect_pads2_default_compare_func;
193 pads->compare_user_data = NULL;
194 pads->earliest_data = NULL;
195 pads->earliest_time = GST_CLOCK_TIME_NONE;
197 /* members to manage the pad list */
198 pads->pad_cookie = 0;
199 pads->pad_list = NULL;
201 /* members for event */
202 g_mutex_init (&pads->evt_lock);
203 g_cond_init (&pads->evt_cond);
204 pads->evt_cookie = 0;
208 gst_collect_pads2_finalize (GObject * object)
210 GstCollectPads2 *pads = GST_COLLECT_PADS2 (object);
212 GST_DEBUG_OBJECT (object, "finalize");
214 g_rec_mutex_clear (&pads->stream_lock);
216 g_cond_clear (&pads->evt_cond);
217 g_mutex_clear (&pads->evt_lock);
219 /* Remove pads and free pads list */
220 g_slist_foreach (pads->pad_list, (GFunc) unref_data, NULL);
221 g_slist_foreach (pads->data, (GFunc) unref_data, NULL);
222 g_slist_free (pads->data);
223 g_slist_free (pads->pad_list);
225 G_OBJECT_CLASS (parent_class)->finalize (object);
229 * gst_collect_pads2_new:
231 * Create a new instance of #GstCollectsPads.
233 * Returns: a new #GstCollectPads2, or NULL in case of an error.
240 gst_collect_pads2_new (void)
242 GstCollectPads2 *newcoll;
244 newcoll = g_object_new (GST_TYPE_COLLECT_PADS2, NULL);
249 /* Must be called with GstObject lock! */
251 gst_collect_pads2_set_buffer_function_locked (GstCollectPads2 * pads,
252 GstCollectPads2BufferFunction func, gpointer user_data)
254 pads->buffer_func = func;
255 pads->buffer_user_data = user_data;
259 * gst_collect_pads2_set_buffer_function:
260 * @pads: the collectpads to use
261 * @func: the function to set
262 * @user_data: user data passed to the function
264 * Set the callback function and user data that will be called with
265 * the oldest buffer when all pads have been collected.
272 gst_collect_pads2_set_buffer_function (GstCollectPads2 * pads,
273 GstCollectPads2BufferFunction func, gpointer user_data)
275 g_return_if_fail (pads != NULL);
276 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
278 GST_OBJECT_LOCK (pads);
279 gst_collect_pads2_set_buffer_function_locked (pads, func, user_data);
280 GST_OBJECT_UNLOCK (pads);
284 * gst_collect_pads2_set_compare_function:
285 * @pads: the pads to use
286 * @func: the function to set
287 * @user_data: user data passed to the function
289 * Set the timestamp comparison function.
295 /* NOTE allowing to change comparison seems not advisable;
296 no known use-case, and collaboration with default algorithm is unpredictable.
297 If custom compairing/operation is needed, just use a collect function of
300 gst_collect_pads2_set_compare_function (GstCollectPads2 * pads,
301 GstCollectPads2CompareFunction func, gpointer user_data)
303 g_return_if_fail (pads != NULL);
304 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
306 GST_OBJECT_LOCK (pads);
307 pads->compare_func = func;
308 pads->compare_user_data = user_data;
309 GST_OBJECT_UNLOCK (pads);
313 * gst_collect_pads2_set_function:
314 * @pads: the collectspads to use
315 * @func: the function to set
316 * @user_data: user data passed to the function
318 * CollectPads provides a default collection algorithm that will determine
319 * the oldest buffer available on all of its pads, and then delegate
320 * to a configured callback.
321 * However, if circumstances are more complicated and/or more control
322 * is desired, this sets a callback that will be invoked instead when
323 * all the pads added to the collection have buffers queued.
324 * Evidently, this callback is not compatible with
325 * gst_collect_pads2_set_buffer_function() callback.
326 * If this callback is set, the former will be unset.
333 gst_collect_pads2_set_function (GstCollectPads2 * pads,
334 GstCollectPads2Function func, gpointer user_data)
336 g_return_if_fail (pads != NULL);
337 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
339 GST_OBJECT_LOCK (pads);
341 pads->user_data = user_data;
342 gst_collect_pads2_set_buffer_function_locked (pads, NULL, NULL);
343 GST_OBJECT_UNLOCK (pads);
347 ref_data (GstCollectData2 * data)
349 g_assert (data != NULL);
351 g_atomic_int_inc (&(data->refcount));
355 unref_data (GstCollectData2 * data)
357 g_assert (data != NULL);
358 g_assert (data->refcount > 0);
360 if (!g_atomic_int_dec_and_test (&(data->refcount)))
363 if (data->destroy_notify)
364 data->destroy_notify (data);
366 g_object_unref (data->pad);
368 gst_buffer_unref (data->buffer);
374 * gst_collect_pads2_set_event_function:
375 * @pads: the collectspads to use
376 * @func: the function to set
377 * @user_data: user data passed to the function
379 * Set the event callback function and user data that will be called after
380 * collectpads has processed and event originating from one of the collected
381 * pads. If the event being processed is a serialized one, this callback is
382 * called with @pads STREAM_LOCK held, otherwise not. As this lock should be
383 * held when calling a number of CollectPads functions, it should be acquired
384 * if so (unusually) needed.
391 gst_collect_pads2_set_event_function (GstCollectPads2 * pads,
392 GstCollectPads2EventFunction func, gpointer user_data)
394 g_return_if_fail (pads != NULL);
395 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
397 GST_OBJECT_LOCK (pads);
398 pads->event_func = func;
399 pads->event_user_data = user_data;
400 GST_OBJECT_UNLOCK (pads);
404 * gst_collect_pads2_clip_running:
405 * @pads: the collectspads to use
406 * @cdata: collect data of corrsponding pad
407 * @buf: buffer being clipped
408 * @outbuf: output buffer with running time, or NULL if clipped
409 * @user_data: user data (unused)
411 * Convenience clipping function that converts incoming buffer's timestamp
412 * to running time, or clips the buffer if outside configured segment.
417 gst_collect_pads2_clip_running_time (GstCollectPads2 * pads,
418 GstCollectData2 * cdata, GstBuffer * buf, GstBuffer ** outbuf,
424 time = GST_BUFFER_TIMESTAMP (buf);
426 /* invalid left alone and passed */
427 if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
428 time = gst_segment_to_running_time (&cdata->segment, GST_FORMAT_TIME, time);
429 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
430 GST_DEBUG_OBJECT (cdata->pad, "clipping buffer on pad outside segment");
431 gst_buffer_unref (buf);
434 GST_LOG_OBJECT (cdata->pad, "buffer ts %" GST_TIME_FORMAT " -> %"
435 GST_TIME_FORMAT " running time",
436 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (time));
437 *outbuf = gst_buffer_make_writable (buf);
438 GST_BUFFER_TIMESTAMP (*outbuf) = time;
446 * gst_collect_pads2_set_clip_function:
447 * @pads: the collectspads to use
448 * @clipfunc: clip function to install
449 * @user_data: user data to pass to @clip_func
451 * Install a clipping function that is called right after a buffer is received
452 * on a pad managed by @pads. See #GstCollectPad2ClipFunction for more info.
457 gst_collect_pads2_set_clip_function (GstCollectPads2 * pads,
458 GstCollectPads2ClipFunction clipfunc, gpointer user_data)
460 g_return_if_fail (pads != NULL);
461 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
463 pads->clip_func = clipfunc;
464 pads->clip_user_data = user_data;
468 * gst_collect_pads2_add_pad:
469 * @pads: the collectspads to use
470 * @pad: the pad to add
471 * @size: the size of the returned #GstCollectData2 structure
473 * Add a pad to the collection of collect pads. The pad has to be
474 * a sinkpad. The refcount of the pad is incremented. Use
475 * gst_collect_pads2_remove_pad() to remove the pad from the collection
478 * You specify a size for the returned #GstCollectData2 structure
479 * so that you can use it to store additional information.
481 * The pad will be automatically activated in push mode when @pads is
484 * This function calls gst_collect_pads2_add_pad() passing a value of NULL
485 * for destroy_notify and TRUE for locked.
487 * Returns: a new #GstCollectData2 to identify the new pad. Or NULL
488 * if wrong parameters are supplied.
495 gst_collect_pads2_add_pad (GstCollectPads2 * pads, GstPad * pad, guint size)
497 return gst_collect_pads2_add_pad_full (pads, pad, size, NULL, TRUE);
501 * gst_collect_pads2_add_pad_full:
502 * @pads: the collectspads to use
503 * @pad: the pad to add
504 * @size: the size of the returned #GstCollectData2 structure
505 * @destroy_notify: function to be called before the returned #GstCollectData2
507 * @lock: whether to lock this pad in usual waiting state
509 * Add a pad to the collection of collect pads. The pad has to be
510 * a sinkpad. The refcount of the pad is incremented. Use
511 * gst_collect_pads2_remove_pad() to remove the pad from the collection
514 * You specify a size for the returned #GstCollectData2 structure
515 * so that you can use it to store additional information.
517 * You can also specify a #GstCollectData2DestroyNotify that will be called
518 * just before the #GstCollectData2 structure is freed. It is passed the
519 * pointer to the structure and should free any custom memory and resources
522 * Keeping a pad locked in waiting state is only relevant when using
523 * the default collection algorithm (providing the oldest buffer).
524 * It ensures a buffer must be available on this pad for a collection
525 * to take place. This is of typical use to a muxer element where
526 * non-subtitle streams should always be in waiting state,
527 * e.g. to assure that caps information is available on all these streams
528 * when initial headers have to be written.
530 * The pad will be automatically activated in push mode when @pads is
535 * Returns: a new #GstCollectData2 to identify the new pad. Or NULL
536 * if wrong parameters are supplied.
541 gst_collect_pads2_add_pad_full (GstCollectPads2 * pads, GstPad * pad,
542 guint size, GstCollectData2DestroyNotify destroy_notify, gboolean lock)
544 GstCollectData2 *data;
546 g_return_val_if_fail (pads != NULL, NULL);
547 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), NULL);
548 g_return_val_if_fail (pad != NULL, NULL);
549 g_return_val_if_fail (GST_PAD_IS_SINK (pad), NULL);
550 g_return_val_if_fail (size >= sizeof (GstCollectData2), NULL);
552 GST_DEBUG_OBJECT (pads, "adding pad %s:%s", GST_DEBUG_PAD_NAME (pad));
554 data = g_malloc0 (size);
555 data->collect = pads;
556 data->pad = gst_object_ref (pad);
559 gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
560 data->state = GST_COLLECT_PADS2_STATE_WAITING;
561 data->state |= lock ? GST_COLLECT_PADS2_STATE_LOCKED : 0;
563 data->destroy_notify = destroy_notify;
565 GST_OBJECT_LOCK (pads);
566 GST_OBJECT_LOCK (pad);
567 gst_pad_set_element_private (pad, data);
568 GST_OBJECT_UNLOCK (pad);
569 pads->pad_list = g_slist_append (pads->pad_list, data);
570 gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads2_chain));
571 gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads2_event));
572 /* backward compat, also add to data if stopped, so that the element already
573 * has this in the public data list before going PAUSED (typically)
574 * this can only be done when we are stopped because we don't take the
575 * STREAM_LOCK to protect the pads->data list. */
576 if (!pads->started) {
577 pads->data = g_slist_append (pads->data, data);
580 /* activate the pad when needed */
582 gst_pad_set_active (pad, TRUE);
584 GST_OBJECT_UNLOCK (pads);
590 find_pad (GstCollectData2 * data, GstPad * pad)
592 if (data->pad == pad)
598 * gst_collect_pads2_remove_pad:
599 * @pads: the collectspads to use
600 * @pad: the pad to remove
602 * Remove a pad from the collection of collect pads. This function will also
603 * free the #GstCollectData2 and all the resources that were allocated with
604 * gst_collect_pads2_add_pad().
606 * The pad will be deactivated automatically when @pads is stopped.
608 * Returns: %TRUE if the pad could be removed.
615 gst_collect_pads2_remove_pad (GstCollectPads2 * pads, GstPad * pad)
617 GstCollectData2 *data;
620 g_return_val_if_fail (pads != NULL, FALSE);
621 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), FALSE);
622 g_return_val_if_fail (pad != NULL, FALSE);
623 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
625 GST_DEBUG_OBJECT (pads, "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
627 GST_OBJECT_LOCK (pads);
628 list = g_slist_find_custom (pads->pad_list, pad, (GCompareFunc) find_pad);
632 data = (GstCollectData2 *) list->data;
634 GST_DEBUG_OBJECT (pads, "found pad %s:%s at %p", GST_DEBUG_PAD_NAME (pad),
637 /* clear the stuff we configured */
638 gst_pad_set_chain_function (pad, NULL);
639 gst_pad_set_event_function (pad, NULL);
640 GST_OBJECT_LOCK (pad);
641 gst_pad_set_element_private (pad, NULL);
642 GST_OBJECT_UNLOCK (pad);
644 /* backward compat, also remove from data if stopped, note that this function
645 * can only be called when we are stopped because we don't take the
646 * STREAM_LOCK to protect the pads->data list. */
647 if (!pads->started) {
650 dlist = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad);
652 GstCollectData2 *pdata = dlist->data;
654 pads->data = g_slist_delete_link (pads->data, dlist);
658 /* remove from the pad list */
659 pads->pad_list = g_slist_delete_link (pads->pad_list, list);
662 /* signal waiters because something changed */
663 GST_COLLECT_PADS2_EVT_BROADCAST (pads);
665 /* deactivate the pad when needed */
667 gst_pad_set_active (pad, FALSE);
669 /* clean and free the collect data */
672 GST_OBJECT_UNLOCK (pads);
678 GST_WARNING_OBJECT (pads, "cannot remove unknown pad %s:%s",
679 GST_DEBUG_PAD_NAME (pad));
680 GST_OBJECT_UNLOCK (pads);
686 * gst_collect_pads2_is_active:
687 * @pads: the collectspads to use
688 * @pad: the pad to check
690 * Check if a pad is active.
692 * This function is currently not implemented.
694 * Returns: %TRUE if the pad is active.
701 gst_collect_pads2_is_active (GstCollectPads2 * pads, GstPad * pad)
703 g_return_val_if_fail (pads != NULL, FALSE);
704 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), FALSE);
705 g_return_val_if_fail (pad != NULL, FALSE);
706 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
708 g_warning ("gst_collect_pads2_is_active() is not implemented");
714 * gst_collect_pads2_collect:
715 * @pads: the collectspads to use
717 * Collect data on all pads. This function is usually called
718 * from a #GstTask function in an element.
720 * This function is currently not implemented.
722 * Returns: #GstFlowReturn of the operation.
729 gst_collect_pads2_collect (GstCollectPads2 * pads)
731 g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
732 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), GST_FLOW_ERROR);
734 g_warning ("gst_collect_pads2_collect() is not implemented");
736 return GST_FLOW_NOT_SUPPORTED;
740 * gst_collect_pads2_collect_range:
741 * @pads: the collectspads to use
742 * @offset: the offset to collect
743 * @length: the length to collect
745 * Collect data with @offset and @length on all pads. This function
746 * is typically called in the getrange function of an element.
748 * This function is currently not implemented.
750 * Returns: #GstFlowReturn of the operation.
757 gst_collect_pads2_collect_range (GstCollectPads2 * pads, guint64 offset,
760 g_return_val_if_fail (pads != NULL, GST_FLOW_ERROR);
761 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), GST_FLOW_ERROR);
763 g_warning ("gst_collect_pads2_collect_range() is not implemented");
765 return GST_FLOW_NOT_SUPPORTED;
769 * Must be called with STREAM_LOCK.
772 gst_collect_pads2_set_flushing_unlocked (GstCollectPads2 * pads,
777 /* Update the pads flushing flag */
778 for (walk = pads->data; walk; walk = g_slist_next (walk)) {
779 GstCollectData2 *cdata = walk->data;
781 if (GST_IS_PAD (cdata->pad)) {
782 GST_OBJECT_LOCK (cdata->pad);
784 GST_PAD_SET_FLUSHING (cdata->pad);
786 GST_PAD_UNSET_FLUSHING (cdata->pad);
788 GST_COLLECT_PADS2_STATE_SET (cdata, GST_COLLECT_PADS2_STATE_FLUSHING);
790 GST_COLLECT_PADS2_STATE_UNSET (cdata, GST_COLLECT_PADS2_STATE_FLUSHING);
791 gst_collect_pads2_clear (pads, cdata);
792 GST_OBJECT_UNLOCK (cdata->pad);
796 /* inform _chain of changes */
797 GST_COLLECT_PADS2_EVT_BROADCAST (pads);
801 * gst_collect_pads2_set_flushing:
802 * @pads: the collectspads to use
803 * @flushing: desired state of the pads
805 * Change the flushing state of all the pads in the collection. No pad
806 * is able to accept anymore data when @flushing is %TRUE. Calling this
807 * function with @flushing %FALSE makes @pads accept data again.
808 * Caller must ensure that downstream streaming (thread) is not blocked,
809 * e.g. by sending a FLUSH_START downstream.
817 gst_collect_pads2_set_flushing (GstCollectPads2 * pads, gboolean flushing)
819 g_return_if_fail (pads != NULL);
820 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
822 /* NOTE since this eventually calls _pop, some (STREAM_)LOCK is needed here */
823 GST_COLLECT_PADS2_STREAM_LOCK (pads);
824 gst_collect_pads2_set_flushing_unlocked (pads, flushing);
825 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
829 * gst_collect_pads2_start:
830 * @pads: the collectspads to use
832 * Starts the processing of data in the collect_pads2.
839 gst_collect_pads2_start (GstCollectPads2 * pads)
843 g_return_if_fail (pads != NULL);
844 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
846 GST_DEBUG_OBJECT (pads, "starting collect pads");
848 /* make sure stop and collect cannot be called anymore */
849 GST_COLLECT_PADS2_STREAM_LOCK (pads);
851 /* make pads streamable */
852 GST_OBJECT_LOCK (pads);
854 /* loop over the master pad list and reset the segment */
855 collected = pads->pad_list;
856 for (; collected; collected = g_slist_next (collected)) {
857 GstCollectData2 *data;
859 data = collected->data;
860 gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
863 gst_collect_pads2_set_flushing_unlocked (pads, FALSE);
865 /* Start collect pads */
866 pads->started = TRUE;
867 GST_OBJECT_UNLOCK (pads);
868 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
872 * gst_collect_pads2_stop:
873 * @pads: the collectspads to use
875 * Stops the processing of data in the collect_pads2. this function
876 * will also unblock any blocking operations.
883 gst_collect_pads2_stop (GstCollectPads2 * pads)
887 g_return_if_fail (pads != NULL);
888 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
890 GST_DEBUG_OBJECT (pads, "stopping collect pads");
892 /* make sure collect and start cannot be called anymore */
893 GST_COLLECT_PADS2_STREAM_LOCK (pads);
895 /* make pads not accept data anymore */
896 GST_OBJECT_LOCK (pads);
897 gst_collect_pads2_set_flushing_unlocked (pads, TRUE);
899 /* Stop collect pads */
900 pads->started = FALSE;
902 pads->queuedpads = 0;
904 /* loop over the master pad list and flush buffers */
905 collected = pads->pad_list;
906 for (; collected; collected = g_slist_next (collected)) {
907 GstCollectData2 *data;
908 GstBuffer **buffer_p;
910 data = collected->data;
912 buffer_p = &data->buffer;
913 gst_buffer_replace (buffer_p, NULL);
916 GST_COLLECT_PADS2_STATE_UNSET (data, GST_COLLECT_PADS2_STATE_EOS);
919 if (pads->earliest_data)
920 unref_data (pads->earliest_data);
921 pads->earliest_data = NULL;
922 pads->earliest_time = GST_CLOCK_TIME_NONE;
924 GST_OBJECT_UNLOCK (pads);
925 /* Wake them up so they can end the chain functions. */
926 GST_COLLECT_PADS2_EVT_BROADCAST (pads);
928 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
932 * gst_collect_pads2_peek:
933 * @pads: the collectspads to peek
934 * @data: the data to use
936 * Peek at the buffer currently queued in @data. This function
937 * should be called with the @pads STREAM_LOCK held, such as in the callback
940 * Returns: The buffer in @data or NULL if no buffer is queued.
941 * should unref the buffer after usage.
948 gst_collect_pads2_peek (GstCollectPads2 * pads, GstCollectData2 * data)
952 g_return_val_if_fail (pads != NULL, NULL);
953 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), NULL);
954 g_return_val_if_fail (data != NULL, NULL);
956 if ((result = data->buffer))
957 gst_buffer_ref (result);
959 GST_DEBUG_OBJECT (pads, "Peeking at pad %s:%s: buffer=%p",
960 GST_DEBUG_PAD_NAME (data->pad), result);
966 * gst_collect_pads2_pop:
967 * @pads: the collectspads to pop
968 * @data: the data to use
970 * Pop the buffer currently queued in @data. This function
971 * should be called with the @pads STREAM_LOCK held, such as in the callback
974 * Returns: The buffer in @data or NULL if no buffer was queued.
975 * You should unref the buffer after usage.
982 gst_collect_pads2_pop (GstCollectPads2 * pads, GstCollectData2 * data)
986 g_return_val_if_fail (pads != NULL, NULL);
987 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), NULL);
988 g_return_val_if_fail (data != NULL, NULL);
990 if ((result = data->buffer)) {
993 /* one less pad with queued data now */
994 if (GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_WAITING))
998 GST_COLLECT_PADS2_EVT_BROADCAST (pads);
1000 GST_DEBUG_OBJECT (pads, "Pop buffer on pad %s:%s: buffer=%p",
1001 GST_DEBUG_PAD_NAME (data->pad), result);
1006 /* pop and unref the currently queued buffer, should be called with STREAM_LOCK
1009 gst_collect_pads2_clear (GstCollectPads2 * pads, GstCollectData2 * data)
1013 if ((buf = gst_collect_pads2_pop (pads, data)))
1014 gst_buffer_unref (buf);
1018 * gst_collect_pads2_available:
1019 * @pads: the collectspads to query
1021 * Query how much bytes can be read from each queued buffer. This means
1022 * that the result of this call is the maximum number of bytes that can
1023 * be read from each of the pads.
1025 * This function should be called with @pads STREAM_LOCK held, such as
1028 * Returns: The maximum number of bytes queued on all pads. This function
1029 * returns 0 if a pad has no queued buffer.
1035 /* we might pre-calculate this in some struct field,
1036 * but would then have to maintain this in _chain and particularly _pop, etc,
1037 * even if element is never interested in this information */
1039 gst_collect_pads2_available (GstCollectPads2 * pads)
1042 guint result = G_MAXUINT;
1044 g_return_val_if_fail (pads != NULL, 0);
1045 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), 0);
1047 collected = pads->data;
1048 for (; collected; collected = g_slist_next (collected)) {
1049 GstCollectData2 *pdata;
1053 pdata = (GstCollectData2 *) collected->data;
1055 /* ignore pad with EOS */
1056 if (G_UNLIKELY (GST_COLLECT_PADS2_STATE_IS_SET (pdata,
1057 GST_COLLECT_PADS2_STATE_EOS))) {
1058 GST_DEBUG_OBJECT (pads, "pad %p is EOS", pdata);
1062 /* an empty buffer without EOS is weird when we get here.. */
1063 if (G_UNLIKELY ((buffer = pdata->buffer) == NULL)) {
1064 GST_WARNING_OBJECT (pads, "pad %p has no buffer", pdata);
1068 /* this is the size left of the buffer */
1069 size = gst_buffer_get_size (buffer) - pdata->pos;
1070 GST_DEBUG_OBJECT (pads, "pad %p has %d bytes left", pdata, size);
1072 /* need to return the min of all available data */
1076 /* nothing changed, all must be EOS then, return 0 */
1077 if (G_UNLIKELY (result == G_MAXUINT))
1089 * gst_collect_pads2_flush:
1090 * @pads: the collectspads to query
1091 * @data: the data to use
1092 * @size: the number of bytes to flush
1094 * Flush @size bytes from the pad @data.
1096 * This function should be called with @pads STREAM_LOCK held, such as
1099 * Returns: The number of bytes flushed This can be less than @size and
1100 * is 0 if the pad was end-of-stream.
1107 gst_collect_pads2_flush (GstCollectPads2 * pads, GstCollectData2 * data,
1114 g_return_val_if_fail (pads != NULL, 0);
1115 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), 0);
1116 g_return_val_if_fail (data != NULL, 0);
1118 /* no buffer, must be EOS */
1119 if ((buffer = data->buffer) == NULL)
1122 bsize = gst_buffer_get_size (buffer);
1124 /* this is what we can flush at max */
1125 flushsize = MIN (size, bsize - data->pos);
1129 if (data->pos >= bsize)
1130 /* _clear will also reset data->pos to 0 */
1131 gst_collect_pads2_clear (pads, data);
1137 * gst_collect_pads2_read_buffer:
1138 * @pads: the collectspads to query
1139 * @data: the data to use
1140 * @size: the number of bytes to read
1142 * Get a subbuffer of @size bytes from the given pad @data.
1144 * This function should be called with @pads STREAM_LOCK held, such as in the
1149 * Returns: A sub buffer. The size of the buffer can be less that requested.
1150 * A return of NULL signals that the pad is end-of-stream.
1151 * Unref the buffer after use.
1156 gst_collect_pads2_read_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
1162 g_return_val_if_fail (pads != NULL, NULL);
1163 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), NULL);
1164 g_return_val_if_fail (data != NULL, NULL);
1166 /* no buffer, must be EOS */
1167 if ((buffer = data->buffer) == NULL)
1170 readsize = MIN (size, gst_buffer_get_size (buffer) - data->pos);
1172 return gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, data->pos,
1177 * gst_collect_pads2_take_buffer:
1178 * @pads: the collectspads to query
1179 * @data: the data to use
1180 * @size: the number of bytes to read
1182 * Get a subbuffer of @size bytes from the given pad @data. Flushes the amount
1185 * This function should be called with @pads STREAM_LOCK held, such as in the
1190 * Returns: A sub buffer. The size of the buffer can be less that requested.
1191 * A return of NULL signals that the pad is end-of-stream.
1192 * Unref the buffer after use.
1197 gst_collect_pads2_take_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
1200 GstBuffer *buffer = gst_collect_pads2_read_buffer (pads, data, size);
1203 gst_collect_pads2_flush (pads, data, gst_buffer_get_size (buffer));
1209 * gst_collect_pads2_set_waiting:
1210 * @pads: the collectspads
1211 * @data: the data to use
1212 * @waiting: boolean indicating whether this pad should operate
1213 * in waiting or non-waiting mode
1215 * Sets a pad to waiting or non-waiting mode, if at least this pad
1216 * has not been created with locked waiting state,
1217 * in which case nothing happens.
1219 * This function should be called with @pads STREAM_LOCK held, such as
1227 gst_collect_pads2_set_waiting (GstCollectPads2 * pads, GstCollectData2 * data,
1230 g_return_if_fail (pads != NULL);
1231 g_return_if_fail (GST_IS_COLLECT_PADS2 (pads));
1232 g_return_if_fail (data != NULL);
1234 GST_DEBUG_OBJECT (pads, "Setting pad %s to waiting %d, locked %d",
1235 GST_PAD_NAME (data->pad), waiting,
1236 GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_LOCKED));
1238 /* Do something only on a change and if not locked */
1239 if (!GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_LOCKED) &&
1240 (GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_WAITING) !=
1242 /* Set waiting state for this pad */
1244 GST_COLLECT_PADS2_STATE_SET (data, GST_COLLECT_PADS2_STATE_WAITING);
1246 GST_COLLECT_PADS2_STATE_UNSET (data, GST_COLLECT_PADS2_STATE_WAITING);
1247 /* Update number of queued pads if needed */
1248 if (!data->buffer &&
1249 !GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_EOS)) {
1256 /* signal waiters because something changed */
1257 GST_COLLECT_PADS2_EVT_BROADCAST (pads);
1261 /* see if pads were added or removed and update our stats. Any pad
1262 * added after releasing the LOCK will get collected in the next
1265 * We can do a quick check by checking the cookies, that get changed
1266 * whenever the pad list is updated.
1268 * Must be called with STREAM_LOCK.
1271 gst_collect_pads2_check_pads (GstCollectPads2 * pads)
1273 /* the master list and cookie are protected with LOCK */
1274 GST_OBJECT_LOCK (pads);
1275 if (G_UNLIKELY (pads->pad_cookie != pads->cookie)) {
1278 /* clear list and stats */
1279 g_slist_foreach (pads->data, (GFunc) unref_data, NULL);
1280 g_slist_free (pads->data);
1283 pads->queuedpads = 0;
1285 if (pads->earliest_data)
1286 unref_data (pads->earliest_data);
1287 pads->earliest_data = NULL;
1288 pads->earliest_time = GST_CLOCK_TIME_NONE;
1290 /* loop over the master pad list */
1291 collected = pads->pad_list;
1292 for (; collected; collected = g_slist_next (collected)) {
1293 GstCollectData2 *data;
1295 /* update the stats */
1297 data = collected->data;
1298 if (GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_EOS))
1300 else if (data->buffer || !GST_COLLECT_PADS2_STATE_IS_SET (data,
1301 GST_COLLECT_PADS2_STATE_WAITING))
1304 /* add to the list of pads to collect */
1306 /* preserve order of adding/requesting pads */
1307 pads->data = g_slist_append (pads->data, data);
1309 /* and update the cookie */
1310 pads->cookie = pads->pad_cookie;
1312 GST_OBJECT_UNLOCK (pads);
1315 /* checks if all the pads are collected and call the collectfunction
1317 * Should be called with STREAM_LOCK.
1319 * Returns: The #GstFlowReturn of collection.
1321 static GstFlowReturn
1322 gst_collect_pads2_check_collected (GstCollectPads2 * pads)
1324 GstFlowReturn flow_ret = GST_FLOW_OK;
1325 GstCollectPads2Function func;
1328 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), GST_FLOW_ERROR);
1330 GST_OBJECT_LOCK (pads);
1332 user_data = pads->user_data;
1333 GST_OBJECT_UNLOCK (pads);
1335 g_return_val_if_fail (pads->func != NULL, GST_FLOW_NOT_SUPPORTED);
1337 /* check for new pads, update stats etc.. */
1338 gst_collect_pads2_check_pads (pads);
1340 if (G_UNLIKELY (pads->eospads == pads->numpads)) {
1341 /* If all our pads are EOS just collect once to let the element
1342 * do its final EOS handling. */
1343 GST_DEBUG_OBJECT (pads, "All active pads (%d) are EOS, calling %s",
1344 pads->numpads, GST_DEBUG_FUNCPTR_NAME (func));
1346 flow_ret = func (pads, user_data);
1348 gboolean collected = FALSE;
1350 /* We call the collected function as long as our condition matches. */
1351 while (((pads->queuedpads + pads->eospads) >= pads->numpads)) {
1352 GST_DEBUG_OBJECT (pads, "All active pads (%d + %d >= %d) have data, "
1353 "calling %s", pads->queuedpads, pads->eospads, pads->numpads,
1354 GST_DEBUG_FUNCPTR_NAME (func));
1356 flow_ret = func (pads, user_data);
1359 /* break on error */
1360 if (flow_ret != GST_FLOW_OK)
1362 /* Don't keep looping after telling the element EOS or flushing */
1363 if (pads->queuedpads == 0)
1367 GST_DEBUG_OBJECT (pads, "Not all active pads (%d) have data, continuing",
1374 /* General overview:
1375 * - only pad with a buffer can determine earliest_data (and earliest_time)
1376 * - only segment info determines (non-)waiting state
1377 * - ? perhaps use _stream_time for comparison
1378 * (which muxers might have use as well ?)
1382 * Function to recalculate the waiting state of all pads.
1384 * Must be called with STREAM_LOCK.
1386 * Returns TRUE if a pad was set to waiting
1387 * (from non-waiting state).
1390 gst_collect_pads2_recalculate_waiting (GstCollectPads2 * pads)
1393 gboolean result = FALSE;
1395 /* If earliest time is not known, there is nothing to do. */
1396 if (pads->earliest_data == NULL)
1399 for (collected = pads->data; collected; collected = g_slist_next (collected)) {
1400 GstCollectData2 *data = (GstCollectData2 *) collected->data;
1403 /* check if pad has a segment */
1404 if (data->segment.format == GST_FORMAT_UNDEFINED)
1407 /* check segment format */
1408 if (data->segment.format != GST_FORMAT_TIME) {
1409 GST_ERROR_OBJECT (pads, "GstCollectPads2 can handle only time segments.");
1413 /* check if the waiting state should be changed */
1414 cmp_res = pads->compare_func (pads, data, data->segment.start,
1415 pads->earliest_data, pads->earliest_time, pads->compare_user_data);
1418 gst_collect_pads2_set_waiting (pads, data, FALSE);
1420 if (!GST_COLLECT_PADS2_STATE_IS_SET (data,
1421 GST_COLLECT_PADS2_STATE_WAITING)) {
1423 gst_collect_pads2_set_waiting (pads, data, TRUE);
1433 * gst_collect_pads2_find_best_pad:
1434 * @pads: the collectpads to use
1435 * @data: returns the collectdata for earliest data
1436 * @time: returns the earliest available buffertime
1438 * Find the oldest/best pad, i.e. pad holding the oldest buffer and
1439 * and return the corresponding #GstCollectData2 and buffertime.
1441 * This function should be called with STREAM_LOCK held,
1442 * such as in the callback.
1447 gst_collect_pads2_find_best_pad (GstCollectPads2 * pads,
1448 GstCollectData2 ** data, GstClockTime * time)
1451 GstCollectData2 *best = NULL;
1452 GstClockTime best_time = GST_CLOCK_TIME_NONE;
1454 g_return_if_fail (data != NULL);
1455 g_return_if_fail (time != NULL);
1457 for (collected = pads->data; collected; collected = g_slist_next (collected)) {
1459 GstCollectData2 *data = (GstCollectData2 *) collected->data;
1460 GstClockTime timestamp;
1462 buffer = gst_collect_pads2_peek (pads, data);
1463 /* if we have a buffer check if it is better then the current best one */
1464 if (buffer != NULL) {
1465 timestamp = GST_BUFFER_TIMESTAMP (buffer);
1466 gst_buffer_unref (buffer);
1467 if (best == NULL || pads->compare_func (pads, data, timestamp,
1468 best, best_time, pads->compare_user_data) < 0) {
1470 best_time = timestamp;
1475 /* set earliest time */
1479 GST_DEBUG_OBJECT (pads, "best pad %s, best time %" GST_TIME_FORMAT,
1480 best ? GST_PAD_NAME (((GstCollectData2 *) best)->pad) : "(nil)",
1481 GST_TIME_ARGS (best_time));
1485 * Function to recalculate earliest_data and earliest_timestamp. This also calls
1486 * gst_collect_pads2_recalculate_waiting
1488 * Must be called with STREAM_LOCK.
1491 gst_collect_pads2_recalculate_full (GstCollectPads2 * pads)
1493 if (pads->earliest_data)
1494 unref_data (pads->earliest_data);
1495 gst_collect_pads2_find_best_pad (pads, &pads->earliest_data,
1496 &pads->earliest_time);
1497 if (pads->earliest_data)
1498 ref_data (pads->earliest_data);
1499 return gst_collect_pads2_recalculate_waiting (pads);
1503 * Default collect callback triggered when #GstCollectPads2 gathered all data.
1505 * Called with STREAM_LOCK.
1507 static GstFlowReturn
1508 gst_collect_pads2_default_collected (GstCollectPads2 * pads, gpointer user_data)
1510 GstCollectData2 *best = NULL;
1512 GstFlowReturn ret = GST_FLOW_OK;
1513 GstCollectPads2BufferFunction func;
1514 gpointer buffer_user_data;
1516 g_return_val_if_fail (GST_IS_COLLECT_PADS2 (pads), GST_FLOW_ERROR);
1518 GST_OBJECT_LOCK (pads);
1519 func = pads->buffer_func;
1520 buffer_user_data = pads->buffer_user_data;
1521 GST_OBJECT_UNLOCK (pads);
1523 g_return_val_if_fail (func != NULL, GST_FLOW_NOT_SUPPORTED);
1525 /* Find the oldest pad at all cost */
1526 if (gst_collect_pads2_recalculate_full (pads)) {
1527 /* waiting was switched on,
1528 * so give another thread a chance to deliver a possibly
1529 * older buffer; don't charge on yet with the current oldest */
1534 best = pads->earliest_data;
1536 /* No data collected means EOS. */
1537 if (G_UNLIKELY (best == NULL)) {
1538 ret = func (pads, best, NULL, buffer_user_data);
1539 if (ret == GST_FLOW_OK)
1544 /* make sure that the pad we take a buffer from is waiting;
1545 * otherwise popping a buffer will seem not to have happened
1546 * and collectpads can get into a busy loop */
1547 gst_collect_pads2_set_waiting (pads, best, TRUE);
1550 buffer = gst_collect_pads2_pop (pads, best);
1551 ret = func (pads, best, buffer, buffer_user_data);
1553 /* maybe non-waiting was forced to waiting above due to
1554 * newsegment events coming too sparsely,
1555 * so re-check to restore state to avoid hanging/waiting */
1556 gst_collect_pads2_recalculate_full (pads);
1563 * Default timestamp compare function.
1566 gst_collect_pads2_default_compare_func (GstCollectPads2 * pads,
1567 GstCollectData2 * data1, GstClockTime timestamp1,
1568 GstCollectData2 * data2, GstClockTime timestamp2, gpointer user_data)
1571 GST_LOG_OBJECT (pads, "comparing %" GST_TIME_FORMAT
1572 " and %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp1),
1573 GST_TIME_ARGS (timestamp2));
1574 /* non-valid timestamps go first as they are probably headers or so */
1575 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp1)))
1576 return GST_CLOCK_TIME_IS_VALID (timestamp2) ? -1 : 0;
1578 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp2)))
1581 /* compare timestamp */
1582 if (timestamp1 < timestamp2)
1585 if (timestamp1 > timestamp2)
1592 gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event)
1594 gboolean res = FALSE, need_unlock = FALSE;
1595 GstCollectData2 *data;
1596 GstCollectPads2 *pads;
1597 GstCollectPads2EventFunction event_func;
1598 GstCollectPads2BufferFunction buffer_func;
1599 gpointer event_user_data;
1601 /* some magic to get the managing collect_pads2 */
1602 GST_OBJECT_LOCK (pad);
1603 data = (GstCollectData2 *) gst_pad_get_element_private (pad);
1604 if (G_UNLIKELY (data == NULL))
1607 GST_OBJECT_UNLOCK (pad);
1611 pads = data->collect;
1613 GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
1614 GST_DEBUG_PAD_NAME (data->pad));
1616 GST_OBJECT_LOCK (pads);
1617 event_func = pads->event_func;
1618 event_user_data = pads->event_user_data;
1619 buffer_func = pads->buffer_func;
1620 GST_OBJECT_UNLOCK (pads);
1622 switch (GST_EVENT_TYPE (event)) {
1623 case GST_EVENT_FLUSH_START:
1625 /* forward event to unblock check_collected */
1627 res = event_func (pads, data, event, event_user_data);
1629 res = gst_pad_event_default (pad, parent, event);
1631 /* now unblock the chain function.
1632 * no cond per pad, so they all unblock,
1633 * non-flushing block again */
1634 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1635 GST_COLLECT_PADS2_STATE_SET (data, GST_COLLECT_PADS2_STATE_FLUSHING);
1636 gst_collect_pads2_clear (pads, data);
1638 /* cater for possible default muxing functionality */
1640 /* restore to initial state */
1641 gst_collect_pads2_set_waiting (pads, data, TRUE);
1642 /* if the current pad is affected, reset state, recalculate later */
1643 if (pads->earliest_data == data) {
1645 pads->earliest_data = NULL;
1646 pads->earliest_time = GST_CLOCK_TIME_NONE;
1650 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1652 /* event already cleaned up by forwarding */
1656 case GST_EVENT_FLUSH_STOP:
1658 /* flush the 1 buffer queue */
1659 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1660 GST_COLLECT_PADS2_STATE_UNSET (data, GST_COLLECT_PADS2_STATE_FLUSHING);
1661 gst_collect_pads2_clear (pads, data);
1662 /* we need new segment info after the flush */
1663 gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
1664 GST_COLLECT_PADS2_STATE_UNSET (data, GST_COLLECT_PADS2_STATE_NEW_SEGMENT);
1665 /* if the pad was EOS, remove the EOS flag and
1666 * decrement the number of eospads */
1667 if (G_UNLIKELY (GST_COLLECT_PADS2_STATE_IS_SET (data,
1668 GST_COLLECT_PADS2_STATE_EOS))) {
1669 if (!GST_COLLECT_PADS2_STATE_IS_SET (data,
1670 GST_COLLECT_PADS2_STATE_WAITING))
1673 GST_COLLECT_PADS2_STATE_UNSET (data, GST_COLLECT_PADS2_STATE_EOS);
1675 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1678 goto forward_or_default;
1682 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1683 /* if the pad was not EOS, make it EOS and so we
1684 * have one more eospad */
1685 if (G_LIKELY (!GST_COLLECT_PADS2_STATE_IS_SET (data,
1686 GST_COLLECT_PADS2_STATE_EOS))) {
1687 GST_COLLECT_PADS2_STATE_SET (data, GST_COLLECT_PADS2_STATE_EOS);
1688 if (!GST_COLLECT_PADS2_STATE_IS_SET (data,
1689 GST_COLLECT_PADS2_STATE_WAITING))
1693 /* check if we need collecting anything, we ignore the result. */
1694 gst_collect_pads2_check_collected (pads);
1695 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1697 goto forward_or_eat;
1699 case GST_EVENT_SEGMENT:
1704 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1706 gst_event_copy_segment (event, &seg);
1708 GST_DEBUG_OBJECT (data->pad, "got segment %" GST_SEGMENT_FORMAT, &seg);
1710 data->segment = seg;
1711 GST_COLLECT_PADS2_STATE_SET (data, GST_COLLECT_PADS2_STATE_NEW_SEGMENT);
1713 /* default muxing functionality */
1715 goto newsegment_done;
1717 /* default collection can not handle other segment formats than time */
1718 if (seg.format != GST_FORMAT_TIME) {
1719 GST_ERROR_OBJECT (pads, "GstCollectPads2 default collecting "
1720 "can only handle time segments.");
1721 goto newsegment_done;
1724 /* If oldest time is not known, or current pad got newsegment;
1725 * recalculate the state */
1726 if (!pads->earliest_data || pads->earliest_data == data) {
1727 gst_collect_pads2_recalculate_full (pads);
1728 goto newsegment_done;
1731 /* Check if the waiting state of the pad should change. */
1732 cmp_res = pads->compare_func (pads, data, seg.start, pads->earliest_data,
1733 pads->earliest_time, pads->compare_user_data);
1737 gst_collect_pads2_set_waiting (pads, data, FALSE);
1740 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1741 /* we must not forward this event since multiple segments will be
1742 * accumulated and this is certainly not what we want. */
1743 goto forward_or_eat;
1746 /* forward other events */
1747 goto forward_or_default;
1751 if (GST_EVENT_IS_SERIALIZED (event)) {
1752 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1756 res = event_func (pads, data, event, event_user_data);
1758 res = gst_pad_event_default (pad, parent, event);
1760 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1764 if (GST_EVENT_IS_SERIALIZED (event)) {
1765 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1769 res = event_func (pads, data, event, event_user_data);
1771 gst_event_unref (event);
1775 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1785 GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
1786 GST_OBJECT_UNLOCK (pad);
1791 /* For each buffer we receive we check if our collected condition is reached
1792 * and if so we call the collected function. When this is done we check if
1793 * data has been unqueued. If data is still queued we wait holding the stream
1794 * lock to make sure no EOS event can happen while we are ready to be
1797 static GstFlowReturn
1798 gst_collect_pads2_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
1800 GstCollectData2 *data;
1801 GstCollectPads2 *pads;
1803 GstBuffer **buffer_p;
1806 GST_DEBUG ("Got buffer for pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1808 /* some magic to get the managing collect_pads2 */
1809 GST_OBJECT_LOCK (pad);
1810 data = (GstCollectData2 *) gst_pad_get_element_private (pad);
1811 if (G_UNLIKELY (data == NULL))
1814 GST_OBJECT_UNLOCK (pad);
1816 pads = data->collect;
1818 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1819 /* if not started, bail out */
1820 if (G_UNLIKELY (!pads->started))
1822 /* check if this pad is flushing */
1823 if (G_UNLIKELY (GST_COLLECT_PADS2_STATE_IS_SET (data,
1824 GST_COLLECT_PADS2_STATE_FLUSHING)))
1826 /* pad was EOS, we can refuse this data */
1827 if (G_UNLIKELY (GST_COLLECT_PADS2_STATE_IS_SET (data,
1828 GST_COLLECT_PADS2_STATE_EOS)))
1831 /* see if we need to clip */
1832 if (pads->clip_func) {
1833 GstBuffer *outbuf = NULL;
1834 ret = pads->clip_func (pads, data, buffer, &outbuf, pads->clip_user_data);
1837 if (G_UNLIKELY (outbuf == NULL))
1840 if (G_UNLIKELY (ret == GST_FLOW_EOS))
1842 else if (G_UNLIKELY (ret != GST_FLOW_OK))
1846 GST_DEBUG_OBJECT (pads, "Queuing buffer %p for pad %s:%s", buffer,
1847 GST_DEBUG_PAD_NAME (pad));
1849 /* One more pad has data queued */
1850 if (GST_COLLECT_PADS2_STATE_IS_SET (data, GST_COLLECT_PADS2_STATE_WAITING))
1852 buffer_p = &data->buffer;
1853 gst_buffer_replace (buffer_p, buffer);
1855 /* update segment last position if in TIME */
1856 if (G_LIKELY (data->segment.format == GST_FORMAT_TIME)) {
1857 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1859 if (GST_CLOCK_TIME_IS_VALID (timestamp))
1860 data->segment.position = timestamp;
1863 /* While we have data queued on this pad try to collect stuff */
1865 /* Check if our collected condition is matched and call the collected
1866 * function if it is */
1867 ret = gst_collect_pads2_check_collected (pads);
1868 /* when an error occurs, we want to report this back to the caller ASAP
1869 * without having to block if the buffer was not popped */
1870 if (G_UNLIKELY (ret != GST_FLOW_OK))
1873 /* data was consumed, we can exit and accept new data */
1874 if (data->buffer == NULL)
1877 /* Having the _INIT here means we don't care about any broadcast up to here
1878 * (most of which occur with STREAM_LOCK held, so could not have happened
1879 * anyway). We do care about e.g. a remove initiated broadcast as of this
1880 * point. Putting it here also makes this thread ignores any evt it raised
1881 * itself (as is a usual WAIT semantic).
1883 GST_COLLECT_PADS2_EVT_INIT (cookie);
1885 /* pad could be removed and re-added */
1887 GST_OBJECT_LOCK (pad);
1888 if (G_UNLIKELY ((data = gst_pad_get_element_private (pad)) == NULL))
1891 GST_OBJECT_UNLOCK (pad);
1893 GST_DEBUG_OBJECT (pads, "Pad %s:%s has a buffer queued, waiting",
1894 GST_DEBUG_PAD_NAME (pad));
1896 /* wait to be collected, this must happen from another thread triggered
1897 * by the _chain function of another pad. We release the lock so we
1898 * can get stopped or flushed as well. We can however not get EOS
1899 * because we still hold the STREAM_LOCK.
1901 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1902 GST_COLLECT_PADS2_EVT_WAIT (pads, cookie);
1903 GST_COLLECT_PADS2_STREAM_LOCK (pads);
1905 GST_DEBUG_OBJECT (pads, "Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad));
1907 /* after a signal, we could be stopped */
1908 if (G_UNLIKELY (!pads->started))
1910 /* check if this pad is flushing */
1911 if (G_UNLIKELY (GST_COLLECT_PADS2_STATE_IS_SET (data,
1912 GST_COLLECT_PADS2_STATE_FLUSHING)))
1915 while (data->buffer != NULL);
1918 GST_COLLECT_PADS2_STREAM_UNLOCK (pads);
1921 gst_buffer_unref (buffer);
1926 GST_WARNING ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
1927 GST_OBJECT_UNLOCK (pad);
1928 ret = GST_FLOW_NOT_LINKED;
1934 GST_DEBUG ("%s got removed from collectpads", GST_OBJECT_NAME (pad));
1935 GST_OBJECT_UNLOCK (pad);
1936 gst_buffer_unref (buffer);
1937 return GST_FLOW_NOT_LINKED;
1941 GST_DEBUG ("not started");
1942 gst_collect_pads2_clear (pads, data);
1943 ret = GST_FLOW_WRONG_STATE;
1948 GST_DEBUG ("pad %s:%s is flushing", GST_DEBUG_PAD_NAME (pad));
1949 gst_collect_pads2_clear (pads, data);
1950 ret = GST_FLOW_WRONG_STATE;
1955 /* we should not post an error for this, just inform upstream that
1956 * we don't expect anything anymore */
1957 GST_DEBUG ("pad %s:%s is eos", GST_DEBUG_PAD_NAME (pad));
1963 GST_DEBUG ("clipped buffer on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1969 /* we print the error, the element should post a reasonable error
1970 * message for fatal errors */
1971 GST_DEBUG ("collect failed, reason %d (%s)", ret, gst_flow_get_name (ret));
1972 gst_collect_pads2_clear (pads, data);