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));
}
Example #3
0
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;
    }
}