static gboolean
gst_rtp_ssrc_demux_src_event (GstPad * pad, GstObject * parent,
                              GstEvent * event)
{
    GstRtpSsrcDemux *demux;
    const GstStructure *s;

    demux = GST_RTP_SSRC_DEMUX (parent);

    switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CUSTOM_UPSTREAM:
    case GST_EVENT_CUSTOM_BOTH:
    case GST_EVENT_CUSTOM_BOTH_OOB:
        s = gst_event_get_structure (event);
        if (s && !gst_structure_has_field (s, "ssrc")) {
            GstRtpSsrcDemuxPad *dpad = find_demux_pad_for_pad (demux, pad);

            if (dpad) {
                GstStructure *ws;

                event = gst_event_make_writable (event);
                ws = gst_event_writable_structure (event);
                gst_structure_set (ws, "ssrc", G_TYPE_UINT, dpad->ssrc, NULL);
            }
        }
        break;
    default:
        break;
    }

    return gst_pad_event_default (pad, parent, event);
}
static GstIterator *
gst_rtp_ssrc_demux_iterate_internal_links (GstPad * pad)
{
  GstRtpSsrcDemux *demux;
  GstPad *otherpad = NULL;
  GstIterator *it;
  GSList *current;

  demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));

  GST_PAD_LOCK (demux);
  for (current = demux->srcpads; current; current = g_slist_next (current)) {
    GstRtpSsrcDemuxPad *dpad = (GstRtpSsrcDemuxPad *) current->data;

    if (pad == demux->rtp_sink) {
      otherpad = dpad->rtp_pad;
      break;
    } else if (pad == demux->rtcp_sink) {
      otherpad = dpad->rtcp_pad;
    } else if (pad == dpad->rtp_pad) {
      otherpad = demux->rtp_sink;
      break;
    } else if (pad == dpad->rtcp_pad) {
      otherpad = demux->rtcp_sink;
      break;
    }
  }
  it = gst_iterator_new_single (GST_TYPE_PAD, otherpad,
      (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
  GST_PAD_UNLOCK (demux);

  gst_object_unref (demux);
  return it;
}
static GstIterator *
gst_rtp_ssrc_demux_iterate_internal_links_src (GstPad * pad, GstObject * parent)
{
    GstRtpSsrcDemux *demux;
    GstPad *otherpad = NULL;
    GstIterator *it = NULL;
    GSList *current;

    demux = GST_RTP_SSRC_DEMUX (parent);

    GST_PAD_LOCK (demux);
    for (current = demux->srcpads; current; current = g_slist_next (current)) {
        GstRtpSsrcDemuxPad *dpad = (GstRtpSsrcDemuxPad *) current->data;

        if (pad == dpad->rtp_pad) {
            otherpad = demux->rtp_sink;
            break;
        } else if (pad == dpad->rtcp_pad) {
            otherpad = demux->rtcp_sink;
            break;
        }
    }
    if (otherpad) {
        GValue val = { 0, };

        g_value_init (&val, GST_TYPE_PAD);
        g_value_set_object (&val, otherpad);
        it = gst_iterator_new_single (GST_TYPE_PAD, &val);
        g_value_unset (&val);

    }
    GST_PAD_UNLOCK (demux);

    return it;
}
static GstStateChangeReturn
gst_rtp_ssrc_demux_change_state (GstElement * element,
                                 GstStateChange transition)
{
    GstStateChangeReturn ret;
    GstRtpSsrcDemux *demux;

    demux = GST_RTP_SSRC_DEMUX (element);

    switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
    case GST_STATE_CHANGE_READY_TO_PAUSED:
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
    default:
        break;
    }

    ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

    switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
        break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
        gst_rtp_ssrc_demux_reset (demux);
        break;
    case GST_STATE_CHANGE_READY_TO_NULL:
    default:
        break;
    }
    return ret;
}
static GstFlowReturn
gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
    GstFlowReturn ret;
    GstRtpSsrcDemux *demux;
    guint32 ssrc;
    GstRTPBuffer rtp = { NULL };
    GstPad *srcpad;
    GstRtpSsrcDemuxPad *dpad;

    demux = GST_RTP_SSRC_DEMUX (parent);

    if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
        goto invalid_payload;

    ssrc = gst_rtp_buffer_get_ssrc (&rtp);
    gst_rtp_buffer_unmap (&rtp);

    GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);

    srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTP_PAD);
    if (srcpad == NULL)
        goto create_failed;

    /* push to srcpad */
    ret = gst_pad_push (srcpad, buf);

    if (ret != GST_FLOW_OK) {
        /* check if the ssrc still there, may have been removed */
        GST_PAD_LOCK (demux);
        dpad = find_demux_pad_for_ssrc (demux, ssrc);
        if (dpad == NULL || dpad->rtp_pad != srcpad) {
            /* SSRC was removed during the push ... ignore the error */
            ret = GST_FLOW_OK;
        }
        GST_PAD_UNLOCK (demux);
    }

    gst_object_unref (srcpad);

    return ret;

    /* ERRORS */
invalid_payload:
    {
        /* this is fatal and should be filtered earlier */
        GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
                           ("Dropping invalid RTP payload"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
create_failed:
    {
        GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
                           ("Could not create new pad"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
}
static void
gst_rtp_ssrc_demux_finalize (GObject * object)
{
    GstRtpSsrcDemux *demux;

    demux = GST_RTP_SSRC_DEMUX (object);
    g_rec_mutex_clear (&demux->padlock);

    G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_rtp_ssrc_demux_dispose (GObject * object)
{
    GstRtpSsrcDemux *demux;

    demux = GST_RTP_SSRC_DEMUX (object);

    gst_rtp_ssrc_demux_reset (demux);

    G_OBJECT_CLASS (parent_class)->dispose (object);
}
示例#8
0
static gboolean
gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstRtpSsrcDemux *demux;
  gboolean res = FALSE;

  demux = GST_RTP_SSRC_DEMUX (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:
      gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
      /* fallthrough */
    default:
    {
      GSList *walk;
      GSList *pads = NULL;

      res = TRUE;
      /* need local snapshot of pads;
       * should not push downstream while holding lock as that might deadlock
       * with stuff traveling upstream tyring to get this lock while holding
       * other (stream)lock */
      GST_PAD_LOCK (demux);
      for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
        GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data;

        pad = g_slice_dup (GstRtpSsrcDemuxPad, pad);
        gst_object_ref (pad->rtp_pad);

        pads = g_slist_prepend (pads, pad);
      }
      GST_PAD_UNLOCK (demux);

      for (walk = pads; walk; walk = g_slist_next (walk)) {
        GstRtpSsrcDemuxPad *dpad = walk->data;
        GstEvent *newevent;

        newevent = add_ssrc_and_ref (event, dpad->ssrc);

        res &= gst_pad_push_event (dpad->rtp_pad, newevent);
        gst_object_unref (dpad->rtp_pad);
        g_slice_free (GstRtpSsrcDemuxPad, dpad);
      }
      g_slist_free (pads);
      gst_event_unref (event);
      break;
    }
  }

  return res;
}
static GstFlowReturn
gst_rtp_ssrc_demux_chain (GstPad * pad, GstBuffer * buf)
{
  GstFlowReturn ret;
  GstRtpSsrcDemux *demux;
  guint32 ssrc;
  GstRtpSsrcDemuxPad *dpad;

  demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad));

  if (!gst_rtp_buffer_validate (buf))
    goto invalid_payload;

  ssrc = gst_rtp_buffer_get_ssrc (buf);

  GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);

  GST_PAD_LOCK (demux);
  dpad = find_demux_pad_for_ssrc (demux, ssrc);
  if (dpad == NULL) {
    if (!(dpad =
            create_demux_pad_for_ssrc (demux, ssrc,
                GST_BUFFER_TIMESTAMP (buf))))
      goto create_failed;
  }
  GST_PAD_UNLOCK (demux);

  /* push to srcpad */
  ret = gst_pad_push (dpad->rtp_pad, buf);

  return ret;

  /* ERRORS */
invalid_payload:
  {
    /* this is fatal and should be filtered earlier */
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
        ("Dropping invalid RTP payload"));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
create_failed:
  {
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
        ("Could not create new pad"));
    GST_PAD_UNLOCK (demux);
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
}
示例#10
0
static GstFlowReturn
gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstFlowReturn ret;
  GstRtpSsrcDemux *demux;
  guint32 ssrc;
  GstRTPBuffer rtp = { NULL };
  GstPad *srcpad;

  demux = GST_RTP_SSRC_DEMUX (parent);

  if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
    goto invalid_payload;

  ssrc = gst_rtp_buffer_get_ssrc (&rtp);
  gst_rtp_buffer_unmap (&rtp);

  GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);

  srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTP_PAD);
  if (srcpad == NULL)
    goto create_failed;

  /* push to srcpad */
  ret = gst_pad_push (srcpad, buf);

  gst_object_unref (srcpad);

  return ret;

  /* ERRORS */
invalid_payload:
  {
    /* this is fatal and should be filtered earlier */
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
        ("Dropping invalid RTP payload"));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
create_failed:
  {
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
        ("Could not create new pad"));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
}
示例#11
0
static gboolean
gst_rtp_ssrc_demux_sink_event (GstPad * pad, GstObject * parent,
                               GstEvent * event)
{
    GstRtpSsrcDemux *demux;
    struct ForwardEventData fdata;

    demux = GST_RTP_SSRC_DEMUX (parent);

    fdata.demux = demux;
    fdata.pad = pad;
    fdata.event = event;
    fdata.res = TRUE;

    gst_pad_forward (pad, forward_event, &fdata);

    gst_event_unref (event);

    return fdata.res;
}
示例#12
0
static gboolean
gst_rtp_ssrc_demux_rtcp_sink_event (GstPad * pad, GstEvent * event)
{
  GstRtpSsrcDemux *demux;
  gboolean res = FALSE;

  demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NEWSEGMENT:
    default:
    {
      GSList *walk;
      GSList *pads = NULL;

      res = TRUE;
      GST_PAD_LOCK (demux);
      for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
        GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data;

        pads = g_slist_prepend (pads, gst_object_ref (pad->rtcp_pad));
      }
      GST_PAD_UNLOCK (demux);
      for (walk = pads; walk; walk = g_slist_next (walk)) {
        GstPad *pad = (GstPad *) walk->data;

        gst_event_ref (event);
        res &= gst_pad_push_event (pad, event);
        gst_object_unref (pad);
      }
      g_slist_free (pads);
      gst_event_unref (event);
      break;
    }
  }
  gst_object_unref (demux);
  return res;
}
示例#13
0
static gboolean
gst_rtp_ssrc_demux_src_query (GstPad * pad, GstObject * parent,
                              GstQuery * query)
{
    GstRtpSsrcDemux *demux;
    gboolean res = FALSE;

    demux = GST_RTP_SSRC_DEMUX (parent);

    switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_LATENCY:
    {

        if ((res = gst_pad_peer_query (demux->rtp_sink, query))) {
            gboolean live;
            GstClockTime min_latency, max_latency;
            GstRtpSsrcDemuxPad *demuxpad;

            demuxpad = gst_pad_get_element_private (pad);

            gst_query_parse_latency (query, &live, &min_latency, &max_latency);

            GST_DEBUG_OBJECT (demux, "peer min latency %" GST_TIME_FORMAT,
                              GST_TIME_ARGS (min_latency));

            GST_DEBUG_OBJECT (demux, "latency for SSRC %08x", demuxpad->ssrc);

            gst_query_set_latency (query, live, min_latency, max_latency);
        }
        break;
    }
    default:
        res = gst_pad_query_default (pad, parent, query);
        break;
    }

    return res;
}
示例#14
0
static gboolean
gst_rtp_ssrc_demux_src_event (GstPad * pad, GstEvent * event)
{
  GstRtpSsrcDemux *demux;
  const GstStructure *s;

  demux = GST_RTP_SSRC_DEMUX (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CUSTOM_UPSTREAM:
    case GST_EVENT_CUSTOM_BOTH:
    case GST_EVENT_CUSTOM_BOTH_OOB:
      s = gst_event_get_structure (event);
      if (s && !gst_structure_has_field (s, "ssrc")) {
        GSList *walk;

        for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
          GstRtpSsrcDemuxPad *dpad = (GstRtpSsrcDemuxPad *) walk->data;

          if (dpad->rtp_pad == pad || dpad->rtcp_pad == pad) {
            event =
                GST_EVENT_CAST (gst_mini_object_make_writable
                (GST_MINI_OBJECT_CAST (event)));
            gst_structure_set (event->structure, "ssrc", G_TYPE_UINT,
                dpad->ssrc, NULL);
            break;
          }
        }
      }
      break;
    default:
      break;
  }

  gst_object_unref (demux);

  return gst_pad_event_default (pad, event);
}
示例#15
0
static GstIterator *
gst_rtp_ssrc_demux_iterate_internal_links_sink (GstPad * pad,
        GstObject * parent)
{
    GstRtpSsrcDemux *demux;
    GstIterator *it = NULL;
    GValue gval = { 0, };

    demux = GST_RTP_SSRC_DEMUX (parent);

    g_value_init (&gval, G_TYPE_STRING);
    if (pad == demux->rtp_sink)
        g_value_set_static_string (&gval, "src_");
    else if (pad == demux->rtcp_sink)
        g_value_set_static_string (&gval, "rtcp_src_");
    else
        g_assert_not_reached ();

    it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (demux));
    it = gst_iterator_filter (it, src_pad_compare_func, &gval);

    return it;
}
示例#16
0
static gboolean
gst_rtp_ssrc_demux_rtcp_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstRtpSsrcDemux *demux;
  gboolean res = TRUE;
  GSList *walk;
  GSList *pads = NULL;

  demux = GST_RTP_SSRC_DEMUX (parent);

  GST_PAD_LOCK (demux);
  for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
    GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data;

    pad = g_slice_dup (GstRtpSsrcDemuxPad, pad);
    gst_object_ref (pad->rtcp_pad);

    pads = g_slist_prepend (pads, pad);
  }
  GST_PAD_UNLOCK (demux);

  for (walk = pads; walk; walk = g_slist_next (walk)) {
    GstRtpSsrcDemuxPad *dpad = walk->data;
    GstEvent *newevent;

    newevent = add_ssrc_and_ref (event, dpad->ssrc);

    res &= gst_pad_push_event (dpad->rtcp_pad, newevent);
    gst_object_unref (dpad->rtcp_pad);
    g_slice_free (GstRtpSsrcDemuxPad, dpad);
  }
  g_slist_free (pads);
  gst_event_unref (event);

  return res;
}
示例#17
0
static GstFlowReturn
gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad, GstObject * parent,
                               GstBuffer * buf)
{
    GstFlowReturn ret;
    GstRtpSsrcDemux *demux;
    guint32 ssrc;
    GstRTCPPacket packet;
    GstRTCPBuffer rtcp = { NULL, };
    GstPad *srcpad;
    GstRtpSsrcDemuxPad *dpad;

    demux = GST_RTP_SSRC_DEMUX (parent);

    if (!gst_rtcp_buffer_validate_reduced (buf))
        goto invalid_rtcp;

    gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
    if (!gst_rtcp_buffer_get_first_packet (&rtcp, &packet)) {
        gst_rtcp_buffer_unmap (&rtcp);
        goto invalid_rtcp;
    }

    /* first packet must be SR or RR, or in case of a reduced size RTCP packet
     * it must be APP, RTPFB or PSFB feeadback, or else the validate would
     * have failed */
    switch (gst_rtcp_packet_get_type (&packet)) {
    case GST_RTCP_TYPE_SR:
        /* get the ssrc so that we can route it to the right source pad */
        gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, NULL, NULL, NULL,
                                            NULL);
        break;
    case GST_RTCP_TYPE_RR:
        ssrc = gst_rtcp_packet_rr_get_ssrc (&packet);
        break;
    case GST_RTCP_TYPE_APP:
    case GST_RTCP_TYPE_RTPFB:
    case GST_RTCP_TYPE_PSFB:
        ssrc = gst_rtcp_packet_fb_get_sender_ssrc (&packet);
        break;
    default:
        goto unexpected_rtcp;
    }
    gst_rtcp_buffer_unmap (&rtcp);

    GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc);

    srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTCP_PAD);
    if (srcpad == NULL)
        goto create_failed;

    /* push to srcpad */
    ret = gst_pad_push (srcpad, buf);

    if (ret != GST_FLOW_OK) {
        /* check if the ssrc still there, may have been removed */
        GST_PAD_LOCK (demux);
        dpad = find_demux_pad_for_ssrc (demux, ssrc);
        if (dpad == NULL || dpad->rtcp_pad != srcpad) {
            /* SSRC was removed during the push ... ignore the error */
            ret = GST_FLOW_OK;
        }
        GST_PAD_UNLOCK (demux);
    }

    gst_object_unref (srcpad);

    return ret;

    /* ERRORS */
invalid_rtcp:
    {
        /* this is fatal and should be filtered earlier */
        GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
                           ("Dropping invalid RTCP packet"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
unexpected_rtcp:
    {
        GST_DEBUG_OBJECT (demux, "dropping unexpected RTCP packet");
        gst_buffer_unref (buf);
        return GST_FLOW_OK;
    }
create_failed:
    {
        GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
                           ("Could not create new pad"));
        gst_buffer_unref (buf);
        return GST_FLOW_ERROR;
    }
}
示例#18
0
static GstFlowReturn
gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad, GstObject * parent,
    GstBuffer * buf)
{
  GstFlowReturn ret;
  GstRtpSsrcDemux *demux;
  guint32 ssrc;
  GstRtpSsrcDemuxPad *dpad;
  GstRTCPPacket packet;
  GstRTCPBuffer rtcp = { NULL, };
  GstPad *srcpad;

  demux = GST_RTP_SSRC_DEMUX (parent);

  if (!gst_rtcp_buffer_validate (buf))
    goto invalid_rtcp;

  gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcp);
  if (!gst_rtcp_buffer_get_first_packet (&rtcp, &packet)) {
    gst_rtcp_buffer_unmap (&rtcp);
    goto invalid_rtcp;
  }

  /* first packet must be SR or RR or else the validate would have failed */
  switch (gst_rtcp_packet_get_type (&packet)) {
    case GST_RTCP_TYPE_SR:
      /* get the ssrc so that we can route it to the right source pad */
      gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, NULL, NULL, NULL,
          NULL);
      break;
    default:
      goto unexpected_rtcp;
  }
  gst_rtcp_buffer_unmap (&rtcp);

  GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc);

  GST_PAD_LOCK (demux);
  dpad = find_or_create_demux_pad_for_ssrc (demux, ssrc);
  if (dpad == NULL) {
    GST_PAD_UNLOCK (demux);
    goto create_failed;
  }
  srcpad = gst_object_ref (dpad->rtcp_pad);
  GST_PAD_UNLOCK (demux);

  /* push to srcpad */
  ret = gst_pad_push (srcpad, buf);

  gst_object_unref (srcpad);

  return ret;

  /* ERRORS */
invalid_rtcp:
  {
    /* this is fatal and should be filtered earlier */
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
        ("Dropping invalid RTCP packet"));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
unexpected_rtcp:
  {
    GST_DEBUG_OBJECT (demux, "dropping unexpected RTCP packet");
    gst_buffer_unref (buf);
    return GST_FLOW_OK;
  }
create_failed:
  {
    GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL),
        ("Could not create new pad"));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
}