Merge branch 'master' into 0.11
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 8 Sep 2011 12:23:50 +0000 (14:23 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 8 Sep 2011 12:28:23 +0000 (14:28 +0200)
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

42 files changed:
1  2 
docs/design/part-TODO.txt
docs/design/part-block.txt
docs/design/part-caps.txt
docs/design/part-element-transform.txt
docs/design/part-events.txt
docs/design/part-gstelement.txt
docs/design/part-latency.txt
docs/design/part-messages.txt
docs/design/part-scheduling.txt
docs/design/part-seeking.txt
docs/manual/highlevel-components.xml
gst/gstbin.c
gst/gstcaps.c
gst/gstelement.c
gst/gstevent.c
gst/gstghostpad.c
gst/gstpad.c
gst/gstpad.h
gst/gstpipeline.c
gst/gstplugin.c
gst/gstpluginfeature.c
gst/gstpluginfeature.h
gst/gstpoll.c
gst/gstregistry.c
gst/gstsegment.h
gst/gststructure.c
gst/gstutils.c
gst/gstutils.h
gst/gstvalue.c
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasetransform.c
libs/gst/base/gsttypefindhelper.c
libs/gst/controller/gstcontroller.c
plugins/elements/gstidentity.c
plugins/elements/gstmultiqueue.c
plugins/elements/gstqueue2.c
plugins/elements/gsttee.c
tests/check/elements/filesink.c
tests/check/generic/sinks.c
tests/check/gst/gstelementfactory.c
tests/check/gst/gstevent.c

index 6b9e2a47dbd310757cb3fdc43b10f8b0dd7e4c75,00524b7a605e1ebbf0df3809bc581277fd83df70..9cb8f0cff1f9227643a49d85dc071935f4aad6e6
@@@ -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
index 8d2508d674eb23affb988ee603cc775a75db2e14,854951dc9e8ff685499d6a234b7a26fca21b295a..deaedbfac84a5ac4624915d663eab2daa17e76cd
@@@ -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.
 -
index ee4b5aa5a001ebf9f84e5d851cac714375ce0a55,3df28ba350a0c4c85dc47e7d31bb5cb41b120540..ac04b757b67dd20932a52caf415a84063f32f5c0
@@@ -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.
  
index 73f18bf560374215b58102cd113895afa72c4717,aecd5fbd669f4da037321aeb1e5440a140d49cff..e3c11b86f2cc897c5f90da5d5ecaaf5f4d221daf
@@@ -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:
  
index 78f15c1149937faf6d7455ee71c82ed30628ceae,b79ed050a630b3182fe2a90802d92c41eeacd7d3..319369823d84baeba8b5f000cc56f7e87c5836e5
@@@ -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.
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gst/gstbin.c
Simple merge
diff --cc gst/gstcaps.c
Simple merge
Simple merge
diff --cc gst/gstevent.c
Simple merge
Simple merge
diff --cc gst/gstpad.c
index f489b77f3c57f4d1bc083e73f9516f8fdb204808,eaeddea9647d4d8e173543e1afc7559514259ae2..b01c483d0ac55b6c5df72528b81b3d10f3b890ac
@@@ -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/gstpad.h
Simple merge
Simple merge
diff --cc gst/gstplugin.c
Simple merge
Simple merge
Simple merge
diff --cc gst/gstpoll.c
Simple merge
Simple merge
index 43f3f1782b8ed450b568b5e08bec60349d35b29d,a0c368320234cd80988c725aa82df53b98744b0f..67a6d503ace7a82ed989a2f7e0c3339403cea25a
@@@ -31,98 -32,12 +31,98 @@@ G_BEGIN_DECL
  
  typedef struct _GstSegment GstSegment;
  
-  * continue playback. With this seek method it is possible to perform seemless
 +/**
 + * 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 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
Simple merge
diff --cc gst/gstutils.c
Simple merge
diff --cc gst/gstutils.h
Simple merge
diff --cc gst/gstvalue.c
Simple merge
index 6dc3c877950179142752cf0b31f3d043f87c74b2,31e62c90ac52c80bb97e4a85dcfe2ca20fb0a2b7..bcaa20ad8679e9525c638fdad2947ef42d121376
@@@ -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);
Simple merge
index 2aa4ca7a9ec0895ffd8809f34f00a0993e2474c1,5c368255793272c3977d42d4862da6657b01745b..a335482784d7aadcf0f3e41d7b0a921b5644a87c
@@@ -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 */
      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_DEBUG_OBJECT (pad, "no peer, using our template caps %" GST_PTR_FORMAT,
 -        temp);
 +    gst_caps_unref (templ);
+   } else {
+     temp = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
+   }
  
-     /* 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)) {
index bfd1556c922d71c8918bb3d033397577039a00fd,d47761fa55b6739d8a3081f0049e11ac4fe1030e..b0e4028967b664ee2995c026278d70295067760e
@@@ -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) {
Simple merge
Simple merge
Simple merge
Simple merge
index 922220681fadb37d2b892d19dededf2cedc4b994,6b9e7cc8009a5060906cc71a924e2e9ac9c0cf39..90678c6e8c2ed5ab92701564a8b6dfd48cc04941
@@@ -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;
  }
  
index 94758ef76f151ad980b26ed89efc95e2265b9934,2e37ad75a4f2d9d27039fe8ea1c70b74a3852da4..fa1d3f97720a1e39c71308a2214c97cf331cc6bb
@@@ -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);
index 58ec9ef1213338d895348d205789e6bb96f58e7d,fd5d62b5229814ee5e7c3dd07d6ed78836db864e..c647441d18826c37ef50d11f7723bfa4ec3a180c
@@@ -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");
  
Simple merge
Simple merge