Esempio n. 1
0
static gboolean
gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstStreamSplitter *stream_splitter = (GstStreamSplitter *) parent;
  gboolean res = TRUE;
  gboolean toall = FALSE;
  gboolean store = FALSE;
  gboolean eos = FALSE;
  gboolean flushpending = FALSE;

  /* FLUSH_START/STOP : forward to all
   * EOS : transform to CUSTOM_REAL_EOS and forward to all
   * INBAND events : store to send in chain function to selected chain
   * OUT_OF_BAND events : send to all
   */

  GST_DEBUG_OBJECT (stream_splitter, "Got event %s",
      GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      res = gst_stream_splitter_sink_setcaps (pad, caps);

      store = TRUE;
      break;
    }
    case GST_EVENT_FLUSH_STOP:
      flushpending = TRUE;
      toall = TRUE;
      break;
    case GST_EVENT_FLUSH_START:
      toall = TRUE;
      break;
    case GST_EVENT_EOS:
      /* Replace with our custom eos event */
      gst_event_unref (event);
      event =
          gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
          gst_structure_new_empty ("stream-switching-eos"));
      toall = TRUE;
      eos = TRUE;
      break;
    default:
      if (GST_EVENT_TYPE (event) & GST_EVENT_TYPE_SERIALIZED)
        store = TRUE;
  }

  if (flushpending) {
    g_list_foreach (stream_splitter->pending_events, (GFunc) gst_event_unref,
        NULL);
    g_list_free (stream_splitter->pending_events);
    stream_splitter->pending_events = NULL;
  }

  if (store) {
    stream_splitter->pending_events =
        g_list_append (stream_splitter->pending_events, event);
  } else if (toall || eos) {
    GList *tmp;
    guint32 cookie;

    /* Send to all pads */
    STREAMS_LOCK (stream_splitter);
  resync:
    if (G_UNLIKELY (stream_splitter->srcpads == NULL)) {
      STREAMS_UNLOCK (stream_splitter);
      /* No source pads */
      gst_event_unref (event);
      res = FALSE;
      goto beach;
    }
    tmp = stream_splitter->srcpads;
    cookie = stream_splitter->cookie;
    while (tmp) {
      GstPad *srcpad = (GstPad *) tmp->data;
      STREAMS_UNLOCK (stream_splitter);
      /* In case of EOS, we first push out the real one to flush out
       * each streams (but which will be discarded in the streamcombiner)
       * before our custom one (which will be converted back to and EOS
       * in the streamcombiner) */
      if (eos)
        gst_pad_push_event (srcpad, gst_event_new_eos ());
      gst_event_ref (event);
      res = gst_pad_push_event (srcpad, event);
      STREAMS_LOCK (stream_splitter);
      if (G_UNLIKELY (cookie != stream_splitter->cookie))
        goto resync;
      tmp = tmp->next;
    }
    STREAMS_UNLOCK (stream_splitter);
    gst_event_unref (event);
  } else {
    GstPad *pad;

    /* Only send to current pad */

    STREAMS_LOCK (stream_splitter);
    pad = stream_splitter->current;
    STREAMS_UNLOCK (stream_splitter);
    if (pad)
      res = gst_pad_push_event (pad, event);
    else {
      gst_event_unref (event);
      res = FALSE;
    }
  }

beach:
  return res;
}
static gboolean
gst_stream_splitter_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstStreamSplitter *stream_splitter = (GstStreamSplitter *) parent;
  gboolean res = TRUE;
  gboolean toall = FALSE;
  gboolean store = FALSE;
  gboolean flushpending = FALSE;

  /* FLUSH_START/STOP : forward to all
   * INBAND events : store to send in chain function to selected chain
   * OUT_OF_BAND events : send to all
   */

  GST_DEBUG_OBJECT (stream_splitter, "Got event %s",
      GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      res = gst_stream_splitter_sink_setcaps (pad, caps);

      store = TRUE;
      break;
    }
    case GST_EVENT_FLUSH_STOP:
      flushpending = TRUE;
      toall = TRUE;
      break;
    case GST_EVENT_FLUSH_START:
      toall = TRUE;
      break;
    case GST_EVENT_EOS:
      toall = TRUE;
      break;
    default:
      if (GST_EVENT_TYPE (event) & GST_EVENT_TYPE_SERIALIZED)
        store = TRUE;
  }

  if (flushpending) {
    g_list_foreach (stream_splitter->pending_events, (GFunc) gst_event_unref,
        NULL);
    g_list_free (stream_splitter->pending_events);
    stream_splitter->pending_events = NULL;
  }

  if (store) {
    stream_splitter->pending_events =
        g_list_append (stream_splitter->pending_events, event);
  } else if (toall) {
    GList *tmp;
    guint32 cookie;

    /* Send to all pads */
    STREAMS_LOCK (stream_splitter);
  resync:
    if (G_UNLIKELY (stream_splitter->srcpads == NULL)) {
      STREAMS_UNLOCK (stream_splitter);
      /* No source pads */
      gst_event_unref (event);
      res = FALSE;
      goto beach;
    }
    tmp = stream_splitter->srcpads;
    cookie = stream_splitter->cookie;
    while (tmp) {
      GstPad *srcpad = (GstPad *) tmp->data;
      STREAMS_UNLOCK (stream_splitter);
      gst_event_ref (event);
      res = gst_pad_push_event (srcpad, event);
      STREAMS_LOCK (stream_splitter);
      if (G_UNLIKELY (cookie != stream_splitter->cookie))
        goto resync;
      tmp = tmp->next;
    }
    STREAMS_UNLOCK (stream_splitter);
    gst_event_unref (event);
  } else {
    GstPad *pad;

    /* Only send to current pad */

    STREAMS_LOCK (stream_splitter);
    pad = stream_splitter->current;
    STREAMS_UNLOCK (stream_splitter);
    if (pad)
      res = gst_pad_push_event (pad, event);
    else {
      gst_event_unref (event);
      res = FALSE;
    }
  }

beach:
  return res;
}