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 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; }