From: Edgard Lima Date: Thu, 17 Nov 2005 18:23:23 +0000 (+0000) Subject: Created Speex payloader and depayloader; Optimize G711 payloader to use adapter and... X-Git-Tag: RELEASE-0_9_6~45 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5ae66f78c51ba7a55fe486a452a795dc231a1a4d;p=platform%2Fupstream%2Fgst-plugins-good.git Created Speex payloader and depayloader; Optimize G711 payloader to use adapter and send packets until MTU size. Original commit message from CVS: Created Speex payloader and depayloader; Optimize G711 payloader to use adapter and send packets until MTU size. --- diff --git a/ChangeLog b/ChangeLog index 2bbd47e..a3e153d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2005-11-17 Edgard Lima + + * gst/rtp/Makefile.am + * gst/rtp/gstrtp.c + * gst/rtp/gstrtpg711enc.c: (gst_rtpg711enc_src_template), + (gst_rtpg711enc_class_init), (gst_rtpg711enc_init), + (gst_rtpg711enc_finalize), (gst_rtpg711enc_setcaps), + (gst_rtpg711enc_flush), (gst_rtpg711enc_handle_buffer): + * gst/rtp/gstrtpg711enc.h: + * gst/rtp/gstrtpg711dec.c: (gst_rtpg711dec_sink_template): + * gst/rtp/gstrtpspeexenc.c: + * gst/rtp/gstrtpspeexenc.h: + * gst/rtp/gstrtpspeexdec.c: + * gst/rtp/gstrtpspeexdec.h: + Created Speex payloader and depayloader; Optimize G711 payloader to + use adapter and send packets until MTU size. + 2005-11-16 Wim Taymans * check/elements/matroskamux.c: (setup_src_pad), (setup_sink_pad): diff --git a/gst/rtp/Makefile.am b/gst/rtp/Makefile.am index 877dbef..d1c98e9 100644 --- a/gst/rtp/Makefile.am +++ b/gst/rtp/Makefile.am @@ -16,8 +16,10 @@ libgstrtp_la_SOURCES = \ gstrtph263enc.c \ gstasteriskh263.c \ gstrtpmp4venc.c \ - gstrtpmp4vdec.c - + gstrtpmp4vdec.c \ + gstrtpspeexenc.c \ + gstrtpspeexdec.c + #gstrtpL16enc.c gstrtpL16parse.c gstrtpgsmenc.c gstrtpgsmparse.c if HAVE_WINSOCK2_H @@ -48,4 +50,6 @@ noinst_HEADERS = gstrtpL16enc.h \ gstrtpmp4vdec.h \ gstrtpdec.h \ gstrtph263enc.h \ - gstasteriskh263.h + gstasteriskh263.h \ + gstrtpspeexenc.h \ + gstrtpspeexdec.h diff --git a/gst/rtp/gstrtp.c b/gst/rtp/gstrtp.c index 07a77e4..889e374 100644 --- a/gst/rtp/gstrtp.c +++ b/gst/rtp/gstrtp.c @@ -36,6 +36,8 @@ #include "gstasteriskh263.h" #include "gstrtpmp4venc.h" #include "gstrtpmp4vdec.h" +#include "gstrtpspeexenc.h" +#include "gstrtpspeexdec.h" static gboolean plugin_init (GstPlugin * plugin) @@ -85,6 +87,12 @@ plugin_init (GstPlugin * plugin) if (!gst_rtpmp4vdec_plugin_init (plugin)) return FALSE; + if (!gst_rtpspeexenc_plugin_init (plugin)) + return FALSE; + + if (!gst_rtpspeexdec_plugin_init (plugin)) + return FALSE; + return TRUE; } diff --git a/gst/rtp/gstrtpg711dec.c b/gst/rtp/gstrtpg711dec.c index e39f7d5..216dc38 100644 --- a/gst/rtp/gstrtpg711dec.c +++ b/gst/rtp/gstrtpg711dec.c @@ -48,12 +48,12 @@ static GstStaticPadTemplate gst_rtpg711dec_sink_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 0, " + "payload = (int) [ 0, 255 ], " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMU\"; " "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 8, " + "payload = (int) [ 0, 255 ], " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMA\"") ); diff --git a/gst/rtp/gstrtpg711depay.c b/gst/rtp/gstrtpg711depay.c index e39f7d5..216dc38 100644 --- a/gst/rtp/gstrtpg711depay.c +++ b/gst/rtp/gstrtpg711depay.c @@ -48,12 +48,12 @@ static GstStaticPadTemplate gst_rtpg711dec_sink_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 0, " + "payload = (int) [ 0, 255 ], " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMU\"; " "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 8, " + "payload = (int) [ 0, 255 ], " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMA\"") ); diff --git a/gst/rtp/gstrtpg711enc.c b/gst/rtp/gstrtpg711enc.c index e0c7067..e83c888 100644 --- a/gst/rtp/gstrtpg711enc.c +++ b/gst/rtp/gstrtpg711enc.c @@ -45,12 +45,12 @@ static GstStaticPadTemplate gst_rtpg711enc_src_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 0, " + "payload = (int) " GST_RTP_PAYLOAD_PCMU_STRING ", " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMU\"; " "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 8, " + "payload = (int) " GST_RTP_PAYLOAD_PCMA_STRING ", " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMA\"") ); @@ -58,6 +58,7 @@ static gboolean gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps); static GstFlowReturn gst_rtpg711enc_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer); +static void gst_rtpg711enc_finalize (GObject * object); GST_BOILERPLATE (GstRtpG711Enc, gst_rtpg711enc, GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD); @@ -86,6 +87,7 @@ gst_rtpg711enc_class_init (GstRtpG711EncClass * klass) gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); + gobject_class->finalize = gst_rtpg711enc_finalize; gstbasertppayload_class->set_caps = gst_rtpg711enc_setcaps; gstbasertppayload_class->handle_buffer = gst_rtpg711enc_handle_buffer; @@ -94,9 +96,23 @@ gst_rtpg711enc_class_init (GstRtpG711EncClass * klass) static void gst_rtpg711enc_init (GstRtpG711Enc * rtpg711enc, GstRtpG711EncClass * klass) { + rtpg711enc->adapter = gst_adapter_new (); GST_BASE_RTP_PAYLOAD (rtpg711enc)->clock_rate = 8000; } +static void +gst_rtpg711enc_finalize (GObject * object) +{ + GstRtpG711Enc *rtpg711enc; + + rtpg711enc = GST_RTP_G711_ENC (object); + + g_object_unref (rtpg711enc->adapter); + rtpg711enc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static gboolean gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) { @@ -109,9 +125,11 @@ gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) stname = gst_structure_get_name (structure); if (0 == strcmp ("audio/x-mulaw", stname)) { - gst_basertppayload_set_options (payload, "audio", TRUE, "PCMU", 8000); + payload->pt = GST_RTP_PAYLOAD_PCMU; + gst_basertppayload_set_options (payload, "audio", FALSE, "PCMU", 8000); } else if (0 == strcmp ("audio/x-alaw", stname)) { - gst_basertppayload_set_options (payload, "audio", TRUE, "PCMA", 8000); + payload->pt = GST_RTP_PAYLOAD_PCMA; + gst_basertppayload_set_options (payload, "audio", FALSE, "PCMA", 8000); } else { return FALSE; } @@ -122,41 +140,88 @@ gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) } static GstFlowReturn +gst_rtpg711enc_flush (GstRtpG711Enc * rtpg711enc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + + /* the data available in the adapter is either smaller + * than the MTU or bigger. In the case it is smaller, the complete + * adapter contents can be put in one packet. */ + avail = gst_adapter_available (rtpg711enc->adapter); + + ret = GST_FLOW_OK; + + while (avail > 0) { + guint towrite; + guint8 *payload; + guint8 *data; + guint payload_len; + guint packet_len; + + /* this will be the total lenght of the packet */ + packet_len = gst_rtpbuffer_calc_packet_len (avail, 0, 0); + /* fill one MTU or all available bytes */ + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpg711enc)); + /* this is the payload length */ + payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); + /* create buffer to hold the payload */ + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + + /* copy payload */ + gst_rtpbuffer_set_payload_type (outbuf, + GST_BASE_RTP_PAYLOAD_PT (rtpg711enc)); + payload = gst_rtpbuffer_get_payload (outbuf); + data = (guint8 *) gst_adapter_peek (rtpg711enc->adapter, payload_len); + memcpy (payload, data, payload_len); + gst_adapter_flush (rtpg711enc->adapter, payload_len); + + avail -= payload_len; + + GST_BUFFER_TIMESTAMP (outbuf) = rtpg711enc->first_ts; + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpg711enc), outbuf); + } + + return ret; +} + +static GstFlowReturn gst_rtpg711enc_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRtpG711Enc *rtpg711enc; - guint size, payload_len; - GstBuffer *outbuf; - guint8 *payload, *data; - GstClockTime timestamp; + guint size, packet_len, avail; GstFlowReturn ret; + GstClockTime duration; rtpg711enc = GST_RTP_G711_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); - timestamp = GST_BUFFER_TIMESTAMP (buffer); + duration = GST_BUFFER_TIMESTAMP (buffer); - /* FIXME, only one G711 frame per RTP packet for now */ - payload_len = size; - - outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - /* FIXME, assert for now */ - g_assert (payload_len <= GST_BASE_RTP_PAYLOAD_MTU (rtpg711enc)); - - /* copy timestamp */ - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - /* get payload */ - payload = gst_rtpbuffer_get_payload (outbuf); - - data = GST_BUFFER_DATA (buffer); + avail = gst_adapter_available (rtpg711enc->adapter); + if (avail == 0) { + rtpg711enc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + rtpg711enc->duration = 0; + } - /* copy data in payload */ - memcpy (&payload[0], data, size); + /* get packet length of data and see if we exceeded MTU. */ + packet_len = gst_rtpbuffer_calc_packet_len (avail + size, 0, 0); - gst_buffer_unref (buffer); + /* if this buffer is going to overflow the packet, flush what we + * have. */ + if (gst_basertppayload_is_filled (basepayload, + packet_len, rtpg711enc->duration + duration)) { + ret = gst_rtpg711enc_flush (rtpg711enc); + rtpg711enc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + rtpg711enc->duration = 0; + } else { + ret = GST_FLOW_OK; + } - ret = gst_basertppayload_push (basepayload, outbuf); + gst_adapter_push (rtpg711enc->adapter, buffer); + rtpg711enc->duration += duration; return ret; } diff --git a/gst/rtp/gstrtpg711enc.h b/gst/rtp/gstrtpg711enc.h index e3ab1fe..f8ca6dd 100644 --- a/gst/rtp/gstrtpg711enc.h +++ b/gst/rtp/gstrtpg711enc.h @@ -18,6 +18,7 @@ #include #include +#include G_BEGIN_DECLS @@ -38,8 +39,10 @@ typedef struct _GstRtpG711EncClass GstRtpG711EncClass; struct _GstRtpG711Enc { GstBaseRTPPayload payload; - - gint frequency; + GstAdapter *adapter; + + GstClockTime first_ts; + GstClockTime duration; }; struct _GstRtpG711EncClass diff --git a/gst/rtp/gstrtpg711pay.c b/gst/rtp/gstrtpg711pay.c index e0c7067..e83c888 100644 --- a/gst/rtp/gstrtpg711pay.c +++ b/gst/rtp/gstrtpg711pay.c @@ -45,12 +45,12 @@ static GstStaticPadTemplate gst_rtpg711enc_src_template = GST_PAD_ALWAYS, GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 0, " + "payload = (int) " GST_RTP_PAYLOAD_PCMU_STRING ", " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMU\"; " "application/x-rtp, " "media = (string) \"audio\", " - "payload = (int) 8, " + "payload = (int) " GST_RTP_PAYLOAD_PCMA_STRING ", " "clock-rate = (int) 8000, " "encoding-name = (string) \"PCMA\"") ); @@ -58,6 +58,7 @@ static gboolean gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps); static GstFlowReturn gst_rtpg711enc_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer); +static void gst_rtpg711enc_finalize (GObject * object); GST_BOILERPLATE (GstRtpG711Enc, gst_rtpg711enc, GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD); @@ -86,6 +87,7 @@ gst_rtpg711enc_class_init (GstRtpG711EncClass * klass) gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); + gobject_class->finalize = gst_rtpg711enc_finalize; gstbasertppayload_class->set_caps = gst_rtpg711enc_setcaps; gstbasertppayload_class->handle_buffer = gst_rtpg711enc_handle_buffer; @@ -94,9 +96,23 @@ gst_rtpg711enc_class_init (GstRtpG711EncClass * klass) static void gst_rtpg711enc_init (GstRtpG711Enc * rtpg711enc, GstRtpG711EncClass * klass) { + rtpg711enc->adapter = gst_adapter_new (); GST_BASE_RTP_PAYLOAD (rtpg711enc)->clock_rate = 8000; } +static void +gst_rtpg711enc_finalize (GObject * object) +{ + GstRtpG711Enc *rtpg711enc; + + rtpg711enc = GST_RTP_G711_ENC (object); + + g_object_unref (rtpg711enc->adapter); + rtpg711enc->adapter = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static gboolean gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) { @@ -109,9 +125,11 @@ gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) stname = gst_structure_get_name (structure); if (0 == strcmp ("audio/x-mulaw", stname)) { - gst_basertppayload_set_options (payload, "audio", TRUE, "PCMU", 8000); + payload->pt = GST_RTP_PAYLOAD_PCMU; + gst_basertppayload_set_options (payload, "audio", FALSE, "PCMU", 8000); } else if (0 == strcmp ("audio/x-alaw", stname)) { - gst_basertppayload_set_options (payload, "audio", TRUE, "PCMA", 8000); + payload->pt = GST_RTP_PAYLOAD_PCMA; + gst_basertppayload_set_options (payload, "audio", FALSE, "PCMA", 8000); } else { return FALSE; } @@ -122,41 +140,88 @@ gst_rtpg711enc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) } static GstFlowReturn +gst_rtpg711enc_flush (GstRtpG711Enc * rtpg711enc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + + /* the data available in the adapter is either smaller + * than the MTU or bigger. In the case it is smaller, the complete + * adapter contents can be put in one packet. */ + avail = gst_adapter_available (rtpg711enc->adapter); + + ret = GST_FLOW_OK; + + while (avail > 0) { + guint towrite; + guint8 *payload; + guint8 *data; + guint payload_len; + guint packet_len; + + /* this will be the total lenght of the packet */ + packet_len = gst_rtpbuffer_calc_packet_len (avail, 0, 0); + /* fill one MTU or all available bytes */ + towrite = MIN (packet_len, GST_BASE_RTP_PAYLOAD_MTU (rtpg711enc)); + /* this is the payload length */ + payload_len = gst_rtpbuffer_calc_payload_len (towrite, 0, 0); + /* create buffer to hold the payload */ + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + + /* copy payload */ + gst_rtpbuffer_set_payload_type (outbuf, + GST_BASE_RTP_PAYLOAD_PT (rtpg711enc)); + payload = gst_rtpbuffer_get_payload (outbuf); + data = (guint8 *) gst_adapter_peek (rtpg711enc->adapter, payload_len); + memcpy (payload, data, payload_len); + gst_adapter_flush (rtpg711enc->adapter, payload_len); + + avail -= payload_len; + + GST_BUFFER_TIMESTAMP (outbuf) = rtpg711enc->first_ts; + ret = gst_basertppayload_push (GST_BASE_RTP_PAYLOAD (rtpg711enc), outbuf); + } + + return ret; +} + +static GstFlowReturn gst_rtpg711enc_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRtpG711Enc *rtpg711enc; - guint size, payload_len; - GstBuffer *outbuf; - guint8 *payload, *data; - GstClockTime timestamp; + guint size, packet_len, avail; GstFlowReturn ret; + GstClockTime duration; rtpg711enc = GST_RTP_G711_ENC (basepayload); size = GST_BUFFER_SIZE (buffer); - timestamp = GST_BUFFER_TIMESTAMP (buffer); + duration = GST_BUFFER_TIMESTAMP (buffer); - /* FIXME, only one G711 frame per RTP packet for now */ - payload_len = size; - - outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); - /* FIXME, assert for now */ - g_assert (payload_len <= GST_BASE_RTP_PAYLOAD_MTU (rtpg711enc)); - - /* copy timestamp */ - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - /* get payload */ - payload = gst_rtpbuffer_get_payload (outbuf); - - data = GST_BUFFER_DATA (buffer); + avail = gst_adapter_available (rtpg711enc->adapter); + if (avail == 0) { + rtpg711enc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + rtpg711enc->duration = 0; + } - /* copy data in payload */ - memcpy (&payload[0], data, size); + /* get packet length of data and see if we exceeded MTU. */ + packet_len = gst_rtpbuffer_calc_packet_len (avail + size, 0, 0); - gst_buffer_unref (buffer); + /* if this buffer is going to overflow the packet, flush what we + * have. */ + if (gst_basertppayload_is_filled (basepayload, + packet_len, rtpg711enc->duration + duration)) { + ret = gst_rtpg711enc_flush (rtpg711enc); + rtpg711enc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + rtpg711enc->duration = 0; + } else { + ret = GST_FLOW_OK; + } - ret = gst_basertppayload_push (basepayload, outbuf); + gst_adapter_push (rtpg711enc->adapter, buffer); + rtpg711enc->duration += duration; return ret; } diff --git a/gst/rtp/gstrtpg711pay.h b/gst/rtp/gstrtpg711pay.h index e3ab1fe..f8ca6dd 100644 --- a/gst/rtp/gstrtpg711pay.h +++ b/gst/rtp/gstrtpg711pay.h @@ -18,6 +18,7 @@ #include #include +#include G_BEGIN_DECLS @@ -38,8 +39,10 @@ typedef struct _GstRtpG711EncClass GstRtpG711EncClass; struct _GstRtpG711Enc { GstBaseRTPPayload payload; - - gint frequency; + GstAdapter *adapter; + + GstClockTime first_ts; + GstClockTime duration; }; struct _GstRtpG711EncClass diff --git a/gst/rtp/gstrtpspeexdec.c b/gst/rtp/gstrtpspeexdec.c new file mode 100644 index 0000000..febcef4 --- /dev/null +++ b/gst/rtp/gstrtpspeexdec.c @@ -0,0 +1,143 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "gstrtpspeexdec.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_speexdec_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts Speex audio from RTP packets", + "Edgard Lima " +}; + +/* RtpSPEEXDec signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0 +}; + +static GstStaticPadTemplate gst_rtpspeexdec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 127 ], " + "clock-rate = (int) [6000, 48000], " + "encoding-name = (string) \"speex\", " + "encoding-params = (string) \"1\"") + ); + +static GstStaticPadTemplate gst_rtpspeexdec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-speex") + ); + +static GstBuffer *gst_rtpspeexdec_process (GstBaseRTPDepayload * depayload, + GstBuffer * buf); +static gboolean gst_rtpspeexdec_setcaps (GstBaseRTPDepayload * depayload, + GstCaps * caps); + +GST_BOILERPLATE (GstRtpSPEEXDec, gst_rtpspeexdec, GstBaseRTPDepayload, + GST_TYPE_BASE_RTP_DEPAYLOAD); + +static void +gst_rtpspeexdec_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexdec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexdec_sink_template)); + gst_element_class_set_details (element_class, &gst_rtp_speexdec_details); +} + +static void +gst_rtpspeexdec_class_init (GstRtpSPEEXDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_DEPAYLOAD); + + gstbasertpdepayload_class->process = gst_rtpspeexdec_process; + gstbasertpdepayload_class->set_caps = gst_rtpspeexdec_setcaps; +} + +static void +gst_rtpspeexdec_init (GstRtpSPEEXDec * rtpspeexdec, GstRtpSPEEXDecClass * klass) +{ + GST_BASE_RTP_DEPAYLOAD (rtpspeexdec)->clock_rate = 8000; +} + +static gboolean +gst_rtpspeexdec_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) +{ + GstCaps *srccaps; + gboolean ret; + + srccaps = gst_static_pad_template_get_caps (&gst_rtpspeexdec_src_template); + ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps); + + gst_caps_unref (srccaps); + return ret; +} + +static GstBuffer * +gst_rtpspeexdec_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +{ + GstBuffer *outbuf = NULL; + gint payload_len; + guint8 *payload; + + GST_DEBUG ("process : got %d bytes, mark %d ts %u seqn %d", + GST_BUFFER_SIZE (buf), + gst_rtpbuffer_get_marker (buf), + gst_rtpbuffer_get_timestamp (buf), gst_rtpbuffer_get_seq (buf)); + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + outbuf = gst_buffer_new_and_alloc (payload_len); + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + return outbuf; +} + +gboolean +gst_rtpspeexdec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpspeexdec", + GST_RANK_NONE, GST_TYPE_RTP_SPEEX_DEC); +} diff --git a/gst/rtp/gstrtpspeexdec.h b/gst/rtp/gstrtpspeexdec.h new file mode 100644 index 0000000..603a7bf --- /dev/null +++ b/gst/rtp/gstrtpspeexdec.h @@ -0,0 +1,51 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +#ifndef __GST_RTP_SPEEX_DEC_H__ +#define __GST_RTP_SPEEX_DEC_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstRtpSPEEXDec GstRtpSPEEXDec; +typedef struct _GstRtpSPEEXDecClass GstRtpSPEEXDecClass; + +#define GST_TYPE_RTP_SPEEX_DEC \ + (gst_rtpspeexdec_get_type()) +#define GST_RTP_SPEEX_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SPEEX_DEC,GstRtpSPEEXDec)) +#define GST_RTP_SPEEX_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SPEEX_DEC,GstRtpSPEEXDec)) +#define GST_IS_RTP_SPEEX_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SPEEX_DEC)) +#define GST_IS_RTP_SPEEX_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SPEEX_DEC)) + +struct _GstRtpSPEEXDec +{ + GstBaseRTPDepayload depayload; +}; + +struct _GstRtpSPEEXDecClass +{ + GstBaseRTPDepayloadClass parent_class; +}; + +gboolean gst_rtpspeexdec_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_SPEEX_DEC_H__ */ diff --git a/gst/rtp/gstrtpspeexdepay.c b/gst/rtp/gstrtpspeexdepay.c new file mode 100644 index 0000000..febcef4 --- /dev/null +++ b/gst/rtp/gstrtpspeexdepay.c @@ -0,0 +1,143 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "gstrtpspeexdec.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_speexdec_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts Speex audio from RTP packets", + "Edgard Lima " +}; + +/* RtpSPEEXDec signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0 +}; + +static GstStaticPadTemplate gst_rtpspeexdec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) [ 96, 127 ], " + "clock-rate = (int) [6000, 48000], " + "encoding-name = (string) \"speex\", " + "encoding-params = (string) \"1\"") + ); + +static GstStaticPadTemplate gst_rtpspeexdec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-speex") + ); + +static GstBuffer *gst_rtpspeexdec_process (GstBaseRTPDepayload * depayload, + GstBuffer * buf); +static gboolean gst_rtpspeexdec_setcaps (GstBaseRTPDepayload * depayload, + GstCaps * caps); + +GST_BOILERPLATE (GstRtpSPEEXDec, gst_rtpspeexdec, GstBaseRTPDepayload, + GST_TYPE_BASE_RTP_DEPAYLOAD); + +static void +gst_rtpspeexdec_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexdec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexdec_sink_template)); + gst_element_class_set_details (element_class, &gst_rtp_speexdec_details); +} + +static void +gst_rtpspeexdec_class_init (GstRtpSPEEXDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_DEPAYLOAD); + + gstbasertpdepayload_class->process = gst_rtpspeexdec_process; + gstbasertpdepayload_class->set_caps = gst_rtpspeexdec_setcaps; +} + +static void +gst_rtpspeexdec_init (GstRtpSPEEXDec * rtpspeexdec, GstRtpSPEEXDecClass * klass) +{ + GST_BASE_RTP_DEPAYLOAD (rtpspeexdec)->clock_rate = 8000; +} + +static gboolean +gst_rtpspeexdec_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) +{ + GstCaps *srccaps; + gboolean ret; + + srccaps = gst_static_pad_template_get_caps (&gst_rtpspeexdec_src_template); + ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps); + + gst_caps_unref (srccaps); + return ret; +} + +static GstBuffer * +gst_rtpspeexdec_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +{ + GstBuffer *outbuf = NULL; + gint payload_len; + guint8 *payload; + + GST_DEBUG ("process : got %d bytes, mark %d ts %u seqn %d", + GST_BUFFER_SIZE (buf), + gst_rtpbuffer_get_marker (buf), + gst_rtpbuffer_get_timestamp (buf), gst_rtpbuffer_get_seq (buf)); + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + outbuf = gst_buffer_new_and_alloc (payload_len); + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + return outbuf; +} + +gboolean +gst_rtpspeexdec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpspeexdec", + GST_RANK_NONE, GST_TYPE_RTP_SPEEX_DEC); +} diff --git a/gst/rtp/gstrtpspeexdepay.h b/gst/rtp/gstrtpspeexdepay.h new file mode 100644 index 0000000..603a7bf --- /dev/null +++ b/gst/rtp/gstrtpspeexdepay.h @@ -0,0 +1,51 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +#ifndef __GST_RTP_SPEEX_DEC_H__ +#define __GST_RTP_SPEEX_DEC_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstRtpSPEEXDec GstRtpSPEEXDec; +typedef struct _GstRtpSPEEXDecClass GstRtpSPEEXDecClass; + +#define GST_TYPE_RTP_SPEEX_DEC \ + (gst_rtpspeexdec_get_type()) +#define GST_RTP_SPEEX_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SPEEX_DEC,GstRtpSPEEXDec)) +#define GST_RTP_SPEEX_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SPEEX_DEC,GstRtpSPEEXDec)) +#define GST_IS_RTP_SPEEX_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SPEEX_DEC)) +#define GST_IS_RTP_SPEEX_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SPEEX_DEC)) + +struct _GstRtpSPEEXDec +{ + GstBaseRTPDepayload depayload; +}; + +struct _GstRtpSPEEXDecClass +{ + GstBaseRTPDepayloadClass parent_class; +}; + +gboolean gst_rtpspeexdec_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_SPEEX_DEC_H__ */ diff --git a/gst/rtp/gstrtpspeexenc.c b/gst/rtp/gstrtpspeexenc.c new file mode 100644 index 0000000..97e3bf3 --- /dev/null +++ b/gst/rtp/gstrtpspeexenc.c @@ -0,0 +1,149 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "gstrtpspeexenc.h" + +/* elementfactory information */ +static GstElementDetails gst_rtpspeexenc_details = { + "RTP packet parser", + "Codec/Encoder/Network", + "Encodes Speex audio into a RTP packet", + "Edgard Lima " +}; + +static GstStaticPadTemplate gst_rtpspeexenc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-speex") + ); + +static GstStaticPadTemplate gst_rtpspeexenc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " "payload = (int) 110, " /* guaranties compatibility with Linphone + Could be [96,127] See page 34 at http://www.ietf.org/rfc/rfc3551.txt */ + "clock-rate = (int) [6000, 48000], " + "encoding-name = (string) \"speex\", " + "encoding-params = (string) \"1\"") + ); + +static gboolean gst_rtpspeexenc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpspeexenc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); + +GST_BOILERPLATE (GstRtpSPEEXEnc, gst_rtpspeexenc, GstBaseRTPPayload, + GST_TYPE_BASE_RTP_PAYLOAD); + +static void +gst_rtpspeexenc_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexenc_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexenc_src_template)); + gst_element_class_set_details (element_class, &gst_rtpspeexenc_details); +} + +static void +gst_rtpspeexenc_class_init (GstRtpSPEEXEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); + + gstbasertppayload_class->set_caps = gst_rtpspeexenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpspeexenc_handle_buffer; +} + +static void +gst_rtpspeexenc_init (GstRtpSPEEXEnc * rtpspeexenc, GstRtpSPEEXEncClass * klass) +{ + GST_BASE_RTP_PAYLOAD (rtpspeexenc)->clock_rate = 8000; + GST_BASE_RTP_PAYLOAD_PT (rtpspeexenc) = 110; /* Create String */ +} + +static gboolean +gst_rtpspeexenc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "audio", FALSE, "speex", 8000); + gst_basertppayload_set_outcaps (payload, NULL); + + return TRUE; +} + +static GstFlowReturn +gst_rtpspeexenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) +{ + GstRtpSPEEXEnc *rtpspeexenc; + guint size, payload_len; + GstBuffer *outbuf; + guint8 *payload, *data; + GstClockTime timestamp; + GstFlowReturn ret; + + rtpspeexenc = GST_RTP_SPEEX_ENC (basepayload); + + size = GST_BUFFER_SIZE (buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); + + /* FIXME, only one SPEEX frame per RTP packet for now */ + payload_len = size; + + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + /* FIXME, assert for now */ + g_assert (payload_len <= GST_BASE_RTP_PAYLOAD_MTU (rtpspeexenc)); + + /* copy timestamp */ + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + /* get payload */ + payload = gst_rtpbuffer_get_payload (outbuf); + + data = GST_BUFFER_DATA (buffer); + + /* copy data in payload */ + memcpy (&payload[0], data, size); + + gst_buffer_unref (buffer); + + ret = gst_basertppayload_push (basepayload, outbuf); + + return ret; +} + +gboolean +gst_rtpspeexenc_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpspeexenc", + GST_RANK_NONE, GST_TYPE_RTP_SPEEX_ENC); +} diff --git a/gst/rtp/gstrtpspeexenc.h b/gst/rtp/gstrtpspeexenc.h new file mode 100644 index 0000000..066b272 --- /dev/null +++ b/gst/rtp/gstrtpspeexenc.h @@ -0,0 +1,52 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + + +#ifndef __GST_RTP_SPEEX_ENC_H__ +#define __GST_RTP_SPEEX_ENC_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstRtpSPEEXEnc GstRtpSPEEXEnc; +typedef struct _GstRtpSPEEXEncClass GstRtpSPEEXEncClass; + +#define GST_TYPE_RTP_SPEEX_ENC \ + (gst_rtpspeexenc_get_type()) +#define GST_RTP_SPEEX_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SPEEX_ENC,GstRtpSPEEXEnc)) +#define GST_RTP_SPEEX_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SPEEX_ENC,GstRtpSPEEXEnc)) +#define GST_IS_RTP_SPEEX_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SPEEX_ENC)) +#define GST_IS_RTP_SPEEX_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SPEEX_ENC)) + +struct _GstRtpSPEEXEnc +{ + GstBaseRTPPayload payload; +}; + +struct _GstRtpSPEEXEncClass +{ + GstBaseRTPPayloadClass parent_class; +}; + +gboolean gst_rtpspeexenc_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_SPEEX_ENC_H__ */ diff --git a/gst/rtp/gstrtpspeexpay.c b/gst/rtp/gstrtpspeexpay.c new file mode 100644 index 0000000..97e3bf3 --- /dev/null +++ b/gst/rtp/gstrtpspeexpay.c @@ -0,0 +1,149 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "gstrtpspeexenc.h" + +/* elementfactory information */ +static GstElementDetails gst_rtpspeexenc_details = { + "RTP packet parser", + "Codec/Encoder/Network", + "Encodes Speex audio into a RTP packet", + "Edgard Lima " +}; + +static GstStaticPadTemplate gst_rtpspeexenc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-speex") + ); + +static GstStaticPadTemplate gst_rtpspeexenc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " "media = (string) \"audio\", " "payload = (int) 110, " /* guaranties compatibility with Linphone + Could be [96,127] See page 34 at http://www.ietf.org/rfc/rfc3551.txt */ + "clock-rate = (int) [6000, 48000], " + "encoding-name = (string) \"speex\", " + "encoding-params = (string) \"1\"") + ); + +static gboolean gst_rtpspeexenc_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtpspeexenc_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); + +GST_BOILERPLATE (GstRtpSPEEXEnc, gst_rtpspeexenc, GstBaseRTPPayload, + GST_TYPE_BASE_RTP_PAYLOAD); + +static void +gst_rtpspeexenc_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexenc_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpspeexenc_src_template)); + gst_element_class_set_details (element_class, &gst_rtpspeexenc_details); +} + +static void +gst_rtpspeexenc_class_init (GstRtpSPEEXEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD); + + gstbasertppayload_class->set_caps = gst_rtpspeexenc_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtpspeexenc_handle_buffer; +} + +static void +gst_rtpspeexenc_init (GstRtpSPEEXEnc * rtpspeexenc, GstRtpSPEEXEncClass * klass) +{ + GST_BASE_RTP_PAYLOAD (rtpspeexenc)->clock_rate = 8000; + GST_BASE_RTP_PAYLOAD_PT (rtpspeexenc) = 110; /* Create String */ +} + +static gboolean +gst_rtpspeexenc_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "audio", FALSE, "speex", 8000); + gst_basertppayload_set_outcaps (payload, NULL); + + return TRUE; +} + +static GstFlowReturn +gst_rtpspeexenc_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) +{ + GstRtpSPEEXEnc *rtpspeexenc; + guint size, payload_len; + GstBuffer *outbuf; + guint8 *payload, *data; + GstClockTime timestamp; + GstFlowReturn ret; + + rtpspeexenc = GST_RTP_SPEEX_ENC (basepayload); + + size = GST_BUFFER_SIZE (buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); + + /* FIXME, only one SPEEX frame per RTP packet for now */ + payload_len = size; + + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + /* FIXME, assert for now */ + g_assert (payload_len <= GST_BASE_RTP_PAYLOAD_MTU (rtpspeexenc)); + + /* copy timestamp */ + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + /* get payload */ + payload = gst_rtpbuffer_get_payload (outbuf); + + data = GST_BUFFER_DATA (buffer); + + /* copy data in payload */ + memcpy (&payload[0], data, size); + + gst_buffer_unref (buffer); + + ret = gst_basertppayload_push (basepayload, outbuf); + + return ret; +} + +gboolean +gst_rtpspeexenc_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpspeexenc", + GST_RANK_NONE, GST_TYPE_RTP_SPEEX_ENC); +} diff --git a/gst/rtp/gstrtpspeexpay.h b/gst/rtp/gstrtpspeexpay.h new file mode 100644 index 0000000..066b272 --- /dev/null +++ b/gst/rtp/gstrtpspeexpay.h @@ -0,0 +1,52 @@ +/* GStreamer + * Copyright (C) <2005> Edgard Lima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + + +#ifndef __GST_RTP_SPEEX_ENC_H__ +#define __GST_RTP_SPEEX_ENC_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstRtpSPEEXEnc GstRtpSPEEXEnc; +typedef struct _GstRtpSPEEXEncClass GstRtpSPEEXEncClass; + +#define GST_TYPE_RTP_SPEEX_ENC \ + (gst_rtpspeexenc_get_type()) +#define GST_RTP_SPEEX_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SPEEX_ENC,GstRtpSPEEXEnc)) +#define GST_RTP_SPEEX_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SPEEX_ENC,GstRtpSPEEXEnc)) +#define GST_IS_RTP_SPEEX_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SPEEX_ENC)) +#define GST_IS_RTP_SPEEX_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SPEEX_ENC)) + +struct _GstRtpSPEEXEnc +{ + GstBaseRTPPayload payload; +}; + +struct _GstRtpSPEEXEncClass +{ + GstBaseRTPPayloadClass parent_class; +}; + +gboolean gst_rtpspeexenc_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_SPEEX_ENC_H__ */