static GstPad * gst_rtp_dec_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstRTPDec *rtpdec; GstElementClass *klass; GstPad *result; g_return_val_if_fail (templ != NULL, NULL); g_return_val_if_fail (GST_IS_RTP_DEC (element), NULL); rtpdec = GST_RTP_DEC (element); klass = GST_ELEMENT_GET_CLASS (element); /* figure out the template */ if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%u")) { result = create_recv_rtp (rtpdec, templ, name); } else if (templ == gst_element_class_get_pad_template (klass, "recv_rtcp_sink_%u")) { result = create_recv_rtcp (rtpdec, templ, name); } else if (templ == gst_element_class_get_pad_template (klass, "rtcp_src_%u")) { result = create_rtcp (rtpdec, templ, name); } else goto wrong_template; return result; /* ERRORS */ wrong_template: { g_warning ("rtpdec: this is not our template"); return NULL; } }
static GstClock * gst_rtp_dec_provide_clock (GstElement * element) { GstRTPDec *rtpdec; rtpdec = GST_RTP_DEC (element); return GST_CLOCK_CAST (gst_object_ref (rtpdec->provided_clock)); }
static void gst_rtp_dec_finalize (GObject * object) { GstRTPDec *rtpdec; rtpdec = GST_RTP_DEC (object); g_slist_foreach (rtpdec->sessions, (GFunc) free_session, NULL); g_slist_free (rtpdec->sessions); G_OBJECT_CLASS (parent_class)->finalize (object); }
static void gst_rtp_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstRTPDec *src; src = GST_RTP_DEC (object); switch (prop_id) { case PROP_LATENCY: g_value_set_uint (value, src->latency); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static GstFlowReturn gst_rtp_dec_chain_rtcp (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstRTPDec *src; #ifdef HAVE_RTCP gboolean valid; GstRTCPPacket packet; gboolean more; #endif src = GST_RTP_DEC (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"); gst_buffer_unref (buffer); return GST_FLOW_OK; } #else gst_buffer_unref (buffer); return GST_FLOW_OK; #endif }
static GstFlowReturn gst_rtp_dec_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstFlowReturn res; GstRTPDec *rtpdec; GstRTPDecSession *session; guint32 ssrc; guint8 pt; GstRTPBuffer rtp = { NULL, }; rtpdec = GST_RTP_DEC (parent); GST_DEBUG_OBJECT (rtpdec, "got rtp packet"); if (!gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp)) goto bad_packet; ssrc = gst_rtp_buffer_get_ssrc (&rtp); pt = gst_rtp_buffer_get_payload_type (&rtp); gst_rtp_buffer_unmap (&rtp); GST_DEBUG_OBJECT (rtpdec, "SSRC %08x, PT %d", ssrc, pt); /* find session */ session = gst_pad_get_element_private (pad); /* see if we have the pad */ if (!session->active) { GstPadTemplate *templ; GstElementClass *klass; gchar *name; GstCaps *caps; GValue ret = { 0 }; GValue args[3] = { {0} , {0} , {0} }; GST_DEBUG_OBJECT (rtpdec, "creating stream"); session->ssrc = ssrc; session->pt = pt; /* get pt map */ g_value_init (&args[0], GST_TYPE_ELEMENT); g_value_set_object (&args[0], rtpdec); g_value_init (&args[1], G_TYPE_UINT); g_value_set_uint (&args[1], session->id); g_value_init (&args[2], G_TYPE_UINT); g_value_set_uint (&args[2], pt); g_value_init (&ret, GST_TYPE_CAPS); g_value_set_boxed (&ret, NULL); g_signal_emitv (args, gst_rtp_dec_signals[SIGNAL_REQUEST_PT_MAP], 0, &ret); caps = (GstCaps *) g_value_get_boxed (&ret); name = g_strdup_printf ("recv_rtp_src_%u_%u_%u", session->id, ssrc, pt); klass = GST_ELEMENT_GET_CLASS (rtpdec); templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%u_%u_%u"); session->recv_rtp_src = gst_pad_new_from_template (templ, name); g_free (name); gst_pad_set_caps (session->recv_rtp_src, caps); gst_pad_set_element_private (session->recv_rtp_src, session); gst_pad_set_query_function (session->recv_rtp_src, gst_rtp_dec_query_src); gst_pad_set_active (session->recv_rtp_src, TRUE); gst_element_add_pad (GST_ELEMENT_CAST (rtpdec), session->recv_rtp_src); session->active = TRUE; } res = gst_pad_push (session->recv_rtp_src, buffer); return res; bad_packet: { GST_ELEMENT_WARNING (rtpdec, STREAM, DECODE, (NULL), ("RTP packet did not validate, dropping")); gst_buffer_unref (buffer); return GST_FLOW_OK; } }