コード例 #1
0
static GstBuffer *
create_rtcp_app (guint32 ssrc, guint count)
{
  GInetAddress *inet_addr_0;
  guint16 port = 5678 + count;
  GSocketAddress *socket_addr_0;
  GstBuffer *rtcp_buffer;
  GstRTCPPacket *rtcp_packet = NULL;
  GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;

  inet_addr_0 = g_inet_address_new_from_string ("192.168.1.1");
  socket_addr_0 = g_inet_socket_address_new (inet_addr_0, port);
  g_object_unref (inet_addr_0);

  rtcp_buffer = gst_rtcp_buffer_new (1400);
  gst_buffer_add_net_address_meta (rtcp_buffer, socket_addr_0);
  g_object_unref (socket_addr_0);

  /* need to begin with rr */
  gst_rtcp_buffer_map (rtcp_buffer, GST_MAP_READWRITE, &rtcp);
  rtcp_packet = g_slice_new0 (GstRTCPPacket);
  gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_RR, rtcp_packet);
  gst_rtcp_packet_rr_set_ssrc (rtcp_packet, ssrc);
  g_slice_free (GstRTCPPacket, rtcp_packet);

  /* useful to make the rtcp buffer valid */
  rtcp_packet = g_slice_new0 (GstRTCPPacket);
  gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_APP, rtcp_packet);
  g_slice_free (GstRTCPPacket, rtcp_packet);
  gst_rtcp_buffer_unmap (&rtcp);

  return rtcp_buffer;
}
コード例 #2
0
gboolean
kms_rtp_synchronizer_process_rtcp_buffer (KmsRtpSynchronizer * self,
    GstBuffer * buffer, GstClockTime current_time, GError ** error)
{
  GstRTCPBuffer rtcp_buffer = GST_RTCP_BUFFER_INIT;
  GstRTCPPacket packet;

  if (!gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp_buffer)) {
    const gchar *msg = "Buffer cannot be mapped as RTCP";

    GST_ERROR_OBJECT (self, "%s", msg);
    g_set_error_literal (error, KMS_RTP_SYNC_ERROR,
        KMS_RTP_SYNC_UNEXPECTED_ERROR, msg);

    return FALSE;
  }

  if (!gst_rtcp_buffer_get_first_packet (&rtcp_buffer, &packet)) {
    GST_WARNING_OBJECT (self, "Empty RTCP buffer");
    goto unmap;
  }

  kms_rtp_synchronizer_process_rtcp_packet (self, &packet, current_time);

unmap:
  gst_rtcp_buffer_unmap (&rtcp_buffer);

  return TRUE;
}
コード例 #3
0
ファイル: rtcpfilter.c プロジェクト: kakaroto/farstream
static GstBuffer *
make_buffer (gboolean have_sr, gint rr_count,
    gboolean have_sdes, gboolean have_bye)
{
  GstRTCPPacket packet;
  GstBuffer *buf = gst_rtcp_buffer_new (1024);
  gint i;
  GstRTCPBuffer rtcpbuffer = GST_RTCP_BUFFER_INIT;

  gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcpbuffer);

  if (have_sr)
  {
    gst_rtcp_buffer_add_packet (&rtcpbuffer, GST_RTCP_TYPE_SR, &packet);
    gst_rtcp_packet_sr_set_sender_info (&packet, 132132, 12, 12, 12, 12);
  }

  if (rr_count >= 0 || !have_sr)
  {
    gst_rtcp_buffer_add_packet (&rtcpbuffer, GST_RTCP_TYPE_RR, &packet);
    gst_rtcp_packet_rr_set_ssrc (&packet, 132132);
    for (i = 0; i < rr_count; i++)
      gst_rtcp_packet_add_rb (&packet, 123124+i, 12, 12, 21, 31, 41, 12);
  }

  if (have_sdes)
  {
    gst_rtcp_buffer_add_packet (&rtcpbuffer, GST_RTCP_TYPE_SDES, &packet);
    gst_rtcp_packet_sdes_add_item (&packet, 123121);
    gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_EMAIL,
        10, (guint8 *) "*****@*****.**");
    gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
        10, (guint8 *) "*****@*****.**");
    gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_PHONE,
        10, (guint8 *) "11-21-2-11");
  }

  if (have_bye)
  {
    gst_rtcp_buffer_add_packet (&rtcpbuffer, GST_RTCP_TYPE_BYE, &packet);
    gst_rtcp_packet_bye_add_ssrc (&packet, 132123);
    gst_rtcp_packet_bye_set_reason (&packet, "allo");
  }
  gst_rtcp_buffer_unmap (&rtcpbuffer);

  return buf;
}
コード例 #4
0
ファイル: kmsrtcpdemux.c プロジェクト: pwithnall/kms-elements
static gboolean
refresh_rtcp_rr_ssrcs_map (KmsRtcpDemux * rtcpdemux, GstBuffer * buffer)
{
  GstRTCPBuffer rtcp = { NULL, };
  GstRTCPPacket packet;
  GstRTCPType type;
  gboolean ret = TRUE;
  guint32 remote_ssrc, local_ssrc;

  gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);

  if (!gst_rtcp_buffer_get_first_packet (&rtcp, &packet)) {
    ret = FALSE;
    goto end;
  }

  type = gst_rtcp_packet_get_type (&packet);

  if (type != GST_RTCP_TYPE_RR) {
    ret = TRUE;
    goto end;
  }

  remote_ssrc = gst_rtcp_packet_rr_get_ssrc (&packet);
  ret =
      g_hash_table_contains (rtcpdemux->priv->rr_ssrcs,
      GUINT_TO_POINTER (remote_ssrc));

  if (!ret && (gst_rtcp_packet_get_rb_count (&packet) > 0)) {
    gst_rtcp_packet_get_rb (&packet, 0, &local_ssrc, NULL, NULL, NULL, NULL,
        NULL, NULL);
    GST_TRACE_OBJECT (rtcpdemux, "remote_ssrc (%u) - local_ssrc(%u)",
        remote_ssrc, local_ssrc);
    g_hash_table_insert (rtcpdemux->priv->rr_ssrcs,
        GUINT_TO_POINTER (remote_ssrc), GUINT_TO_POINTER (local_ssrc));
    ret = TRUE;
  }

end:
  gst_rtcp_buffer_unmap (&rtcp);

  return ret;
}
コード例 #5
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;
    }
}
コード例 #6
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;
  }
}
コード例 #7
0
ファイル: kmsremb.c プロジェクト: theravengod/kms-core
static void
on_sending_rtcp (GObject * sess, GstBuffer * buffer, gboolean is_early,
    gboolean * do_not_supress)
{
  KmsRembLocal *rl;
  KmsRTCPPSFBAFBREMBPacket remb_packet;
  GstRTCPBuffer rtcp = { NULL, };
  GstRTCPPacket packet;
  guint packet_ssrc;

  rl = g_object_get_data (sess, KMS_REMB_LOCAL);

  if (!rl) {
    GST_WARNING ("Invalid RembLocal");
    return;
  }

  if (is_early) {
    return;
  }

  if (!gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp)) {
    GST_WARNING_OBJECT (sess, "Cannot map buffer to RTCP");
    return;
  }

  if (!gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_PSFB, &packet)) {
    GST_WARNING_OBJECT (sess, "Cannot add RTCP packet");
    goto end;
  }

  if (!kms_remb_local_update (rl)) {
    goto end;
  }

  remb_packet.bitrate = rl->remb;
  if (rl->event_manager != NULL) {
    guint remb_local_max;

    remb_local_max = kms_utils_remb_event_manager_get_min (rl->event_manager);
    if (remb_local_max > 0) {
      GST_TRACE_OBJECT (sess, "REMB local max: %" G_GUINT32_FORMAT,
          remb_local_max);
      remb_packet.bitrate = MIN (remb_local_max, rl->remb);
    }
  }

  if (rl->min_bw > 0) {
    remb_packet.bitrate = MAX (remb_packet.bitrate, rl->min_bw * 1000);
  } else {
    remb_packet.bitrate = MAX (remb_packet.bitrate, REMB_MIN);
  }

  remb_packet.n_ssrcs = 1;
  remb_packet.ssrcs[0] = rl->remote_ssrc;
  g_object_get (sess, "internal-ssrc", &packet_ssrc, NULL);
  if (!kms_rtcp_psfb_afb_remb_marshall_packet (&packet, &remb_packet,
          packet_ssrc)) {
    gst_rtcp_packet_remove (&packet);
  }

  GST_TRACE_OBJECT (sess, "Sending REMB (bitrate: %" G_GUINT32_FORMAT
      ", ssrc: %" G_GUINT32_FORMAT ")", remb_packet.bitrate, rl->remote_ssrc);

  kms_remb_base_update_stats (KMS_REMB_BASE (rl), rl->remote_ssrc,
      remb_packet.bitrate);

end:
  gst_rtcp_buffer_unmap (&rtcp);
}
コード例 #8
0
ファイル: fs-rtcp-filter.c プロジェクト: kakaroto/farstream
static GstFlowReturn
fs_rtcp_filter_transform_ip (GstBaseTransform *transform, GstBuffer *buf)
{
    FsRtcpFilter *filter = FS_RTCP_FILTER (transform);

    if (!gst_rtcp_buffer_validate (buf))
    {
        GST_ERROR_OBJECT (transform, "Invalid RTCP buffer");
        return GST_FLOW_ERROR;
    }

    GST_OBJECT_LOCK (filter);

    if (!filter->sending)
    {
        GstRTCPBuffer rtcpbuffer = GST_RTCP_BUFFER_INIT;
        GstRTCPPacket packet;

        gst_rtcp_buffer_map (buf, GST_MAP_READWRITE, &rtcpbuffer);

        if (gst_rtcp_buffer_get_first_packet (&rtcpbuffer, &packet))
        {
            for (;;)
            {
                if (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SR)
                {
                    GstRTCPPacket nextpacket = packet;

                    if (gst_rtcp_packet_move_to_next (&nextpacket) &&
                            gst_rtcp_packet_get_type (&nextpacket) == GST_RTCP_TYPE_RR)
                    {
                        if (!gst_rtcp_packet_remove (&packet))
                            break;
                    }
                    else
                    {
                        guchar *data = rtcpbuffer.map.data + packet.offset;

                        /* If there is no RR, lets add an empty one */
                        data[0] = (GST_RTCP_VERSION << 6);
                        data[1] = GST_RTCP_TYPE_RR;
                        data[2] = 0;
                        data[3] = 1;
                        memmove (rtcpbuffer.map.data + packet.offset + 8,
                                 rtcpbuffer.map.data + nextpacket.offset,
                                 rtcpbuffer.map.size - nextpacket.offset);

                        rtcpbuffer.map.size -= nextpacket.offset - packet.offset - 8 ;

                        if (!gst_rtcp_buffer_get_first_packet (&rtcpbuffer, &packet))
                            break;
                    }

                }
                else
                {
                    if (!gst_rtcp_packet_move_to_next (&packet))
                        break;
                }
            }
        }
        gst_rtcp_buffer_unmap (&rtcpbuffer);
    }

    GST_OBJECT_UNLOCK (filter);

    return GST_FLOW_OK;
}