commit 334acbd876653c1b1fe35833cb37d18daa8072be
Author: Song Bing <b06498@freescale.com>
Date:   Tue Dec 16 14:10:08 2014 +0800

    [inputselector] sticky events haven't send out when active track reach EOS
    
    The root cause is the sticky event is send in chain function. But the
    short audio track already reach EOS, so chain function can't be called.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=740949
    
    Signed-off-by: Song Bing <b06498@freescale.com>

diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c
index 84e2c7b..ce4bfcc 100644
--- a/plugins/elements/gstinputselector.c
+++ b/plugins/elements/gstinputselector.c
@@ -441,6 +441,17 @@ gst_selector_pad_iterate_linked_pads (GstPad * pad, GstObject * parent)
 }
 
 static gboolean
+gst_input_selector_eos_wait (GstInputSelector * self, GstSelectorPad * pad)
+{
+  while (self->eos_block && !self->flushing && !pad->flushing) {
+    /* we can be unlocked here when we are shutting down (flushing) or when we
+     * get unblocked */
+    GST_INPUT_SELECTOR_WAIT (self);
+  }
+  return self->flushing;
+}
+
+static gboolean
 gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
@@ -550,6 +561,9 @@ gst_selector_pad_event (GstPad * pad, GstObject * parent, GstEvent * event)
         active_selpad = GST_SELECTOR_PAD (active_sinkpad);
         forward = (active_selpad->eos && !active_selpad->eos_sent);
         active_selpad->eos_sent = TRUE;
+        gst_input_selector_eos_wait (sel, selpad);
+        forward = TRUE;
+        selpad->eos_sent = TRUE;
       }
       GST_DEBUG_OBJECT (pad, "received EOS");
       break;
@@ -685,6 +699,12 @@ gst_input_selector_wait_running_time (GstInputSelector * sel,
         gst_input_selector_activate_sinkpad (sel, GST_PAD_CAST (selpad));
     active_selpad = GST_SELECTOR_PAD_CAST (active_sinkpad);
 
+    if (active_selpad->eos) {
+      GST_DEBUG_OBJECT (selpad, "Not waiting because active pad EOS.");
+      GST_INPUT_SELECTOR_UNLOCK (sel);
+      return FALSE;
+    }
+
     if (seg->format != GST_FORMAT_TIME) {
       GST_DEBUG_OBJECT (selpad,
           "Not waiting because we don't have a TIME segment");
@@ -970,6 +990,7 @@ gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
   GstPad *active_sinkpad;
   GstPad *prev_active_sinkpad = NULL;
   GstSelectorPad *selpad;
+  GstSelectorPad *active_selpad;
   GstClockTime start_time;
 
   sel = GST_INPUT_SELECTOR (parent);
@@ -991,6 +1012,12 @@ gst_selector_pad_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
   prev_active_sinkpad =
       sel->active_sinkpad ? gst_object_ref (sel->active_sinkpad) : NULL;
   active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+  active_selpad = GST_SELECTOR_PAD_CAST (active_sinkpad);
+  if (active_selpad->eos) {
+    GST_DEBUG_OBJECT (pad, "active pad eos.");
+    GST_INPUT_SELECTOR_UNLOCK (sel);
+    goto ignore;
+  }
 
   /* In sync mode wait until the active pad has advanced
    * after the running time of the current buffer */
@@ -1319,6 +1346,7 @@ gst_input_selector_init (GstInputSelector * sel)
   g_mutex_init (&sel->lock);
   g_cond_init (&sel->cond);
   sel->blocked = FALSE;
+  sel->eos_block = TRUE;
 
   /* lets give a change for downstream to do something on
    * active-pad change before we start pushing new buffers */
@@ -1387,6 +1415,11 @@ gst_input_selector_set_active_pad (GstInputSelector * self, GstPad * pad)
   GST_DEBUG_OBJECT (self, "New active pad is %" GST_PTR_FORMAT,
       self->active_sinkpad);
 
+  if (old != new && new->eos && !new->eos_sent) {
+    self->eos_block = FALSE;
+    GST_INPUT_SELECTOR_BROADCAST (self);
+  }
+
   return TRUE;
 }
 
@@ -1781,6 +1814,7 @@ gst_input_selector_change_state (GstElement * element,
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       GST_INPUT_SELECTOR_LOCK (self);
+      self->eos_block = TRUE;
       self->blocked = FALSE;
       self->flushing = FALSE;
       GST_INPUT_SELECTOR_UNLOCK (self);
@@ -1789,6 +1823,7 @@ gst_input_selector_change_state (GstElement * element,
       /* first unlock before we call the parent state change function, which
        * tries to acquire the stream lock when going to ready. */
       GST_INPUT_SELECTOR_LOCK (self);
+      self->eos_block = FALSE;
       self->blocked = FALSE;
       self->flushing = TRUE;
       GST_INPUT_SELECTOR_BROADCAST (self);
diff --git a/plugins/elements/gstinputselector.h b/plugins/elements/gstinputselector.h
index 96c680f..689ea83 100644
--- a/plugins/elements/gstinputselector.h
+++ b/plugins/elements/gstinputselector.h
@@ -77,6 +77,7 @@ struct _GstInputSelector {
   GMutex lock;
   GCond cond;
   gboolean blocked;
+  gboolean eos_block;
   gboolean flushing;
 };
 
