示例#1
0
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;
}
static GstFlowReturn
gst_rdt_manager_chain_rtcp (GstPad * pad, GstObject * parent,
    GstBuffer * buffer)
{
  GstRDTManager *src;

#ifdef HAVE_RTCP
  gboolean valid;
  GstRTCPPacket packet;
  gboolean more;
#endif

  src = GST_RDT_MANAGER (parent);

  GST_DEBUG_OBJECT (src, "got rtcp packet");

#ifdef HAVE_RTCP
  valid = gst_rtcp_buffer_validate (buffer);
  if (!valid)
    goto bad_packet;

  /* position on first packet */
  more = gst_rtcp_buffer_get_first_packet (buffer, &packet);
  while (more) {
    switch (gst_rtcp_packet_get_type (&packet)) {
      case GST_RTCP_TYPE_SR:
      {
        guint32 ssrc, rtptime, packet_count, octet_count;
        guint64 ntptime;
        guint count, i;

        gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, &rtptime,
            &packet_count, &octet_count);

        GST_DEBUG_OBJECT (src,
            "got SR packet: SSRC %08x, NTP %" G_GUINT64_FORMAT
            ", RTP %u, PC %u, OC %u", ssrc, ntptime, rtptime, packet_count,
            octet_count);

        count = gst_rtcp_packet_get_rb_count (&packet);
        for (i = 0; i < count; i++) {
          guint32 ssrc, exthighestseq, jitter, lsr, dlsr;
          guint8 fractionlost;
          gint32 packetslost;

          gst_rtcp_packet_get_rb (&packet, i, &ssrc, &fractionlost,
              &packetslost, &exthighestseq, &jitter, &lsr, &dlsr);

          GST_DEBUG_OBJECT (src, "got RB packet %d: SSRC %08x, FL %u"
              ", PL %u, HS %u, JITTER %u, LSR %u, DLSR %u", ssrc, fractionlost,
              packetslost, exthighestseq, jitter, lsr, dlsr);
        }
        break;
      }
      case GST_RTCP_TYPE_RR:
      {
        guint32 ssrc;
        guint count, i;

        ssrc = gst_rtcp_packet_rr_get_ssrc (&packet);

        GST_DEBUG_OBJECT (src, "got RR packet: SSRC %08x", ssrc);

        count = gst_rtcp_packet_get_rb_count (&packet);
        for (i = 0; i < count; i++) {
          guint32 ssrc, exthighestseq, jitter, lsr, dlsr;
          guint8 fractionlost;
          gint32 packetslost;

          gst_rtcp_packet_get_rb (&packet, i, &ssrc, &fractionlost,
              &packetslost, &exthighestseq, &jitter, &lsr, &dlsr);

          GST_DEBUG_OBJECT (src, "got RB packet %d: SSRC %08x, FL %u"
              ", PL %u, HS %u, JITTER %u, LSR %u, DLSR %u", ssrc, fractionlost,
              packetslost, exthighestseq, jitter, lsr, dlsr);
        }
        break;
      }
      case GST_RTCP_TYPE_SDES:
      {
        guint chunks, i, j;
        gboolean more_chunks, more_items;

        chunks = gst_rtcp_packet_sdes_get_chunk_count (&packet);
        GST_DEBUG_OBJECT (src, "got SDES packet with %d chunks", chunks);

        more_chunks = gst_rtcp_packet_sdes_first_chunk (&packet);
        i = 0;
        while (more_chunks) {
          guint32 ssrc;

          ssrc = gst_rtcp_packet_sdes_get_ssrc (&packet);

          GST_DEBUG_OBJECT (src, "chunk %d, SSRC %08x", i, ssrc);

          more_items = gst_rtcp_packet_sdes_first_item (&packet);
          j = 0;
          while (more_items) {
            GstRTCPSDESType type;
            guint8 len;
            gchar *data;

            gst_rtcp_packet_sdes_get_item (&packet, &type, &len, &data);

            GST_DEBUG_OBJECT (src, "item %d, type %d, len %d, data %s", j,
                type, len, data);

            more_items = gst_rtcp_packet_sdes_next_item (&packet);
            j++;
          }
          more_chunks = gst_rtcp_packet_sdes_next_chunk (&packet);
          i++;
        }
        break;
      }
      case GST_RTCP_TYPE_BYE:
      {
        guint count, i;
        gchar *reason;

        reason = gst_rtcp_packet_bye_get_reason (&packet);
        GST_DEBUG_OBJECT (src, "got BYE packet (reason: %s)",
            GST_STR_NULL (reason));
        g_free (reason);

        count = gst_rtcp_packet_bye_get_ssrc_count (&packet);
        for (i = 0; i < count; i++) {
          guint32 ssrc;


          ssrc = gst_rtcp_packet_bye_get_nth_ssrc (&packet, i);

          GST_DEBUG_OBJECT (src, "SSRC: %08x", ssrc);
        }
        break;
      }
      case GST_RTCP_TYPE_APP:
        GST_DEBUG_OBJECT (src, "got APP packet");
        break;
      default:
        GST_WARNING_OBJECT (src, "got unknown RTCP packet");
        break;
    }
    more = gst_rtcp_packet_move_to_next (&packet);
  }
  gst_buffer_unref (buffer);
  return GST_FLOW_OK;

bad_packet:
  {
    GST_WARNING_OBJECT (src, "got invalid RTCP packet");
    return GST_FLOW_OK;
  }
#else
  return GST_FLOW_OK;
#endif
}
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;
    }
}