From: Sebastian Dröge Date: Thu, 8 Sep 2011 12:23:50 +0000 (+0200) Subject: Merge branch 'master' into 0.11 X-Git-Tag: RELEASE-0.11.1~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=43538e2e75b4bdc5fc71a62b472a4b223472c059;p=platform%2Fupstream%2Fgstreamer.git Merge branch 'master' into 0.11 Conflicts: docs/design/draft-buffer2.txt docs/design/part-TODO.txt docs/design/part-block.txt docs/design/part-bufferlist.txt docs/design/part-caps.txt docs/design/part-element-transform.txt docs/design/part-events.txt docs/design/part-negotiation.txt gst/gstcaps.c gst/gstevent.h gst/gstghostpad.c gst/gstinterface.c gst/gstpad.c gst/gstpad.h gst/gstutils.c libs/gst/base/gstbasesink.c libs/gst/base/gstbasesrc.c libs/gst/base/gstbasetransform.c libs/gst/base/gsttypefindhelper.c plugins/elements/gstcapsfilter.c plugins/elements/gsttee.c tests/check/generic/sinks.c tools/gst-launch.1.in --- 43538e2e75b4bdc5fc71a62b472a4b223472c059 diff --cc docs/design/part-TODO.txt index 6b9e2a47db,00524b7a60..9cb8f0cff1 --- a/docs/design/part-TODO.txt +++ b/docs/design/part-TODO.txt @@@ -26,9 -27,8 +26,10 @@@ API/AB - Optimize negotiation. We currently do a get_caps() call when we link pads, which could potentially generate a huge list of caps and all their combinations, we need to avoid generating these huge lists by generating them - incrementaly when needed. We can do this with a gst_pad_iterate_caps() call. + We also need to incrementally return intersections etc, for this. somewhat + incrementally when needed. We can do this with a gst_pad_iterate_caps() call. + We also need to incrementally return intersections etc, for this. + FIXED in 0.11 with a filter on getcaps functions. - Elements in a bin have no clue about the final state of the parent element since the bin sets the target state on its children in small steps. This diff --cc docs/design/part-block.txt index 8d2508d674,854951dc9e..deaedbfac8 --- a/docs/design/part-block.txt +++ b/docs/design/part-block.txt @@@ -156,3 -156,20 +156,4 @@@ as well, so that there is a generic met The same flow works as well for any chain of multiple elements and might be implemented with a helper function in the future. + - -Issues -~~~~~~ - -When an EOS event has passed a pad and the pad is set to blocked, the block will -never happen because no data is going to flow anymore. One possibility is to -keep track of the pad's EOS state and make the block succeed immediately. This is -not yet implemenented. - -When dynamically reconnecting pads, some events (like NEWSEGMENT, EOS, -TAGS, ...) are not yet retransmitted to the newly connected element. It's -unclear if this can be done by core automatically by caching those events and -resending them on a relink. It might also be possible that this needs a -GstFlowReturn value from the event function, in which case the implementation -must be delayed for after 0.11, when we can break API/ABI. - diff --cc docs/design/part-caps.txt index ee4b5aa5a0,3df28ba350..ac04b757b6 --- a/docs/design/part-caps.txt +++ b/docs/design/part-caps.txt @@@ -12,6 -12,9 +12,6 @@@ Caps are exposed on the element pads us This function describes the possible types that the pad can handle or produce (see part-pads.txt and part-negotiation.txt). - Various methods exist to work with the media types such as substracting -Caps are also attached to buffers to describe to content of the data -pointed to be the buffer. - + Various methods exist to work with the media types such as subtracting or intersecting. diff --cc docs/design/part-element-transform.txt index 73f18bf560,aecd5fbd66..e3c11b86f2 --- a/docs/design/part-element-transform.txt +++ b/docs/design/part-element-transform.txt @@@ -253,11 -266,12 +253,11 @@@ state. We can identify these steady sta input buffer is transformed into the output buffer. The flow is exactly the same as the case with the same-caps negotiation. (DCC) - We can immeditatly observe that the copy transform states will need to + We can immediately observe that the copy transform states will need to -allocate a buffer from a downstream element using pad-alloc. When the transform -element is receiving a non-writable buffer in the in-place state, it will also -need to perform a pad-alloc. There is no reason why the passthrough state would -perform a pad-alloc. This is important because upstream re-negotiation can only -happen when the transform uses pad-alloc for all outgoing buffers. +allocate a new buffer from the bufferpool. When the transform element is +receiving a non-writable buffer in the in-place state, it will also +need to perform an allocation. There is no reason why the passthrough state would +perform an allocation. This steady state changes when one of the following actions occur: diff --cc docs/design/part-events.txt index 78f15c1149,b79ed050a6..319369823d --- a/docs/design/part-events.txt +++ b/docs/design/part-events.txt @@@ -156,20 -115,20 +156,20 @@@ also contains the playback speed and th Since the stream time is always set to 0 at start and after a seek, a 0 point for all next buffer's timestamps has to be propagated through the -pipeline using the NEWSEGMENT event. +pipeline using the SEGMENT event. -Before sending buffers, an element must send a NEWSEGMENT event. An element is -free to refuse buffers if they were not preceeded by a NEWSEGMENT event. +Before sending buffers, an element must send a SEGMENT event. An element is +free to refuse buffers if they were not preceeded by a SEGMENT event. -Elements that sync to the clock should store the NEWSEGMENT start and end values +Elements that sync to the clock should store the SEGMENT start and end values - and substract the start value from the buffer timestamp before comparing + and subtract the start value from the buffer timestamp before comparing it against the stream time (see part-clocks.txt). -An element is allowed to send out buffers with the NEWSEGMENT start time already +An element is allowed to send out buffers with the SEGMENT start time already - substracted from the timestamp. If it does so, it needs to send a corrected + subtracted from the timestamp. If it does so, it needs to send a corrected -NEWSEGMENT downstream, ie, one with start time 0. +SEGMENT downstream, ie, one with start time 0. -A NEWSEGMENT event should be generated as soon as possible in the pipeline and +A SEGMENT event should be generated as soon as possible in the pipeline and is usually generated by a demuxer or source. The event is generated before pushing the first buffer and after a seek, right before pushing the new buffer. diff --cc gst/gstpad.c index f489b77f3c,eaeddea964..b01c483d0a --- a/gst/gstpad.c +++ b/gst/gstpad.c @@@ -2589,21 -2598,41 +2589,41 @@@ gst_pad_accept_caps (GstPad * pad, GstC if (caps == existing || gst_caps_is_equal (caps, existing)) goto is_same_caps; } - acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad); GST_OBJECT_UNLOCK (pad); +#endif + acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad); - if (G_LIKELY (acceptfunc)) { - /* we can call the function */ - result = acceptfunc (pad, caps); - GST_DEBUG_OBJECT (pad, "acceptfunc returned %d", result); - } else { - /* Only null if the element explicitly unset it */ - result = gst_pad_acceptcaps_default (pad, caps); - GST_DEBUG_OBJECT (pad, "default acceptcaps returned %d", result); - } + /* Only null if the element explicitly unset it */ + if (G_UNLIKELY (acceptfunc == NULL)) + goto no_func; + + /* we can call the function */ + result = acceptfunc (pad, caps); + GST_DEBUG_OBJECT (pad, "acceptfunc returned %d", result); + #ifndef G_DISABLE_ASSERT + { + GstCaps *padcaps; + + padcaps = gst_pad_get_caps_reffed (pad); + if (!gst_caps_is_subset (caps, padcaps)) { + gchar *padcaps_str, *caps_str; + + padcaps_str = gst_caps_to_string (padcaps); + caps_str = gst_caps_to_string (caps); + g_warning ("pad %s:%s accepted caps %s although " + "they are not a subset of its caps %s", + GST_DEBUG_PAD_NAME (pad), caps_str, padcaps_str); + g_free (padcaps_str); + g_free (caps_str); + } + gst_caps_unref (padcaps); + } + #endif + return result; +#if 0 is_same_caps: { GST_DEBUG_OBJECT (pad, "pad had same caps"); @@@ -2680,70 -2703,74 +2700,69 @@@ no_peer gboolean gst_pad_set_caps (GstPad * pad, GstCaps * caps) { - GstPadSetCapsFunction setcaps; - GstCaps *existing; + GstEvent *event; + gboolean res = TRUE; g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (caps == NULL || gst_caps_is_fixed (caps), FALSE); + g_return_val_if_fail (caps != NULL && gst_caps_is_fixed (caps), FALSE); - GST_OBJECT_LOCK (pad); - existing = GST_PAD_CAPS (pad); - if (existing == caps) - goto was_ok; + event = gst_event_new_caps (caps); - if (gst_caps_is_equal (caps, existing)) - goto setting_same_caps; + if (GST_PAD_IS_SRC (pad)) + res = gst_pad_push_event (pad, event); + else + res = gst_pad_send_event (pad, event); - setcaps = GST_PAD_SETCAPSFUNC (pad); + return res; +} - /* call setcaps function to configure the pad only if the - * caps is not NULL */ - if (setcaps != NULL && caps) { - if (!GST_PAD_IS_IN_SETCAPS (pad)) { - GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_SETCAPS); - GST_OBJECT_UNLOCK (pad); - if (!setcaps (pad, caps)) - goto could_not_set; - GST_OBJECT_LOCK (pad); - GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS); - } else { - GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad was dispatching"); +static gboolean +do_event_function (GstPad * pad, GstEvent * event, + GstPadEventFunction eventfunc, gboolean * caps_notify) +{ + gboolean result = TRUE, call_event = TRUE; - GstCaps *caps, *templ, *old; ++ GstCaps *caps, *old, *templ; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + { + /* backwards compatibility mode for caps */ + gst_event_parse_caps (event, &caps); + + /* See if pad accepts the caps */ + templ = gst_pad_get_pad_template_caps (pad); + if (!gst_caps_can_intersect (caps, templ)) + goto not_accepted; + + /* check if it changed */ + if ((old = gst_pad_get_current_caps (pad))) { + call_event = !gst_caps_is_equal (caps, old); + gst_caps_unref (old); + } + if (call_event) + *caps_notify = TRUE; - + gst_caps_unref (templ); + break; } + default: + break; } - gst_caps_replace (&GST_PAD_CAPS (pad), caps); - GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "caps %p %" GST_PTR_FORMAT, caps, - caps); - GST_OBJECT_UNLOCK (pad); - -#if GLIB_CHECK_VERSION(2,26,0) - g_object_notify_by_pspec ((GObject *) pad, pspec_caps); -#else - g_object_notify ((GObject *) pad, "caps"); -#endif - - return TRUE; - -was_ok: - { - GST_OBJECT_UNLOCK (pad); - return TRUE; - } -setting_same_caps: - { - gst_caps_replace (&GST_PAD_CAPS (pad), caps); - GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, - "caps %p %" GST_PTR_FORMAT " same as existing, updating ptr only", caps, - caps); - GST_OBJECT_UNLOCK (pad); - return TRUE; + if (call_event) { + GST_DEBUG_OBJECT (pad, "calling event function with event %p", event); + result = eventfunc (pad, event); + } else { + gst_event_unref (event); } + return result; /* ERRORS */ -could_not_set: +not_accepted: { - GST_OBJECT_LOCK (pad); - GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS); + gst_caps_unref (templ); + gst_event_unref (event); GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, - "caps %" GST_PTR_FORMAT " could not be set", caps); - GST_OBJECT_UNLOCK (pad); - + "caps %" GST_PTR_FORMAT " not accepted", caps); return FALSE; } } @@@ -3120,17 -3631,13 +3139,17 @@@ event_forward_func (GstPad * pad, Event * @pad: a #GstPad to call the default event handler on. * @event: (transfer full): the #GstEvent to handle. * - * Invokes the default event handler for the given pad. End-of-stream and - * discontinuity events are handled specially, and then the event is sent to all - * pads internally linked to @pad. Note that if there are many possible sink - * pads that are internally linked to @pad, only one will be sent an event. - * Multi-sinkpad elements should implement custom event handlers. + * Invokes the default event handler for the given pad. + * + * The EOS event will pause the task associated with @pad before it is forwarded + * to all internally linked pads, + * + * The CAPS event will never be forwarded. + * + * The the event is sent to all pads internally linked to @pad. This function + * takes ownership of @event. * - * Returns: TRUE if the event was sent succesfully. + * Returns: TRUE if the event was sent successfully. */ gboolean gst_pad_event_default (GstPad * pad, GstEvent * event) diff --cc gst/gstsegment.h index 43f3f1782b,a0c3683202..67a6d503ac --- a/gst/gstsegment.h +++ b/gst/gstsegment.h @@@ -31,98 -32,12 +31,98 @@@ G_BEGIN_DECL typedef struct _GstSegment GstSegment; +/** + * GstSeekType: + * @GST_SEEK_TYPE_NONE: no change in position is required + * @GST_SEEK_TYPE_CUR: change relative to currently configured segment. This + * can't be used to seek relative to the current playback position - do a + * position query, calculate the desired position and then do an absolute + * position seek instead if that's what you want to do. + * @GST_SEEK_TYPE_SET: absolute position is requested + * @GST_SEEK_TYPE_END: relative position to duration is requested + * + * The different types of seek events. When constructing a seek event with + * gst_event_new_seek() or when doing gst_segment_do_seek (). + */ +typedef enum { + /* one of these */ + GST_SEEK_TYPE_NONE = 0, + GST_SEEK_TYPE_CUR = 1, + GST_SEEK_TYPE_SET = 2, + GST_SEEK_TYPE_END = 3 +} GstSeekType; + +/** + * GstSeekFlags: + * @GST_SEEK_FLAG_NONE: no flag + * @GST_SEEK_FLAG_FLUSH: flush pipeline + * @GST_SEEK_FLAG_ACCURATE: accurate position is requested, this might + * be considerably slower for some formats. + * @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be + * faster but less accurate. + * @GST_SEEK_FLAG_SEGMENT: perform a segment seek. + * @GST_SEEK_FLAG_SKIP: when doing fast foward or fast reverse playback, allow + * elements to skip frames instead of generating all + * frames. Since 0.10.22. + * + * Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags + * can be used together. + * + * A non flushing seek might take some time to perform as the currently + * playing data in the pipeline will not be cleared. + * + * An accurate seek might be slower for formats that don't have any indexes + * or timestamp markers in the stream. Specifying this flag might require a + * complete scan of the file in those cases. + * + * When performing a segment seek: after the playback of the segment completes, + * no EOS will be emmited by the element that performed the seek, but a + * #GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element. + * When this message is posted, it is possible to send a new seek event to - * continue playback. With this seek method it is possible to perform seemless ++ * continue playback. With this seek method it is possible to perform seamless + * looping or simple linear editing. + * + * When doing fast forward (rate > 1.0) or fast reverse (rate < -1.0) trickmode + * playback, the @GST_SEEK_FLAG_SKIP flag can be used to instruct decoders + * and demuxers to adjust the playback rate by skipping frames. This can improve + * performance and decrease CPU usage because not all frames need to be decoded. + * + * Also see part-seeking.txt in the GStreamer design documentation for more + * details on the meaning of these flags and the behaviour expected of + * elements that handle them. + */ +typedef enum { + GST_SEEK_FLAG_NONE = 0, + GST_SEEK_FLAG_FLUSH = (1 << 0), + GST_SEEK_FLAG_ACCURATE = (1 << 1), + GST_SEEK_FLAG_KEY_UNIT = (1 << 2), + GST_SEEK_FLAG_SEGMENT = (1 << 3), + GST_SEEK_FLAG_SKIP = (1 << 4) +} GstSeekFlags; + +/** + * GstSegmentFlags: + * @GST_SEGMENT_FLAG_NONE: no flags + * @GST_SEGMENT_FLAG_RESET: reset the pipeline running_time to the segment + * running_time + * @GST_SEGMENT_FLAG_SKIP: perform skip playback + * + * Flags for the GstSegment structure. Currently mapped to the corresponding + * values of the seek flags. + */ +typedef enum { + GST_SEGMENT_FLAG_NONE = GST_SEEK_FLAG_NONE, + GST_SEGMENT_FLAG_RESET = GST_SEEK_FLAG_FLUSH, + GST_SEGMENT_FLAG_SKIP = GST_SEEK_FLAG_SKIP +} GstSegmentFlags; + /** * GstSegment: + * @flags: flags for this segment * @rate: the rate of the segment - * @abs_rate: absolute value of @rate + * @applied_rate: the already applied rate to the segment * @format: the format of the segment values - * @flags: flags for this segment + * @base: the base time of the segment * @start: the start of the segment * @stop: the stop of the segment * @time: the stream time of the segment diff --cc libs/gst/base/gstbasesink.c index 6dc3c87795,31e62c90ac..bcaa20ad86 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@@ -3854,10 -3966,10 +3854,10 @@@ gst_base_sink_perform_seek (GstBaseSin res = FALSE; } - /* if successfull seek, we update our real segment and push + /* if successful seek, we update our real segment and push * out the new segment. */ if (res) { - memcpy (&sink->segment, &seeksegment, sizeof (GstSegment)); + gst_segment_copy_into (&seeksegment, &sink->segment); if (sink->segment.flags & GST_SEEK_FLAG_SEGMENT) { gst_element_post_message (GST_ELEMENT (sink), @@@ -4248,10 -4346,12 +4248,10 @@@ gst_base_sink_negotiate_pull (GstBaseSi GST_DEBUG_OBJECT (basesink, "allowed caps: %" GST_PTR_FORMAT, caps); caps = gst_caps_make_writable (caps); - /* get the first (prefered) format */ + /* get the first (preferred) format */ gst_caps_truncate (caps); - /* try to fixate */ - gst_pad_fixate_caps (GST_BASE_SINK_PAD (basesink), caps); - GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps); + GST_DEBUG_OBJECT (basesink, "have caps: %" GST_PTR_FORMAT, caps); if (gst_caps_is_any (caps)) { GST_DEBUG_OBJECT (basesink, "caps were ANY after fixating, " @@@ -5060,11 -5107,11 +5060,11 @@@ gst_base_sink_change_state (GstElement ", dropped: %" G_GUINT64_FORMAT, priv->rendered, priv->dropped); gst_base_sink_reset_qos (basesink); - GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); + GST_BASE_SINK_PREROLL_UNLOCK (basesink); break; case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_PAD_PREROLL_LOCK (basesink->sinkpad); + GST_BASE_SINK_PREROLL_LOCK (basesink); - /* start by reseting our position state with the object lock so that the + /* start by resetting our position state with the object lock so that the * position query gets the right idea. We do this before we post the * messages so that the message handlers pick this up. */ GST_OBJECT_LOCK (basesink); diff --cc libs/gst/base/gstbasetransform.c index 2aa4ca7a9e,5c36825579..a335482784 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@@ -620,51 -657,16 +620,49 @@@ gst_base_transform_getcaps (GstPad * pa { GstBaseTransform *trans; GstPad *otherpad; - GstCaps *peercaps, *caps, *peerfilter = NULL; - const GstCaps *templ; - GstCaps *peercaps, *caps, *temp; ++ GstCaps *peercaps, *caps, *temp, *peerfilter = NULL; ++ GstCaps *templ; trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad)); otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad; /* we can do what the peer can */ - peercaps = gst_pad_peer_get_caps_reffed (otherpad); + if (filter) { - GstCaps *temp, *templ; + + GST_DEBUG_OBJECT (pad, "filter caps %" GST_PTR_FORMAT, filter); + + /* filtered against our padtemplate on the other side */ + templ = gst_pad_get_pad_template_caps (pad); + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); + temp = gst_caps_intersect_full (filter, templ, GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (templ); + + /* then see what we can transform this to */ + peerfilter = gst_base_transform_transform_caps (trans, + GST_PAD_DIRECTION (pad), temp, NULL); + GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, peerfilter); + gst_caps_unref (temp); + + /* and filter against the template of this pad */ + templ = gst_pad_get_pad_template_caps (otherpad); + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); + /* We keep the caps sorted like the returned caps */ + temp = + gst_caps_intersect_full (peerfilter, templ, GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (peerfilter); + gst_caps_unref (templ); + peerfilter = temp; + } + + peercaps = gst_pad_peer_get_caps (otherpad, peerfilter); + + if (peerfilter) + gst_caps_unref (peerfilter); + if (peercaps) { - GstCaps *temp, *templ; - GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peercaps); /* filtered against our padtemplate on the other side */ @@@ -672,26 -674,30 +670,30 @@@ GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); temp = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST); GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (templ); + } else { + temp = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad)); - GST_DEBUG_OBJECT (pad, "no peer, using our template caps %" GST_PTR_FORMAT, - temp); + } - /* then see what we can transform this to */ - caps = gst_base_transform_transform_caps (trans, - GST_PAD_DIRECTION (otherpad), temp, filter); - GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, caps); - gst_caps_unref (temp); - if (caps == NULL) - goto done; - - /* and filter against the template of this pad */ - templ = gst_pad_get_pad_template_caps (pad); - GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); - /* We keep the caps sorted like the returned caps */ - temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST); - GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); - gst_caps_unref (caps); - gst_caps_unref (templ); - caps = temp; + /* then see what we can transform this to */ + caps = gst_base_transform_transform_caps (trans, - GST_PAD_DIRECTION (otherpad), temp); ++ GST_PAD_DIRECTION (otherpad), temp, filter); + GST_DEBUG_OBJECT (pad, "transformed %" GST_PTR_FORMAT, caps); + gst_caps_unref (temp); + if (caps == NULL) + goto done; + + /* and filter against the template of this pad */ + templ = gst_pad_get_pad_template_caps (pad); + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); + /* We keep the caps sorted like the returned caps */ + temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (caps); ++ gst_caps_unref (templ); + caps = temp; + if (peercaps) { /* Now try if we can put the untransformed downstream caps first */ temp = gst_caps_intersect_full (peercaps, caps, GST_CAPS_INTERSECT_FIRST); if (!gst_caps_is_empty (temp)) { diff --cc libs/gst/base/gsttypefindhelper.c index bfd1556c92,d47761fa55..b0e4028967 --- a/libs/gst/base/gsttypefindhelper.c +++ b/libs/gst/base/gsttypefindhelper.c @@@ -156,10 -147,10 +156,10 @@@ helper_find_peek (gpointer data, gint6 /* getrange might silently return shortened buffers at the end of a file, * we must, however, always return either the full requested data or NULL */ buf_offset = GST_BUFFER_OFFSET (buffer); - buf_size = GST_BUFFER_SIZE (buffer); + buf_size = gst_buffer_get_size (buffer); if ((buf_offset != -1 && buf_offset != offset) || buf_size < size) { - GST_DEBUG ("droping short buffer: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT + GST_DEBUG ("dropping short buffer: %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT " instead of %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT, buf_offset, buf_offset + buf_size - 1, offset, offset + size - 1); gst_buffer_unref (buffer); @@@ -202,8 -191,8 +202,8 @@@ helper_find_suggest (gpointer data, Gst GstTypeFindHelper *helper = (GstTypeFindHelper *) data; GST_LOG_OBJECT (helper->obj, - "'%s' called called suggest (%u, %" GST_PTR_FORMAT ")", + "'%s' called suggest (%u, %" GST_PTR_FORMAT ")", - GST_PLUGIN_FEATURE_NAME (helper->factory), probability, caps); + GST_OBJECT_NAME (helper->factory), probability, caps); if (probability > helper->best_probability) { GstCaps *copy = gst_caps_copy (caps); @@@ -219,8 -208,9 +219,8 @@@ helper_find_get_length (gpointer data { GstTypeFindHelper *helper = (GstTypeFindHelper *) data; - GST_LOG_OBJECT (helper->obj, "'%s' called called get_length, returning %" + GST_LOG_OBJECT (helper->obj, "'%s' called get_length, returning %" - G_GUINT64_FORMAT, GST_PLUGIN_FEATURE_NAME (helper->factory), - helper->size); + G_GUINT64_FORMAT, GST_OBJECT_NAME (helper->factory), helper->size); return helper->size; } @@@ -475,8 -465,8 +475,8 @@@ buf_helper_find_suggest (gpointer data GstTypeFindBufHelper *helper = (GstTypeFindBufHelper *) data; GST_LOG_OBJECT (helper->obj, - "'%s' called called suggest (%u, %" GST_PTR_FORMAT ")", + "'%s' called suggest (%u, %" GST_PTR_FORMAT ")", - GST_PLUGIN_FEATURE_NAME (helper->factory), probability, caps); + GST_OBJECT_NAME (helper->factory), probability, caps); /* Note: not >= as we call typefinders in order of rank, highest first */ if (probability > helper->best_probability) { diff --cc plugins/elements/gsttee.c index 922220681f,6b9e7cc800..90678c6e8c --- a/plugins/elements/gsttee.c +++ b/plugins/elements/gsttee.c @@@ -478,16 -477,69 +478,17 @@@ gst_tee_get_property (GObject * object GST_OBJECT_UNLOCK (tee); } -/* we have no previous source pad we can use to proxy the pad alloc. Loop over - * the source pads, try to alloc a buffer on each one of them. Keep a reference - * to the first pad that succeeds, we will be using it to alloc more buffers - * later. must be called with the OBJECT_LOCK on tee. */ -static GstFlowReturn -gst_tee_find_buffer_alloc (GstTee * tee, guint64 offset, guint size, - GstCaps * caps, GstBuffer ** buf) +static gboolean +gst_tee_sink_event (GstPad * pad, GstEvent * event) { - GstFlowReturn res; - GList *pads; - guint32 cookie; - - res = GST_FLOW_NOT_LINKED; - -retry: - pads = GST_ELEMENT_CAST (tee)->srcpads; - cookie = GST_ELEMENT_CAST (tee)->pads_cookie; - - while (pads) { - GstPad *pad; - PushData *data; - - pad = GST_PAD_CAST (pads->data); - gst_object_ref (pad); - GST_DEBUG_OBJECT (tee, "try alloc on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - GST_OBJECT_UNLOCK (tee); - - GST_TEE_DYN_LOCK (tee); - data = g_object_get_qdata ((GObject *) pad, push_data); - if (!data->removed) - res = gst_pad_alloc_buffer (pad, offset, size, caps, buf); - else - res = GST_FLOW_NOT_LINKED; - GST_TEE_DYN_UNLOCK (tee); - - GST_DEBUG_OBJECT (tee, "got return value %d", res); - - gst_object_unref (pad); + gboolean res; - GST_OBJECT_LOCK (tee); - if (GST_ELEMENT_CAST (tee)->pads_cookie != cookie) { - GST_DEBUG_OBJECT (tee, "pad list changed, restart"); - /* pad list changed, restart. If the pad alloc function returned OK we - * need to unref the buffer */ - if (res == GST_FLOW_OK) - gst_buffer_unref (*buf); - *buf = NULL; - goto retry; - } - if (!data->removed && res == GST_FLOW_OK) { - GST_DEBUG_OBJECT (tee, "we have a buffer on pad %s:%s", - GST_DEBUG_PAD_NAME (pad)); - /* we have a buffer, keep the pad for later and exit the loop. */ - tee->allocpad = pad; - GST_OBJECT_UNLOCK (tee); - gst_tee_notify_alloc_pad (tee); - GST_OBJECT_LOCK (tee); + switch (GST_EVENT_TYPE (event)) { + default: + res = gst_pad_event_default (pad, event); break; - } - /* no valid buffer, try another pad */ - pads = g_list_next (pads); } + return res; } diff --cc tests/check/elements/filesink.c index 94758ef76f,2e37ad75a4..fa1d3f9772 --- a/tests/check/elements/filesink.c +++ b/tests/check/elements/filesink.c @@@ -161,10 -159,11 +161,10 @@@ GST_START_TEST (test_seeking PUSH_BYTES (8800); CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8900); - if (gst_pad_push_event (mysrcpad, - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 8800, -1, - 0))) { + segment.start = 8800; + if (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))) { GST_LOG ("seek ok"); - /* make sure that that new position is reported immediately */ + /* make sure that new position is reported immediately */ CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8800); PUSH_BYTES (1); CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 8801); diff --cc tests/check/generic/sinks.c index 58ec9ef121,fd5d62b522..c647441d18 --- a/tests/check/generic/sinks.c +++ b/tests/check/generic/sinks.c @@@ -1199,16 -1222,17 +1199,19 @@@ GST_START_TEST (test_async_done_eos fail_unless (qret == TRUE, "position wrong"); fail_unless (position == 10 * GST_SECOND, "position is wrong"); + /* Since we are paused and the preroll queue has a length of 1, this function + * will return immediately. The EOS will complete the preroll and the + * position should now be 10 seconds. */ GST_DEBUG ("pushing EOS"); - event = gst_event_new_eos (); - res = gst_pad_send_event (sinkpad, event); - fail_unless (res == TRUE, "no TRUE return"); + GST_DEBUG ("starting thread"); + thread = g_thread_create ((GThreadFunc) send_eos, sinkpad, TRUE, NULL); + fail_if (thread == NULL, "no thread"); + + /* wait for preroll */ + gst_element_get_state (sink, NULL, NULL, -1); /* check if position is still 10 seconds */ - format = GST_FORMAT_TIME; - gst_element_query_position (sink, &format, &position); + gst_element_query_position (sink, GST_FORMAT_TIME, &position); GST_DEBUG ("EOS position %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); fail_unless (position == 10 * GST_SECOND, "position is wrong");