X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libs%2Fgst%2Fbase%2Fgstcollectpads.c;h=16a239b5d34b1dedf6978ba6bcdf3e206342af4f;hb=a87b4551a6090663a1714f263d4e20fe75eb46ca;hp=c82b0d46ff9ee3b29df3b95c6c4dcee41dc764eb;hpb=b40fa2b8c3485a8374186ca047622ab518e09485;p=platform%2Fupstream%2Fgstreamer.git diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c index c82b0d4..16a239b 100644 --- a/libs/gst/base/gstcollectpads.c +++ b/libs/gst/base/gstcollectpads.c @@ -22,57 +22,47 @@ */ /** * SECTION:gstcollectpads + * @title: GstCollectPads * @short_description: manages a set of pads that operate in collect mode * @see_also: * * Manages a set of pads that operate in collect mode. This means that control * is given to the manager of this object when all pads have data. - * - * - * Collectpads are created with gst_collect_pads_new(). A callback should then + * + * * Collectpads are created with gst_collect_pads_new(). A callback should then * be installed with gst_collect_pads_set_function (). - * - * - * Pads are added to the collection with gst_collect_pads_add_pad()/ + * + * * Pads are added to the collection with gst_collect_pads_add_pad()/ * gst_collect_pads_remove_pad(). The pad * has to be a sinkpad. The chain and event functions of the pad are * overridden. The element_private of the pad is used to store * private information for the collectpads. - * - * - * For each pad, data is queued in the _chain function or by + * + * * For each pad, data is queued in the _chain function or by * performing a pull_range. - * - * - * When data is queued on all pads in waiting mode, the callback function is called. - * - * - * Data can be dequeued from the pad with the gst_collect_pads_pop() method. + * + * * When data is queued on all pads in waiting mode, the callback function is called. + * + * * Data can be dequeued from the pad with the gst_collect_pads_pop() method. * One can peek at the data with the gst_collect_pads_peek() function. - * These functions will return NULL if the pad received an EOS event. When all - * pads return NULL from a gst_collect_pads_peek(), the element can emit an EOS + * These functions will return %NULL if the pad received an EOS event. When all + * pads return %NULL from a gst_collect_pads_peek(), the element can emit an EOS * event itself. - * - * - * Data can also be dequeued in byte units using the gst_collect_pads_available(), + * + * * Data can also be dequeued in byte units using the gst_collect_pads_available(), * gst_collect_pads_read_buffer() and gst_collect_pads_flush() calls. - * - * - * Elements should call gst_collect_pads_start() and gst_collect_pads_stop() in + * + * * Elements should call gst_collect_pads_start() and gst_collect_pads_stop() in * their state change functions to start and stop the processing of the collectpads. * The gst_collect_pads_stop() call should be called before calling the parent * element state change function in the PAUSED_TO_READY state change to ensure * no pad is blocked and the element can finish streaming. - * - * - * gst_collect_pads_set_waiting() sets a pad to waiting or non-waiting mode. + * + * * gst_collect_pads_set_waiting() sets a pad to waiting or non-waiting mode. * CollectPads element is not waiting for data to be collected on non-waiting pads. * Thus these pads may but need not have data when the callback is called. * All pads are in waiting mode by default. - * - * * - * Last reviewed on 2011-10-28 (0.10.36) */ #ifdef HAVE_CONFIG_H @@ -265,6 +255,9 @@ gst_collect_pads_init (GstCollectPads * pads) pads->priv->seeking = FALSE; pads->priv->pending_flush_start = FALSE; pads->priv->pending_flush_stop = FALSE; + + /* clear floating flag */ + gst_object_ref_sink (pads); } static void @@ -295,7 +288,7 @@ gst_collect_pads_finalize (GObject * object) * * MT safe. * - * Returns: (transfer full): a new #GstCollectPads, or NULL in case of an error. + * Returns: (transfer full): a new #GstCollectPads, or %NULL in case of an error. */ GstCollectPads * gst_collect_pads_new (void) @@ -319,11 +312,11 @@ gst_collect_pads_set_buffer_function_locked (GstCollectPads * pads, /** * gst_collect_pads_set_buffer_function: * @pads: the collectpads to use - * @func: the function to set + * @func: (scope call): the function to set * @user_data: (closure): user data passed to the function * * Set the callback function and user data that will be called with - * the oldest buffer when all pads have been collected, or NULL on EOS. + * the oldest buffer when all pads have been collected, or %NULL on EOS. * If a buffer is passed, the callback owns a reference and must unref * it. * @@ -344,7 +337,7 @@ gst_collect_pads_set_buffer_function (GstCollectPads * pads, /** * gst_collect_pads_set_compare_function: * @pads: the pads to use - * @func: the function to set + * @func: (scope call): the function to set * @user_data: (closure): user data passed to the function * * Set the timestamp comparison function. @@ -371,7 +364,7 @@ gst_collect_pads_set_compare_function (GstCollectPads * pads, /** * gst_collect_pads_set_function: * @pads: the collectpads to use - * @func: the function to set + * @func: (scope call): the function to set * @user_data: user data passed to the function * * CollectPads provides a default collection algorithm that will determine @@ -431,7 +424,7 @@ unref_data (GstCollectData * data) /** * gst_collect_pads_set_event_function: * @pads: the collectpads to use - * @func: the function to set + * @func: (scope call): the function to set * @user_data: user data passed to the function * * Set the event callback function and user data that will be called when @@ -459,7 +452,7 @@ gst_collect_pads_set_event_function (GstCollectPads * pads, /** * gst_collect_pads_set_query_function: * @pads: the collectpads to use - * @func: the function to set + * @func: (scope call): the function to set * @user_data: user data passed to the function * * Set the query callback function and user data that will be called after @@ -494,33 +487,61 @@ gst_collect_pads_set_query_function (GstCollectPads * pads, * * Convenience clipping function that converts incoming buffer's timestamp * to running time, or clips the buffer if outside configured segment. +* +* Since 1.6, this clipping function also sets the DTS parameter of the +* GstCollectData structure. This version of the running time DTS can be +* negative. G_MININT64 is used to indicate invalid value. */ GstFlowReturn gst_collect_pads_clip_running_time (GstCollectPads * pads, GstCollectData * cdata, GstBuffer * buf, GstBuffer ** outbuf, gpointer user_data) { - GstClockTime time; - *outbuf = buf; - time = GST_BUFFER_PTS (buf); /* invalid left alone and passed */ - if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) { - time = gst_segment_to_running_time (&cdata->segment, GST_FORMAT_TIME, time); - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) { - GST_DEBUG_OBJECT (cdata->pad, "clipping buffer on pad outside segment"); - gst_buffer_unref (buf); - *outbuf = NULL; + if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS_OR_PTS (buf)))) { + GstClockTime time; + GstClockTime buf_dts, abs_dts; + gint dts_sign; + + time = GST_BUFFER_PTS (buf); + + if (GST_CLOCK_TIME_IS_VALID (time)) { + time = + gst_segment_to_running_time (&cdata->segment, GST_FORMAT_TIME, time); + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) { + GST_DEBUG_OBJECT (cdata->pad, "clipping buffer on pad outside segment %" + GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); + gst_buffer_unref (buf); + *outbuf = NULL; + return GST_FLOW_OK; + } + } + + GST_LOG_OBJECT (cdata->pad, "buffer pts %" GST_TIME_FORMAT " -> %" + GST_TIME_FORMAT " running time", + GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time)); + *outbuf = gst_buffer_make_writable (buf); + GST_BUFFER_PTS (*outbuf) = time; + + dts_sign = gst_segment_to_running_time_full (&cdata->segment, + GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf), &abs_dts); + buf_dts = GST_BUFFER_DTS (*outbuf); + if (dts_sign > 0) { + GST_BUFFER_DTS (*outbuf) = abs_dts; + GST_COLLECT_PADS_DTS (cdata) = abs_dts; + } else if (dts_sign < 0) { + GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE; + GST_COLLECT_PADS_DTS (cdata) = -((gint64) abs_dts); } else { - GST_LOG_OBJECT (cdata->pad, "buffer ts %" GST_TIME_FORMAT " -> %" - GST_TIME_FORMAT " running time", - GST_TIME_ARGS (GST_BUFFER_PTS (buf)), GST_TIME_ARGS (time)); - *outbuf = gst_buffer_make_writable (buf); - GST_BUFFER_PTS (*outbuf) = time; - GST_BUFFER_DTS (*outbuf) = gst_segment_to_running_time (&cdata->segment, - GST_FORMAT_TIME, GST_BUFFER_DTS (*outbuf)); + GST_BUFFER_DTS (*outbuf) = GST_CLOCK_TIME_NONE; + GST_COLLECT_PADS_DTS (cdata) = GST_CLOCK_STIME_NONE; } + + GST_LOG_OBJECT (cdata->pad, "buffer dts %" GST_TIME_FORMAT " -> %" + GST_STIME_FORMAT " running time", GST_TIME_ARGS (buf_dts), + GST_STIME_ARGS (GST_COLLECT_PADS_DTS (cdata))); } return GST_FLOW_OK; @@ -529,7 +550,7 @@ gst_collect_pads_clip_running_time (GstCollectPads * pads, /** * gst_collect_pads_set_clip_function: * @pads: the collectpads to use - * @clipfunc: clip function to install + * @clipfunc: (scope call): clip function to install * @user_data: user data to pass to @clip_func * * Install a clipping function that is called right after a buffer is received @@ -549,7 +570,7 @@ gst_collect_pads_set_clip_function (GstCollectPads * pads, /** * gst_collect_pads_set_flush_function: * @pads: the collectpads to use - * @func: flush function to install + * @func: (scope call): flush function to install * @user_data: user data to pass to @func * * Install a flush function that is called when the internal @@ -574,8 +595,8 @@ gst_collect_pads_set_flush_function (GstCollectPads * pads, * @pads: the collectpads to use * @pad: (transfer none): the pad to add * @size: the size of the returned #GstCollectData structure - * @destroy_notify: function to be called before the returned #GstCollectData - * structure is freed + * @destroy_notify: (scope async): function to be called before the returned + * #GstCollectData structure is freed * @lock: whether to lock this pad in usual waiting state * * Add a pad to the collection of collect pads. The pad has to be @@ -604,8 +625,8 @@ gst_collect_pads_set_flush_function (GstCollectPads * pads, * * MT safe. * - * Returns: a new #GstCollectData to identify the new pad. Or NULL - * if wrong parameters are supplied. + * Returns: (nullable) (transfer none): a new #GstCollectData to identify the + * new pad. Or %NULL if wrong parameters are supplied. */ GstCollectData * gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size, @@ -632,6 +653,7 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size, data->state |= lock ? GST_COLLECT_PADS_STATE_LOCKED : 0; data->priv->refcount = 1; data->priv->destroy_notify = destroy_notify; + data->ABI.abi.dts = G_MININT64; GST_OBJECT_LOCK (pads); GST_OBJECT_LOCK (pad); @@ -922,8 +944,8 @@ gst_collect_pads_stop (GstCollectPads * pads) * * MT safe. * - * Returns: The buffer in @data or NULL if no buffer is queued. - * should unref the buffer after usage. + * Returns: (transfer full) (nullable): The buffer in @data or %NULL if no + * buffer is queued. should unref the buffer after usage. */ GstBuffer * gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data) @@ -937,7 +959,7 @@ gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data) if ((result = data->buffer)) gst_buffer_ref (result); - GST_DEBUG_OBJECT (pads, "Peeking at pad %s:%s: buffer=%p", + GST_DEBUG_OBJECT (pads, "Peeking at pad %s:%s: buffer=%" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (data->pad), result); return result; @@ -954,8 +976,8 @@ gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data) * * MT safe. * - * Returns: (transfer full): The buffer in @data or NULL if no buffer was - * queued. You should unref the buffer after usage. + * Returns: (transfer full) (nullable): The buffer in @data or %NULL if no + * buffer was queued. You should unref the buffer after usage. */ GstBuffer * gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data) @@ -976,7 +998,7 @@ gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data) GST_COLLECT_PADS_EVT_BROADCAST (pads); - GST_DEBUG_OBJECT (pads, "Pop buffer on pad %s:%s: buffer=%p", + GST_DEBUG_OBJECT (pads, "Pop buffer on pad %s:%s: buffer=%" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (data->pad), result); return result; @@ -1121,15 +1143,15 @@ gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data, * * MT safe. * - * Returns: (transfer full): A sub buffer. The size of the buffer can be less that requested. - * A return of NULL signals that the pad is end-of-stream. - * Unref the buffer after use. + * Returns: (transfer full) (nullable): A sub buffer. The size of the buffer can + * be less that requested. A return of %NULL signals that the pad is + * end-of-stream. Unref the buffer after use. */ GstBuffer * gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data, guint size) { - guint readsize; + guint readsize, buf_size; GstBuffer *buffer; g_return_val_if_fail (pads != NULL, NULL); @@ -1140,7 +1162,8 @@ gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data, if ((buffer = data->buffer) == NULL) return NULL; - readsize = MIN (size, gst_buffer_get_size (buffer) - data->pos); + buf_size = gst_buffer_get_size (buffer); + readsize = MIN (size, buf_size - data->pos); return gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, data->pos, readsize); @@ -1160,9 +1183,9 @@ gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data, * * MT safe. * - * Returns: A sub buffer. The size of the buffer can be less that requested. - * A return of NULL signals that the pad is end-of-stream. - * Unref the buffer after use. + * Returns: (transfer full) (nullable): A sub buffer. The size of the buffer can + * be less that requested. A return of %NULL signals that the pad is + * end-of-stream. Unref the buffer after use. */ GstBuffer * gst_collect_pads_take_buffer (GstCollectPads * pads, GstCollectData * data, @@ -1313,7 +1336,7 @@ gst_collect_pads_check_collected (GstCollectPads * pads) pads->priv->numpads, GST_DEBUG_FUNCPTR_NAME (func)); if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking, - TRUE, FALSE) == TRUE)) { + TRUE, FALSE))) { GST_INFO_OBJECT (pads, "finished seeking"); } do { @@ -1331,7 +1354,7 @@ gst_collect_pads_check_collected (GstCollectPads * pads) GST_DEBUG_FUNCPTR_NAME (func)); if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking, - TRUE, FALSE) == TRUE)) { + TRUE, FALSE))) { GST_INFO_OBJECT (pads, "finished seeking"); } flow_ret = func (pads, user_data); @@ -1364,7 +1387,7 @@ gst_collect_pads_check_collected (GstCollectPads * pads) * * Must be called with STREAM_LOCK. * - * Returns TRUE if a pad was set to waiting + * Returns %TRUE if a pad was set to waiting * (from non-waiting state). */ static gboolean @@ -1447,10 +1470,7 @@ gst_collect_pads_find_best_pad (GstCollectPads * pads, buffer = gst_collect_pads_peek (pads, data); /* if we have a buffer check if it is better then the current best one */ if (buffer != NULL) { - timestamp = GST_BUFFER_DTS (buffer); - if (!GST_CLOCK_TIME_IS_VALID (timestamp)) { - timestamp = GST_BUFFER_PTS (buffer); - } + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); gst_buffer_unref (buffer); if (best == NULL || pads->priv->compare_func (pads, data, timestamp, best, best_time, pads->priv->compare_user_data) < 0) { @@ -1615,7 +1635,7 @@ gst_collect_pads_clip_time (GstCollectPads * pads, GstCollectData * data, if (pads->priv->clip_func) { in = gst_buffer_new (); GST_BUFFER_PTS (in) = time; - GST_BUFFER_DTS (in) = time; + GST_BUFFER_DTS (in) = GST_CLOCK_TIME_NONE; pads->priv->clip_func (pads, data, in, &out, pads->priv->clip_user_data); if (out) { otime = GST_BUFFER_PTS (out); @@ -1637,7 +1657,7 @@ gst_collect_pads_clip_time (GstCollectPads * pads, GstCollectData * data, * @event: event being processed * @discard: process but do not send event downstream * - * Default GstCollectPads event handling that elements should always + * Default #GstCollectPads event handling that elements should always * chain up to to ensure proper operation. Element might however indicate * event should not be forwarded downstream. */ @@ -1662,8 +1682,8 @@ gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data, { if (g_atomic_int_get (&pads->priv->seeking)) { /* drop all but the first FLUSH_STARTs when seeking */ - if (g_atomic_int_compare_and_exchange (&pads->priv->pending_flush_start, - TRUE, FALSE) == FALSE) + if (!g_atomic_int_compare_and_exchange (&pads-> + priv->pending_flush_start, TRUE, FALSE)) goto eat; /* unblock collect pads */ @@ -1730,7 +1750,9 @@ gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data, if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING)) pads->priv->queuedpads++; - pads->priv->eospads--; + if (!g_atomic_int_get (&pads->priv->seeking)) { + pads->priv->eospads--; + } GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_EOS); } GST_COLLECT_PADS_STREAM_UNLOCK (pads); @@ -1786,7 +1808,8 @@ gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data, GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_NEW_SEGMENT); /* now we can use for e.g. running time */ - seg.position = gst_collect_pads_clip_time (pads, data, seg.start); + seg.position = + gst_collect_pads_clip_time (pads, data, seg.start + seg.offset); /* update again */ data->segment = seg; @@ -1809,6 +1832,7 @@ gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data, GST_COLLECT_PADS_STREAM_LOCK (pads); gst_event_parse_gap (event, &start, &duration); + /* FIXME, handle reverse playback case */ if (GST_CLOCK_TIME_IS_VALID (duration)) start += duration; /* we do not expect another buffer until after gap, @@ -1853,8 +1877,15 @@ typedef struct static gboolean event_forward_func (GstPad * pad, EventData * data) { - data->result &= gst_pad_push_event (pad, gst_event_ref (data->event)); + gboolean ret = TRUE; + GstPad *peer = gst_pad_get_peer (pad); + + if (peer) { + ret = gst_pad_send_event (peer, gst_event_ref (data->event)); + gst_object_unref (peer); + } + data->result &= ret; /* Always send to all pads */ return FALSE; } @@ -1876,13 +1907,13 @@ forward_event_to_all_sinkpads (GstPad * srcpad, GstEvent * event) /** * gst_collect_pads_src_event_default: - * @pads: the collectpads to use + * @pads: the #GstCollectPads to use * @pad: src #GstPad that received the event * @event: event being processed * - * Default GstCollectPads event handling for the src pad of elements. + * Default #GstCollectPads event handling for the src pad of elements. * Elements can chain up to this to let flushing seek event handling - * be done by GstCollectPads. + * be done by #GstCollectPads. * * Since: 1.4 */ @@ -1899,6 +1930,8 @@ gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad, case GST_EVENT_SEEK:{ GstSeekFlags flags; + pads->priv->eospads = 0; + GST_INFO_OBJECT (pads, "starting seek"); gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); @@ -1995,7 +2028,7 @@ pad_removed: * @query: query being processed * @discard: process but do not send event downstream * - * Default GstCollectPads query handling that elements should always + * Default #GstCollectPads query handling that elements should always * chain up to to ensure proper operation. Element might however indicate * query should not be forwarded downstream. */ @@ -2096,7 +2129,7 @@ pad_removed: * and if so we call the collected function. When this is done we check if * data has been unqueued. If data is still queued we wait holding the stream * lock to make sure no EOS event can happen while we are ready to be - * collected + * collected */ static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) @@ -2162,9 +2195,7 @@ gst_collect_pads_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) if (G_LIKELY (data->segment.format == GST_FORMAT_TIME)) { GstClockTime timestamp; - timestamp = GST_BUFFER_DTS (buffer); - if (!GST_CLOCK_TIME_IS_VALID (timestamp)) - timestamp = GST_BUFFER_PTS (buffer); + timestamp = GST_BUFFER_DTS_OR_PTS (buffer); if (GST_CLOCK_TIME_IS_VALID (timestamp)) data->segment.position = timestamp;