diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2005-08-18 10:33:15 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2005-08-18 10:33:15 +0000 |
commit | 9a5c8cd25ef8fe33fb8b189f88725bfac5c68768 (patch) | |
tree | 8f14b039669348a7bb805c680293f30a4c560828 /gst/rtp | |
parent | a6c633b9ab883eee91c855dbec9a620acbdb944a (diff) |
gst/rtp/: Remove old code that is now in gst-libs/gst/rtp/.
Original commit message from CVS:
* gst/rtp/Makefile.am:
* gst/rtp/gstrtp-common.h:
* gst/rtp/gstrtp.c: (plugin_init):
* gst/rtp/gstrtpL16enc.h:
* gst/rtp/gstrtpdec.c: (gst_rtpdec_get_type),
(gst_rtpdec_class_init), (gst_rtpdec_chain_rtp),
(gst_rtpdec_chain_rtcp), (gst_rtpdec_change_state),
(gst_rtpdec_plugin_init):
* gst/rtp/gstrtph263pdec.c: (gst_rtph263pdec_get_type),
(gst_rtph263pdec_base_init), (gst_rtph263pdec_class_init),
(gst_rtph263pdec_init), (gst_rtph263pdec_chain),
(gst_rtph263pdec_set_property), (gst_rtph263pdec_get_property),
(gst_rtph263pdec_change_state), (gst_rtph263pdec_plugin_init):
* gst/rtp/gstrtph263pdec.h:
* gst/rtp/gstrtph263penc.c: (gst_rtph263penc_get_type),
(gst_rtph263penc_base_init), (gst_rtph263penc_class_init),
(gst_rtph263penc_init), (gst_rtph263penc_flush),
(gst_rtph263penc_chain), (gst_rtph263penc_set_property),
(gst_rtph263penc_get_property), (gst_rtph263penc_change_state),
(gst_rtph263penc_plugin_init):
* gst/rtp/gstrtph263penc.h:
* gst/rtp/gstrtpmpadec.c: (gst_rtpmpadec_get_type),
(gst_rtpmpadec_base_init), (gst_rtpmpadec_class_init),
(gst_rtpmpadec_init), (gst_rtpmpadec_chain),
(gst_rtpmpadec_set_property), (gst_rtpmpadec_get_property),
(gst_rtpmpadec_change_state), (gst_rtpmpadec_plugin_init):
* gst/rtp/gstrtpmpadec.h:
* gst/rtp/gstrtpmpaenc.c: (gst_rtpmpaenc_get_type),
(gst_rtpmpaenc_base_init), (gst_rtpmpaenc_class_init),
(gst_rtpmpaenc_init), (gst_rtpmpaenc_flush), (gst_rtpmpaenc_chain),
(gst_rtpmpaenc_set_property), (gst_rtpmpaenc_get_property),
(gst_rtpmpaenc_change_state), (gst_rtpmpaenc_plugin_init):
* gst/rtp/gstrtpmpaenc.h:
* gst/rtp/rtp-packet.c:
* gst/rtp/rtp-packet.h:
Remove old code that is now in gst-libs/gst/rtp/.
Added some payload/depayloaders.
* gst/udp/gstudpsink.c: (gst_udpsink_class_init):
Fix port number range.
Diffstat (limited to 'gst/rtp')
-rw-r--r-- | gst/rtp/Makefile.am | 24 | ||||
-rw-r--r-- | gst/rtp/gstrtp-common.h | 50 | ||||
-rw-r--r-- | gst/rtp/gstrtp.c | 16 | ||||
-rw-r--r-- | gst/rtp/gstrtpL16enc.h | 12 | ||||
-rw-r--r-- | gst/rtp/gstrtpL16pay.h | 12 | ||||
-rw-r--r-- | gst/rtp/gstrtpdec.c | 11 | ||||
-rw-r--r-- | gst/rtp/gstrtpdepay.c | 11 | ||||
-rw-r--r-- | gst/rtp/gstrtph263pdec.c | 317 | ||||
-rw-r--r-- | gst/rtp/gstrtph263pdec.h | 63 | ||||
-rw-r--r-- | gst/rtp/gstrtph263pdepay.c | 317 | ||||
-rw-r--r-- | gst/rtp/gstrtph263pdepay.h | 63 | ||||
-rw-r--r-- | gst/rtp/gstrtph263penc.c | 303 | ||||
-rw-r--r-- | gst/rtp/gstrtph263penc.h | 64 | ||||
-rw-r--r-- | gst/rtp/gstrtph263ppay.c | 303 | ||||
-rw-r--r-- | gst/rtp/gstrtph263ppay.h | 64 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpadec.c | 272 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpadec.h | 60 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpadepay.c | 272 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpadepay.h | 60 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpaenc.c | 331 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpaenc.h | 65 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpapay.c | 331 | ||||
-rw-r--r-- | gst/rtp/gstrtpmpapay.h | 65 | ||||
-rw-r--r-- | gst/rtp/rtp-packet.c | 307 | ||||
-rw-r--r-- | gst/rtp/rtp-packet.h | 106 |
25 files changed, 3007 insertions, 492 deletions
diff --git a/gst/rtp/Makefile.am b/gst/rtp/Makefile.am index 436cc27a..b08df858 100644 --- a/gst/rtp/Makefile.am +++ b/gst/rtp/Makefile.am @@ -1,10 +1,24 @@ plugin_LTLIBRARIES = libgstrtp.la -libgstrtp_la_SOURCES = gstrtp.c gstrtpdec.c +libgstrtp_la_SOURCES = gstrtp.c \ + gstrtpdec.c \ + gstrtpmpadec.c \ + gstrtpmpaenc.c \ + gstrtph263pdec.c \ + gstrtph263penc.c -#gstrtpL16enc.c gstrtpL16parse.c gstrtpgsmenc.c gstrtpgsmparse.c rtp-packet.c +#gstrtpL16enc.c gstrtpL16parse.c gstrtpgsmenc.c gstrtpgsmparse.c -libgstrtp_la_CFLAGS = $(GST_CFLAGS) -libgstrtp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstrtp_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgstrtp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstrtp_la_LIBADD = $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ + -lgstrtp-@GST_MAJORMINOR@ -noinst_HEADERS = gstrtpL16enc.h gstrtpL16parse.h gstrtpgsmenc.h gstrtpgsmparse.h gstrtp-common.h rtp-packet.h gstrtpdec.h +noinst_HEADERS = gstrtpL16enc.h \ + gstrtpL16parse.h \ + gstrtpgsmenc.h \ + gstrtpgsmparse.h \ + gstrtpmpadec.h \ + gstrtpmpaenc.h \ + gstrtph263pdec.h \ + gstrtph263penc.h diff --git a/gst/rtp/gstrtp-common.h b/gst/rtp/gstrtp-common.h deleted file mode 100644 index fb675189..00000000 --- a/gst/rtp/gstrtp-common.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Gnome-Streamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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 details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_RTP_COMMON_H__ -#define __GST_RTP_COMMON_H__ - -#define RTP_VERSION 2 - -typedef enum -{ -/* Audio: */ - PAYLOAD_PCMU = 0, /* ITU-T G.711. mu-law audio (RFC 3551) */ - PAYLOAD_GSM = 3, - PAYLOAD_PCMA = 8, /* ITU-T G.711 A-law audio (RFC 3551) */ - PAYLOAD_L16_STEREO = 10, - PAYLOAD_L16_MONO = 11, - PAYLOAD_MPA = 14, /* Audio MPEG 1-3 */ - PAYLOAD_G723_63 = 16, /* Not standard */ - PAYLOAD_G723_53 = 17, /* Not standard */ - PAYLOAD_TS48 = 18, /* Not standard */ - PAYLOAD_TS41 = 19, /* Not standard */ - PAYLOAD_G728 = 20, /* Not standard */ - PAYLOAD_G729 = 21, /* Not standard */ - -/* Video: */ - PAYLOAD_MPV = 32, /* Video MPEG 1 & 2 */ - -/* BOTH */ - PAYLOAD_BMPEG = 34 /* Not Standard */ -} -rtp_payload_t; - -#endif diff --git a/gst/rtp/gstrtp.c b/gst/rtp/gstrtp.c index 8ea85ae9..9715e9a8 100644 --- a/gst/rtp/gstrtp.c +++ b/gst/rtp/gstrtp.c @@ -22,6 +22,10 @@ #endif #include "gstrtpdec.h" +#include "gstrtpmpaenc.h" +#include "gstrtpmpadec.h" +#include "gstrtph263pdec.h" +#include "gstrtph263penc.h" static gboolean plugin_init (GstPlugin * plugin) @@ -29,6 +33,18 @@ plugin_init (GstPlugin * plugin) if (!gst_rtpdec_plugin_init (plugin)) return FALSE; + if (!gst_rtpmpadec_plugin_init (plugin)) + return FALSE; + + if (!gst_rtpmpaenc_plugin_init (plugin)) + return FALSE; + + if (!gst_rtph263penc_plugin_init (plugin)) + return FALSE; + + if (!gst_rtph263pdec_plugin_init (plugin)) + return FALSE; + return TRUE; } diff --git a/gst/rtp/gstrtpL16enc.h b/gst/rtp/gstrtpL16enc.h index 15ed92f6..31332ea4 100644 --- a/gst/rtp/gstrtpL16enc.h +++ b/gst/rtp/gstrtpL16enc.h @@ -22,13 +22,8 @@ #define __GST_RTP_L16_ENC_H__ #include <gst/gst.h> -#include "rtp-packet.h" -#include "gstrtp-common.h" -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +G_BEGIN_DECLS /* Definition of structure storing data for this element. */ typedef struct _GstRtpL16Enc GstRtpL16Enc; @@ -72,9 +67,6 @@ struct _GstRtpL16EncClass gboolean gst_rtpL16enc_plugin_init (GstPlugin * plugin); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - +G_END_DECLS #endif /* __GST_RTP_L16_ENC_H__ */ diff --git a/gst/rtp/gstrtpL16pay.h b/gst/rtp/gstrtpL16pay.h index 15ed92f6..31332ea4 100644 --- a/gst/rtp/gstrtpL16pay.h +++ b/gst/rtp/gstrtpL16pay.h @@ -22,13 +22,8 @@ #define __GST_RTP_L16_ENC_H__ #include <gst/gst.h> -#include "rtp-packet.h" -#include "gstrtp-common.h" -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ +G_BEGIN_DECLS /* Definition of structure storing data for this element. */ typedef struct _GstRtpL16Enc GstRtpL16Enc; @@ -72,9 +67,6 @@ struct _GstRtpL16EncClass gboolean gst_rtpL16enc_plugin_init (GstPlugin * plugin); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - +G_END_DECLS #endif /* __GST_RTP_L16_ENC_H__ */ diff --git a/gst/rtp/gstrtpdec.c b/gst/rtp/gstrtpdec.c index 6e7906e0..bb8a7afd 100644 --- a/gst/rtp/gstrtpdec.c +++ b/gst/rtp/gstrtpdec.c @@ -20,6 +20,9 @@ #include "gstrtpdec.h" +GST_DEBUG_CATEGORY (rtpdec_debug); +#define GST_CAT_DEFAULT (rtpdec_debug) + /* elementfactory information */ static GstElementDetails rtpdec_details = GST_ELEMENT_DETAILS ("RTP Decoder", "Codec/Parser/Network", @@ -137,6 +140,8 @@ gst_rtpdec_class_init (gpointer g_class) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); gstelement_class->change_state = gst_rtpdec_change_state; + + GST_DEBUG_CATEGORY_INIT (rtpdec_debug, "rtpdec", 0, "RTP decoder"); } static void @@ -176,14 +181,16 @@ gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer) src = GST_RTPDEC (GST_PAD_PARENT (pad)); - g_print ("got rtp packet\n"); + GST_DEBUG ("got rtp packet"); return gst_pad_push (src->src_rtp, buffer); } static GstFlowReturn gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer) { - g_print ("got rtcp packet\n"); + GST_DEBUG ("got rtcp packet"); + + gst_buffer_unref (buffer); return GST_FLOW_OK; } diff --git a/gst/rtp/gstrtpdepay.c b/gst/rtp/gstrtpdepay.c index 6e7906e0..bb8a7afd 100644 --- a/gst/rtp/gstrtpdepay.c +++ b/gst/rtp/gstrtpdepay.c @@ -20,6 +20,9 @@ #include "gstrtpdec.h" +GST_DEBUG_CATEGORY (rtpdec_debug); +#define GST_CAT_DEFAULT (rtpdec_debug) + /* elementfactory information */ static GstElementDetails rtpdec_details = GST_ELEMENT_DETAILS ("RTP Decoder", "Codec/Parser/Network", @@ -137,6 +140,8 @@ gst_rtpdec_class_init (gpointer g_class) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); gstelement_class->change_state = gst_rtpdec_change_state; + + GST_DEBUG_CATEGORY_INIT (rtpdec_debug, "rtpdec", 0, "RTP decoder"); } static void @@ -176,14 +181,16 @@ gst_rtpdec_chain_rtp (GstPad * pad, GstBuffer * buffer) src = GST_RTPDEC (GST_PAD_PARENT (pad)); - g_print ("got rtp packet\n"); + GST_DEBUG ("got rtp packet"); return gst_pad_push (src->src_rtp, buffer); } static GstFlowReturn gst_rtpdec_chain_rtcp (GstPad * pad, GstBuffer * buffer) { - g_print ("got rtcp packet\n"); + GST_DEBUG ("got rtcp packet"); + + gst_buffer_unref (buffer); return GST_FLOW_OK; } diff --git a/gst/rtp/gstrtph263pdec.c b/gst/rtp/gstrtph263pdec.c new file mode 100644 index 00000000..5061402d --- /dev/null +++ b/gst/rtp/gstrtph263pdec.c @@ -0,0 +1,317 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <string.h> + +#include <gst/rtp/gstrtpbuffer.h> +#include "gstrtph263pdec.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_h263pdec_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts H263+ video from RTP packets (RFC 2429)", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpH263PDec signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_FREQUENCY +}; + +static GstStaticPadTemplate gst_rtph263pdec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h263") + ); + +static GstStaticPadTemplate gst_rtph263pdec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass); +static void gst_rtph263pdec_base_init (GstRtpH263PDecClass * klass); +static void gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec); + +static GstFlowReturn gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtph263pdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtph263pdec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtph263pdec_change_state (GstElement * + element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtph263pdec_get_type (void) +{ + static GType rtph263pdec_type = 0; + + if (!rtph263pdec_type) { + static const GTypeInfo rtph263pdec_info = { + sizeof (GstRtpH263PDecClass), + (GBaseInitFunc) gst_rtph263pdec_base_init, + NULL, + (GClassInitFunc) gst_rtph263pdec_class_init, + NULL, + NULL, + sizeof (GstRtpH263PDec), + 0, + (GInstanceInitFunc) gst_rtph263pdec_init, + }; + + rtph263pdec_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpH263PDec", + &rtph263pdec_info, 0); + } + return rtph263pdec_type; +} + +static void +gst_rtph263pdec_base_init (GstRtpH263PDecClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263pdec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263pdec_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_h263pdec_details); +} + +static void +gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtph263pdec_set_property; + gobject_class->get_property = gst_rtph263pdec_get_property; + + gstelement_class->change_state = gst_rtph263pdec_change_state; +} + +static void +gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec) +{ + rtph263pdec->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263pdec_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtph263pdec), rtph263pdec->srcpad); + + rtph263pdec->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263pdec_sink_template), "sink"); + gst_pad_set_chain_function (rtph263pdec->sinkpad, gst_rtph263pdec_chain); + gst_element_add_pad (GST_ELEMENT (rtph263pdec), rtph263pdec->sinkpad); + + rtph263pdec->adapter = gst_adapter_new (); +} + +static GstFlowReturn +gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buf) +{ + GstRtpH263PDec *rtph263pdec; + GstBuffer *outbuf; + GstFlowReturn ret; + GstRTPPayload pt; + + rtph263pdec = GST_RTP_H263P_DEC (GST_OBJECT_PARENT (pad)); + + if (!gst_rtpbuffer_validate (buf)) + goto bad_packet; + + if ((pt = gst_rtpbuffer_get_payload_type (buf)) != 0) + goto bad_payload; + + { + gint payload_len; + guint8 *payload; + gboolean P, V, M; + guint32 timestamp; + guint header_len; + guint8 PLEN; + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + header_len = 2; + + M = gst_rtpbuffer_get_marker (buf); + P = payload[0] & 0x04 ? TRUE : FALSE; + V = payload[0] & 0x02 ? TRUE : FALSE; + PLEN = ((payload[0] & 0x1) << 5) | (payload[1] >> 3); + + if (V) { + header_len++; + } + if (PLEN) { + header_len += PLEN; + } + + if (P) { + header_len -= 2; + payload[header_len] = 0; + payload[header_len + 1] = 0; + } + + /* strip off header */ + payload += header_len; + payload_len -= header_len; + + timestamp = gst_rtpbuffer_get_timestamp (buf); + + if (M) { + /* frame is completed: append to previous, push it out */ + guint avail; + guint8 *data; + + avail = gst_adapter_available (rtph263pdec->adapter); + + outbuf = gst_buffer_new_and_alloc (avail + payload_len); + + /* prepend previous data */ + if (avail > 0) { + data = (guint8 *) gst_adapter_peek (rtph263pdec->adapter, avail); + memcpy (GST_BUFFER_DATA (outbuf), data, avail); + gst_adapter_flush (rtph263pdec->adapter, avail); + } + memcpy (GST_BUFFER_DATA (outbuf) + avail, payload, payload_len); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 90000; + gst_buffer_set_caps (outbuf, + (GstCaps *) gst_pad_get_pad_template_caps (rtph263pdec->srcpad)); + + ret = gst_pad_push (rtph263pdec->srcpad, outbuf); + } else { + /* frame not completed: store in adapter */ + outbuf = gst_buffer_new_and_alloc (payload_len); + + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + + gst_adapter_push (rtph263pdec->adapter, outbuf); + + ret = GST_FLOW_OK; + } + + gst_buffer_unref (buf); + } + + return ret; + +bad_packet: + { + GST_DEBUG ("Packet does not validate"); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +bad_payload: + { + GST_DEBUG ("Unexpected payload type %u", pt); + + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static void +gst_rtph263pdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpH263PDec *rtph263pdec; + + rtph263pdec = GST_RTP_H263P_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtph263pdec_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpH263PDec *rtph263pdec; + + rtph263pdec = GST_RTP_H263P_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtph263pdec_change_state (GstElement * element) +{ + GstRtpH263PDec *rtph263pdec; + gint transition; + GstElementStateReturn ret; + + rtph263pdec = GST_RTP_H263P_DEC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtph263pdec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtph263pdec", + GST_RANK_NONE, GST_TYPE_RTP_H263P_DEC); +} diff --git a/gst/rtp/gstrtph263pdec.h b/gst/rtp/gstrtph263pdec.h new file mode 100644 index 00000000..c7bbc74d --- /dev/null +++ b/gst/rtp/gstrtph263pdec.h @@ -0,0 +1,63 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_H263P_DEC_H__ +#define __GST_RTP_H263P_DEC_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_H263P_DEC \ + (gst_rtph263pdec_get_type()) +#define GST_RTP_H263P_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_H263P_DEC,GstRtpH263PDec)) +#define GST_RTP_H263P_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_H263P_DEC,GstRtpH263PDec)) +#define GST_IS_RTP_H263P_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_H263P_DEC)) +#define GST_IS_RTP_H263P_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_H263P_DEC)) + +typedef struct _GstRtpH263PDec GstRtpH263PDec; +typedef struct _GstRtpH263PDecClass GstRtpH263PDecClass; + +struct _GstRtpH263PDec +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + + guint frequency; +}; + +struct _GstRtpH263PDecClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtph263pdec_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_H263P_DEC_H__ */ diff --git a/gst/rtp/gstrtph263pdepay.c b/gst/rtp/gstrtph263pdepay.c new file mode 100644 index 00000000..5061402d --- /dev/null +++ b/gst/rtp/gstrtph263pdepay.c @@ -0,0 +1,317 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <string.h> + +#include <gst/rtp/gstrtpbuffer.h> +#include "gstrtph263pdec.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_h263pdec_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts H263+ video from RTP packets (RFC 2429)", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpH263PDec signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_FREQUENCY +}; + +static GstStaticPadTemplate gst_rtph263pdec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h263") + ); + +static GstStaticPadTemplate gst_rtph263pdec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass); +static void gst_rtph263pdec_base_init (GstRtpH263PDecClass * klass); +static void gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec); + +static GstFlowReturn gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtph263pdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtph263pdec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtph263pdec_change_state (GstElement * + element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtph263pdec_get_type (void) +{ + static GType rtph263pdec_type = 0; + + if (!rtph263pdec_type) { + static const GTypeInfo rtph263pdec_info = { + sizeof (GstRtpH263PDecClass), + (GBaseInitFunc) gst_rtph263pdec_base_init, + NULL, + (GClassInitFunc) gst_rtph263pdec_class_init, + NULL, + NULL, + sizeof (GstRtpH263PDec), + 0, + (GInstanceInitFunc) gst_rtph263pdec_init, + }; + + rtph263pdec_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpH263PDec", + &rtph263pdec_info, 0); + } + return rtph263pdec_type; +} + +static void +gst_rtph263pdec_base_init (GstRtpH263PDecClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263pdec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263pdec_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_h263pdec_details); +} + +static void +gst_rtph263pdec_class_init (GstRtpH263PDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtph263pdec_set_property; + gobject_class->get_property = gst_rtph263pdec_get_property; + + gstelement_class->change_state = gst_rtph263pdec_change_state; +} + +static void +gst_rtph263pdec_init (GstRtpH263PDec * rtph263pdec) +{ + rtph263pdec->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263pdec_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtph263pdec), rtph263pdec->srcpad); + + rtph263pdec->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263pdec_sink_template), "sink"); + gst_pad_set_chain_function (rtph263pdec->sinkpad, gst_rtph263pdec_chain); + gst_element_add_pad (GST_ELEMENT (rtph263pdec), rtph263pdec->sinkpad); + + rtph263pdec->adapter = gst_adapter_new (); +} + +static GstFlowReturn +gst_rtph263pdec_chain (GstPad * pad, GstBuffer * buf) +{ + GstRtpH263PDec *rtph263pdec; + GstBuffer *outbuf; + GstFlowReturn ret; + GstRTPPayload pt; + + rtph263pdec = GST_RTP_H263P_DEC (GST_OBJECT_PARENT (pad)); + + if (!gst_rtpbuffer_validate (buf)) + goto bad_packet; + + if ((pt = gst_rtpbuffer_get_payload_type (buf)) != 0) + goto bad_payload; + + { + gint payload_len; + guint8 *payload; + gboolean P, V, M; + guint32 timestamp; + guint header_len; + guint8 PLEN; + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + header_len = 2; + + M = gst_rtpbuffer_get_marker (buf); + P = payload[0] & 0x04 ? TRUE : FALSE; + V = payload[0] & 0x02 ? TRUE : FALSE; + PLEN = ((payload[0] & 0x1) << 5) | (payload[1] >> 3); + + if (V) { + header_len++; + } + if (PLEN) { + header_len += PLEN; + } + + if (P) { + header_len -= 2; + payload[header_len] = 0; + payload[header_len + 1] = 0; + } + + /* strip off header */ + payload += header_len; + payload_len -= header_len; + + timestamp = gst_rtpbuffer_get_timestamp (buf); + + if (M) { + /* frame is completed: append to previous, push it out */ + guint avail; + guint8 *data; + + avail = gst_adapter_available (rtph263pdec->adapter); + + outbuf = gst_buffer_new_and_alloc (avail + payload_len); + + /* prepend previous data */ + if (avail > 0) { + data = (guint8 *) gst_adapter_peek (rtph263pdec->adapter, avail); + memcpy (GST_BUFFER_DATA (outbuf), data, avail); + gst_adapter_flush (rtph263pdec->adapter, avail); + } + memcpy (GST_BUFFER_DATA (outbuf) + avail, payload, payload_len); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 90000; + gst_buffer_set_caps (outbuf, + (GstCaps *) gst_pad_get_pad_template_caps (rtph263pdec->srcpad)); + + ret = gst_pad_push (rtph263pdec->srcpad, outbuf); + } else { + /* frame not completed: store in adapter */ + outbuf = gst_buffer_new_and_alloc (payload_len); + + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + + gst_adapter_push (rtph263pdec->adapter, outbuf); + + ret = GST_FLOW_OK; + } + + gst_buffer_unref (buf); + } + + return ret; + +bad_packet: + { + GST_DEBUG ("Packet does not validate"); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +bad_payload: + { + GST_DEBUG ("Unexpected payload type %u", pt); + + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static void +gst_rtph263pdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpH263PDec *rtph263pdec; + + rtph263pdec = GST_RTP_H263P_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtph263pdec_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpH263PDec *rtph263pdec; + + rtph263pdec = GST_RTP_H263P_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtph263pdec_change_state (GstElement * element) +{ + GstRtpH263PDec *rtph263pdec; + gint transition; + GstElementStateReturn ret; + + rtph263pdec = GST_RTP_H263P_DEC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtph263pdec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtph263pdec", + GST_RANK_NONE, GST_TYPE_RTP_H263P_DEC); +} diff --git a/gst/rtp/gstrtph263pdepay.h b/gst/rtp/gstrtph263pdepay.h new file mode 100644 index 00000000..c7bbc74d --- /dev/null +++ b/gst/rtp/gstrtph263pdepay.h @@ -0,0 +1,63 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_H263P_DEC_H__ +#define __GST_RTP_H263P_DEC_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_H263P_DEC \ + (gst_rtph263pdec_get_type()) +#define GST_RTP_H263P_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_H263P_DEC,GstRtpH263PDec)) +#define GST_RTP_H263P_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_H263P_DEC,GstRtpH263PDec)) +#define GST_IS_RTP_H263P_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_H263P_DEC)) +#define GST_IS_RTP_H263P_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_H263P_DEC)) + +typedef struct _GstRtpH263PDec GstRtpH263PDec; +typedef struct _GstRtpH263PDecClass GstRtpH263PDecClass; + +struct _GstRtpH263PDec +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + + guint frequency; +}; + +struct _GstRtpH263PDecClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtph263pdec_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_H263P_DEC_H__ */ diff --git a/gst/rtp/gstrtph263penc.c b/gst/rtp/gstrtph263penc.c new file mode 100644 index 00000000..14c28c03 --- /dev/null +++ b/gst/rtp/gstrtph263penc.c @@ -0,0 +1,303 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <string.h> + +#include <gst/rtp/gstrtpbuffer.h> + +#include "gstrtph263penc.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_h263penc_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts H263+ video from RTP packets", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpH263PEnc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_MTU 1024 + +enum +{ + PROP_0, + PROP_MTU +}; + +static GstStaticPadTemplate gst_rtph263penc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h263") + ); + +static GstStaticPadTemplate gst_rtph263penc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtph263penc_class_init (GstRtpH263PEncClass * klass); +static void gst_rtph263penc_base_init (GstRtpH263PEncClass * klass); +static void gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc); + +static GstFlowReturn gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtph263penc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtph263penc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtph263penc_change_state (GstElement * + element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtph263penc_get_type (void) +{ + static GType rtph263penc_type = 0; + + if (!rtph263penc_type) { + static const GTypeInfo rtph263penc_info = { + sizeof (GstRtpH263PEncClass), + (GBaseInitFunc) gst_rtph263penc_base_init, + NULL, + (GClassInitFunc) gst_rtph263penc_class_init, + NULL, + NULL, + sizeof (GstRtpH263PEnc), + 0, + (GInstanceInitFunc) gst_rtph263penc_init, + }; + + rtph263penc_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpH263PEnc", + &rtph263penc_info, 0); + } + return rtph263penc_type; +} + +static void +gst_rtph263penc_base_init (GstRtpH263PEncClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263penc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263penc_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_h263penc_details); +} + +static void +gst_rtph263penc_class_init (GstRtpH263PEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtph263penc_set_property; + gobject_class->get_property = gst_rtph263penc_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, + g_param_spec_uint ("mtu", "MTU", + "Maximum size of one packet", + 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); + + gstelement_class->change_state = gst_rtph263penc_change_state; +} + +static void +gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc) +{ + rtph263penc->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263penc_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->srcpad); + + rtph263penc->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263penc_sink_template), "sink"); + gst_pad_set_chain_function (rtph263penc->sinkpad, gst_rtph263penc_chain); + gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->sinkpad); + + rtph263penc->adapter = gst_adapter_new (); + rtph263penc->mtu = DEFAULT_MTU; +} + +static GstFlowReturn +gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + gboolean fragmented; + + avail = gst_adapter_available (rtph263penc->adapter); + if (avail == 0) + return GST_FLOW_OK; + + fragmented = FALSE; + + while (avail > 0) { + guint towrite; + guint8 *payload; + guint8 *data; + guint payload_len; + gint header_len; + + /* FIXME, do better mtu packing, header len etc should be + * included in this calculation. */ + towrite = MIN (avail, rtph263penc->mtu); + /* for fragmented frames we need 2 bytes header, for other + * frames we must reuse the first 2 bytes of the data as the + * header */ + header_len = (fragmented ? 2 : 0); + payload_len = header_len + towrite; + + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + gst_rtpbuffer_set_padding (outbuf, 0); + gst_rtpbuffer_set_timestamp (outbuf, + rtph263penc->first_ts * 90000 / GST_SECOND); + gst_rtpbuffer_set_payload_type (outbuf, 0); + /* last fragment gets the marker bit set */ + gst_rtpbuffer_set_marker (outbuf, avail > towrite ? 0 : 1); + + payload = gst_rtpbuffer_get_payload (outbuf); + + data = (guint8 *) gst_adapter_peek (rtph263penc->adapter, towrite); + memcpy (&payload[header_len], data, towrite); + + payload[0] = fragmented ? 0x00 : 0x04; + payload[1] = 0; + + GST_BUFFER_TIMESTAMP (outbuf) = rtph263penc->first_ts; + gst_adapter_flush (rtph263penc->adapter, towrite); + + ret = gst_pad_push (rtph263penc->srcpad, outbuf); + + avail -= towrite; + fragmented = TRUE; + } + + return ret; +} + +static GstFlowReturn +gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstRtpH263PEnc *rtph263penc; + GstFlowReturn ret; + guint size; + + rtph263penc = GST_RTP_H263P_ENC (GST_OBJECT_PARENT (pad)); + + size = GST_BUFFER_SIZE (buffer); + rtph263penc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + + /* we always encode and flush a full picture */ + gst_adapter_push (rtph263penc->adapter, buffer); + ret = gst_rtph263penc_flush (rtph263penc); + + return ret; +} + +static void +gst_rtph263penc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpH263PEnc *rtph263penc; + + rtph263penc = GST_RTP_H263P_ENC (object); + + switch (prop_id) { + case PROP_MTU: + rtph263penc->mtu = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtph263penc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpH263PEnc *rtph263penc; + + rtph263penc = GST_RTP_H263P_ENC (object); + + switch (prop_id) { + case PROP_MTU: + g_value_set_uint (value, rtph263penc->mtu); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtph263penc_change_state (GstElement * element) +{ + GstRtpH263PEnc *rtph263penc; + gint transition; + GstElementStateReturn ret; + + rtph263penc = GST_RTP_H263P_ENC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtph263penc_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtph263penc", + GST_RANK_NONE, GST_TYPE_RTP_H263P_ENC); +} diff --git a/gst/rtp/gstrtph263penc.h b/gst/rtp/gstrtph263penc.h new file mode 100644 index 00000000..3d0f6e24 --- /dev/null +++ b/gst/rtp/gstrtph263penc.h @@ -0,0 +1,64 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_H263P_ENC_H__ +#define __GST_RTP_H263P_ENC_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_H263P_ENC \ + (gst_rtph263penc_get_type()) +#define GST_RTP_H263P_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_H263P_ENC,GstRtpH263PEnc)) +#define GST_RTP_H263P_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_H263P_ENC,GstRtpH263PEnc)) +#define GST_IS_RTP_H263P_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_H263P_ENC)) +#define GST_IS_RTP_H263P_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_H263P_ENC)) + +typedef struct _GstRtpH263PEnc GstRtpH263PEnc; +typedef struct _GstRtpH263PEncClass GstRtpH263PEncClass; + +struct _GstRtpH263PEnc +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + GstClockTime first_ts; + + guint mtu; +}; + +struct _GstRtpH263PEncClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtph263penc_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_H263P_ENC_H__ */ diff --git a/gst/rtp/gstrtph263ppay.c b/gst/rtp/gstrtph263ppay.c new file mode 100644 index 00000000..14c28c03 --- /dev/null +++ b/gst/rtp/gstrtph263ppay.c @@ -0,0 +1,303 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <string.h> + +#include <gst/rtp/gstrtpbuffer.h> + +#include "gstrtph263penc.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_h263penc_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts H263+ video from RTP packets", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpH263PEnc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_MTU 1024 + +enum +{ + PROP_0, + PROP_MTU +}; + +static GstStaticPadTemplate gst_rtph263penc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h263") + ); + +static GstStaticPadTemplate gst_rtph263penc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtph263penc_class_init (GstRtpH263PEncClass * klass); +static void gst_rtph263penc_base_init (GstRtpH263PEncClass * klass); +static void gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc); + +static GstFlowReturn gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtph263penc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtph263penc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtph263penc_change_state (GstElement * + element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtph263penc_get_type (void) +{ + static GType rtph263penc_type = 0; + + if (!rtph263penc_type) { + static const GTypeInfo rtph263penc_info = { + sizeof (GstRtpH263PEncClass), + (GBaseInitFunc) gst_rtph263penc_base_init, + NULL, + (GClassInitFunc) gst_rtph263penc_class_init, + NULL, + NULL, + sizeof (GstRtpH263PEnc), + 0, + (GInstanceInitFunc) gst_rtph263penc_init, + }; + + rtph263penc_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpH263PEnc", + &rtph263penc_info, 0); + } + return rtph263penc_type; +} + +static void +gst_rtph263penc_base_init (GstRtpH263PEncClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263penc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtph263penc_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_h263penc_details); +} + +static void +gst_rtph263penc_class_init (GstRtpH263PEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtph263penc_set_property; + gobject_class->get_property = gst_rtph263penc_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, + g_param_spec_uint ("mtu", "MTU", + "Maximum size of one packet", + 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); + + gstelement_class->change_state = gst_rtph263penc_change_state; +} + +static void +gst_rtph263penc_init (GstRtpH263PEnc * rtph263penc) +{ + rtph263penc->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263penc_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->srcpad); + + rtph263penc->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtph263penc_sink_template), "sink"); + gst_pad_set_chain_function (rtph263penc->sinkpad, gst_rtph263penc_chain); + gst_element_add_pad (GST_ELEMENT (rtph263penc), rtph263penc->sinkpad); + + rtph263penc->adapter = gst_adapter_new (); + rtph263penc->mtu = DEFAULT_MTU; +} + +static GstFlowReturn +gst_rtph263penc_flush (GstRtpH263PEnc * rtph263penc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + gboolean fragmented; + + avail = gst_adapter_available (rtph263penc->adapter); + if (avail == 0) + return GST_FLOW_OK; + + fragmented = FALSE; + + while (avail > 0) { + guint towrite; + guint8 *payload; + guint8 *data; + guint payload_len; + gint header_len; + + /* FIXME, do better mtu packing, header len etc should be + * included in this calculation. */ + towrite = MIN (avail, rtph263penc->mtu); + /* for fragmented frames we need 2 bytes header, for other + * frames we must reuse the first 2 bytes of the data as the + * header */ + header_len = (fragmented ? 2 : 0); + payload_len = header_len + towrite; + + outbuf = gst_rtpbuffer_new_allocate (payload_len, 0, 0); + gst_rtpbuffer_set_padding (outbuf, 0); + gst_rtpbuffer_set_timestamp (outbuf, + rtph263penc->first_ts * 90000 / GST_SECOND); + gst_rtpbuffer_set_payload_type (outbuf, 0); + /* last fragment gets the marker bit set */ + gst_rtpbuffer_set_marker (outbuf, avail > towrite ? 0 : 1); + + payload = gst_rtpbuffer_get_payload (outbuf); + + data = (guint8 *) gst_adapter_peek (rtph263penc->adapter, towrite); + memcpy (&payload[header_len], data, towrite); + + payload[0] = fragmented ? 0x00 : 0x04; + payload[1] = 0; + + GST_BUFFER_TIMESTAMP (outbuf) = rtph263penc->first_ts; + gst_adapter_flush (rtph263penc->adapter, towrite); + + ret = gst_pad_push (rtph263penc->srcpad, outbuf); + + avail -= towrite; + fragmented = TRUE; + } + + return ret; +} + +static GstFlowReturn +gst_rtph263penc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstRtpH263PEnc *rtph263penc; + GstFlowReturn ret; + guint size; + + rtph263penc = GST_RTP_H263P_ENC (GST_OBJECT_PARENT (pad)); + + size = GST_BUFFER_SIZE (buffer); + rtph263penc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + + /* we always encode and flush a full picture */ + gst_adapter_push (rtph263penc->adapter, buffer); + ret = gst_rtph263penc_flush (rtph263penc); + + return ret; +} + +static void +gst_rtph263penc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpH263PEnc *rtph263penc; + + rtph263penc = GST_RTP_H263P_ENC (object); + + switch (prop_id) { + case PROP_MTU: + rtph263penc->mtu = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtph263penc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpH263PEnc *rtph263penc; + + rtph263penc = GST_RTP_H263P_ENC (object); + + switch (prop_id) { + case PROP_MTU: + g_value_set_uint (value, rtph263penc->mtu); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtph263penc_change_state (GstElement * element) +{ + GstRtpH263PEnc *rtph263penc; + gint transition; + GstElementStateReturn ret; + + rtph263penc = GST_RTP_H263P_ENC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtph263penc_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtph263penc", + GST_RANK_NONE, GST_TYPE_RTP_H263P_ENC); +} diff --git a/gst/rtp/gstrtph263ppay.h b/gst/rtp/gstrtph263ppay.h new file mode 100644 index 00000000..3d0f6e24 --- /dev/null +++ b/gst/rtp/gstrtph263ppay.h @@ -0,0 +1,64 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_H263P_ENC_H__ +#define __GST_RTP_H263P_ENC_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_H263P_ENC \ + (gst_rtph263penc_get_type()) +#define GST_RTP_H263P_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_H263P_ENC,GstRtpH263PEnc)) +#define GST_RTP_H263P_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_H263P_ENC,GstRtpH263PEnc)) +#define GST_IS_RTP_H263P_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_H263P_ENC)) +#define GST_IS_RTP_H263P_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_H263P_ENC)) + +typedef struct _GstRtpH263PEnc GstRtpH263PEnc; +typedef struct _GstRtpH263PEncClass GstRtpH263PEncClass; + +struct _GstRtpH263PEnc +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + GstClockTime first_ts; + + guint mtu; +}; + +struct _GstRtpH263PEncClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtph263penc_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_H263P_ENC_H__ */ diff --git a/gst/rtp/gstrtpmpadec.c b/gst/rtp/gstrtpmpadec.c new file mode 100644 index 00000000..970aed96 --- /dev/null +++ b/gst/rtp/gstrtpmpadec.c @@ -0,0 +1,272 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <gst/rtp/gstrtpbuffer.h> + +#include <string.h> +#include "gstrtpmpadec.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_mpadec_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts MPEG audio from RTP packets", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpMPADec signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_FREQUENCY +}; + +static GstStaticPadTemplate gst_rtpmpadec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/mpeg") + ); + +static GstStaticPadTemplate gst_rtpmpadec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtpmpadec_class_init (GstRtpMPADecClass * klass); +static void gst_rtpmpadec_base_init (GstRtpMPADecClass * klass); +static void gst_rtpmpadec_init (GstRtpMPADec * rtpmpadec); + +static GstFlowReturn gst_rtpmpadec_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtpmpadec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtpmpadec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtpmpadec_change_state (GstElement * element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtpmpadec_get_type (void) +{ + static GType rtpmpadec_type = 0; + + if (!rtpmpadec_type) { + static const GTypeInfo rtpmpadec_info = { + sizeof (GstRtpMPADecClass), + (GBaseInitFunc) gst_rtpmpadec_base_init, + NULL, + (GClassInitFunc) gst_rtpmpadec_class_init, + NULL, + NULL, + sizeof (GstRtpMPADec), + 0, + (GInstanceInitFunc) gst_rtpmpadec_init, + }; + + rtpmpadec_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMPADec", + &rtpmpadec_info, 0); + } + return rtpmpadec_type; +} + +static void +gst_rtpmpadec_base_init (GstRtpMPADecClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpadec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpadec_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_mpadec_details); +} + +static void +gst_rtpmpadec_class_init (GstRtpMPADecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtpmpadec_set_property; + gobject_class->get_property = gst_rtpmpadec_get_property; + + gstelement_class->change_state = gst_rtpmpadec_change_state; +} + +static void +gst_rtpmpadec_init (GstRtpMPADec * rtpmpadec) +{ + rtpmpadec->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpadec_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtpmpadec), rtpmpadec->srcpad); + + rtpmpadec->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpadec_sink_template), "sink"); + gst_pad_set_chain_function (rtpmpadec->sinkpad, gst_rtpmpadec_chain); + gst_element_add_pad (GST_ELEMENT (rtpmpadec), rtpmpadec->sinkpad); +} + +static GstFlowReturn +gst_rtpmpadec_chain (GstPad * pad, GstBuffer * buf) +{ + GstRtpMPADec *rtpmpadec; + GstBuffer *outbuf; + guint8 pt; + GstFlowReturn ret; + + rtpmpadec = GST_RTP_MPA_DEC (GST_OBJECT_PARENT (pad)); + + if (!gst_rtpbuffer_validate (buf)) + goto bad_packet; + + if ((pt = gst_rtpbuffer_get_payload_type (buf)) != GST_RTP_PAYLOAD_MPA) + goto bad_payload; + + + { + gint payload_len; + guint8 *payload; + guint16 frag_offset; + guint32 timestamp; + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + frag_offset = (payload[2] << 8) | payload[3]; + + /* strip off header */ + payload_len -= 4; + payload += 4; + + timestamp = gst_rtpbuffer_get_timestamp (buf); + + outbuf = gst_buffer_new_and_alloc (payload_len); + + //GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 90000; + + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + + GST_DEBUG ("gst_rtpmpadec_chain: pushing buffer of size %d", + GST_BUFFER_SIZE (outbuf)); + + gst_buffer_unref (buf); + + ret = gst_pad_push (rtpmpadec->srcpad, outbuf); + } + + return ret; + +bad_packet: + { + GST_DEBUG ("Packet did not validate"); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +bad_payload: + { + GST_DEBUG ("Unexpected payload type %u", pt); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static void +gst_rtpmpadec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpMPADec *rtpmpadec; + + rtpmpadec = GST_RTP_MPA_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtpmpadec_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpMPADec *rtpmpadec; + + rtpmpadec = GST_RTP_MPA_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtpmpadec_change_state (GstElement * element) +{ + GstRtpMPADec *rtpmpadec; + gint transition; + GstElementStateReturn ret; + + rtpmpadec = GST_RTP_MPA_DEC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtpmpadec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpmpadec", + GST_RANK_NONE, GST_TYPE_RTP_MPA_DEC); +} diff --git a/gst/rtp/gstrtpmpadec.h b/gst/rtp/gstrtpmpadec.h new file mode 100644 index 00000000..ef2a232d --- /dev/null +++ b/gst/rtp/gstrtpmpadec.h @@ -0,0 +1,60 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_MPA_DEC_H__ +#define __GST_RTP_MPA_DEC_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_MPA_DEC \ + (gst_rtpmpadec_get_type()) +#define GST_RTP_MPA_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_MPA_DEC,GstRtpMPADec)) +#define GST_RTP_MPA_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MPA_DEC,GstRtpMPADec)) +#define GST_IS_RTP_MPA_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_MPA_DEC)) +#define GST_IS_RTP_MPA_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_MPA_DEC)) + +typedef struct _GstRtpMPADec GstRtpMPADec; +typedef struct _GstRtpMPADecClass GstRtpMPADecClass; + +struct _GstRtpMPADec +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + guint frequency; +}; + +struct _GstRtpMPADecClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtpmpadec_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_MPA_DEC_H__ */ diff --git a/gst/rtp/gstrtpmpadepay.c b/gst/rtp/gstrtpmpadepay.c new file mode 100644 index 00000000..970aed96 --- /dev/null +++ b/gst/rtp/gstrtpmpadepay.c @@ -0,0 +1,272 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <gst/rtp/gstrtpbuffer.h> + +#include <string.h> +#include "gstrtpmpadec.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_mpadec_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts MPEG audio from RTP packets", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpMPADec signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_FREQUENCY +}; + +static GstStaticPadTemplate gst_rtpmpadec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/mpeg") + ); + +static GstStaticPadTemplate gst_rtpmpadec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtpmpadec_class_init (GstRtpMPADecClass * klass); +static void gst_rtpmpadec_base_init (GstRtpMPADecClass * klass); +static void gst_rtpmpadec_init (GstRtpMPADec * rtpmpadec); + +static GstFlowReturn gst_rtpmpadec_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtpmpadec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtpmpadec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtpmpadec_change_state (GstElement * element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtpmpadec_get_type (void) +{ + static GType rtpmpadec_type = 0; + + if (!rtpmpadec_type) { + static const GTypeInfo rtpmpadec_info = { + sizeof (GstRtpMPADecClass), + (GBaseInitFunc) gst_rtpmpadec_base_init, + NULL, + (GClassInitFunc) gst_rtpmpadec_class_init, + NULL, + NULL, + sizeof (GstRtpMPADec), + 0, + (GInstanceInitFunc) gst_rtpmpadec_init, + }; + + rtpmpadec_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMPADec", + &rtpmpadec_info, 0); + } + return rtpmpadec_type; +} + +static void +gst_rtpmpadec_base_init (GstRtpMPADecClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpadec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpadec_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_mpadec_details); +} + +static void +gst_rtpmpadec_class_init (GstRtpMPADecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtpmpadec_set_property; + gobject_class->get_property = gst_rtpmpadec_get_property; + + gstelement_class->change_state = gst_rtpmpadec_change_state; +} + +static void +gst_rtpmpadec_init (GstRtpMPADec * rtpmpadec) +{ + rtpmpadec->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpadec_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtpmpadec), rtpmpadec->srcpad); + + rtpmpadec->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpadec_sink_template), "sink"); + gst_pad_set_chain_function (rtpmpadec->sinkpad, gst_rtpmpadec_chain); + gst_element_add_pad (GST_ELEMENT (rtpmpadec), rtpmpadec->sinkpad); +} + +static GstFlowReturn +gst_rtpmpadec_chain (GstPad * pad, GstBuffer * buf) +{ + GstRtpMPADec *rtpmpadec; + GstBuffer *outbuf; + guint8 pt; + GstFlowReturn ret; + + rtpmpadec = GST_RTP_MPA_DEC (GST_OBJECT_PARENT (pad)); + + if (!gst_rtpbuffer_validate (buf)) + goto bad_packet; + + if ((pt = gst_rtpbuffer_get_payload_type (buf)) != GST_RTP_PAYLOAD_MPA) + goto bad_payload; + + + { + gint payload_len; + guint8 *payload; + guint16 frag_offset; + guint32 timestamp; + + payload_len = gst_rtpbuffer_get_payload_len (buf); + payload = gst_rtpbuffer_get_payload (buf); + + frag_offset = (payload[2] << 8) | payload[3]; + + /* strip off header */ + payload_len -= 4; + payload += 4; + + timestamp = gst_rtpbuffer_get_timestamp (buf); + + outbuf = gst_buffer_new_and_alloc (payload_len); + + //GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 90000; + + memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len); + + GST_DEBUG ("gst_rtpmpadec_chain: pushing buffer of size %d", + GST_BUFFER_SIZE (outbuf)); + + gst_buffer_unref (buf); + + ret = gst_pad_push (rtpmpadec->srcpad, outbuf); + } + + return ret; + +bad_packet: + { + GST_DEBUG ("Packet did not validate"); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +bad_payload: + { + GST_DEBUG ("Unexpected payload type %u", pt); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static void +gst_rtpmpadec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpMPADec *rtpmpadec; + + rtpmpadec = GST_RTP_MPA_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtpmpadec_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpMPADec *rtpmpadec; + + rtpmpadec = GST_RTP_MPA_DEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtpmpadec_change_state (GstElement * element) +{ + GstRtpMPADec *rtpmpadec; + gint transition; + GstElementStateReturn ret; + + rtpmpadec = GST_RTP_MPA_DEC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtpmpadec_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpmpadec", + GST_RANK_NONE, GST_TYPE_RTP_MPA_DEC); +} diff --git a/gst/rtp/gstrtpmpadepay.h b/gst/rtp/gstrtpmpadepay.h new file mode 100644 index 00000000..ef2a232d --- /dev/null +++ b/gst/rtp/gstrtpmpadepay.h @@ -0,0 +1,60 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_MPA_DEC_H__ +#define __GST_RTP_MPA_DEC_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_MPA_DEC \ + (gst_rtpmpadec_get_type()) +#define GST_RTP_MPA_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_MPA_DEC,GstRtpMPADec)) +#define GST_RTP_MPA_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MPA_DEC,GstRtpMPADec)) +#define GST_IS_RTP_MPA_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_MPA_DEC)) +#define GST_IS_RTP_MPA_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_MPA_DEC)) + +typedef struct _GstRtpMPADec GstRtpMPADec; +typedef struct _GstRtpMPADecClass GstRtpMPADecClass; + +struct _GstRtpMPADec +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + guint frequency; +}; + +struct _GstRtpMPADecClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtpmpadec_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_MPA_DEC_H__ */ diff --git a/gst/rtp/gstrtpmpaenc.c b/gst/rtp/gstrtpmpaenc.c new file mode 100644 index 00000000..6c77291f --- /dev/null +++ b/gst/rtp/gstrtpmpaenc.c @@ -0,0 +1,331 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <string.h> + +#include <gst/rtp/gstrtpbuffer.h> + +#include "gstrtpmpaenc.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_mpaenc_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts MPEG audio from RTP packets", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpMPAEnc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_MTU 1024 + +enum +{ + PROP_0, + PROP_MTU +}; + +static GstStaticPadTemplate gst_rtpmpaenc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/mpeg") + ); + +static GstStaticPadTemplate gst_rtpmpaenc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass); +static void gst_rtpmpaenc_base_init (GstRtpMPAEncClass * klass); +static void gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc); + +static GstFlowReturn gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtpmpaenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtpmpaenc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtpmpaenc_change_state (GstElement * element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtpmpaenc_get_type (void) +{ + static GType rtpmpaenc_type = 0; + + if (!rtpmpaenc_type) { + static const GTypeInfo rtpmpaenc_info = { + sizeof (GstRtpMPAEncClass), + (GBaseInitFunc) gst_rtpmpaenc_base_init, + NULL, + (GClassInitFunc) gst_rtpmpaenc_class_init, + NULL, + NULL, + sizeof (GstRtpMPAEnc), + 0, + (GInstanceInitFunc) gst_rtpmpaenc_init, + }; + + rtpmpaenc_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMPAEnc", + &rtpmpaenc_info, 0); + } + return rtpmpaenc_type; +} + +static void +gst_rtpmpaenc_base_init (GstRtpMPAEncClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpaenc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpaenc_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_mpaenc_details); +} + +static void +gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtpmpaenc_set_property; + gobject_class->get_property = gst_rtpmpaenc_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, + g_param_spec_uint ("mtu", "MTU", + "Maximum size of one packet", + 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); + + gstelement_class->change_state = gst_rtpmpaenc_change_state; +} + +static void +gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc) +{ + rtpmpaenc->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpaenc_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->srcpad); + + rtpmpaenc->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpaenc_sink_template), "sink"); + gst_pad_set_chain_function (rtpmpaenc->sinkpad, gst_rtpmpaenc_chain); + gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->sinkpad); + + rtpmpaenc->adapter = gst_adapter_new (); + rtpmpaenc->mtu = DEFAULT_MTU; +} + +static GstFlowReturn +gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + guint16 frag_offset; + + /* 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. In the case the + * adapter has more than one MTU, we need to split the MPA data + * over multiple packets. The frag_offset in each packet header + * needs to be updated with the position in the MPA frame. */ + avail = gst_adapter_available (rtpmpaenc->adapter); + + ret = GST_FLOW_OK; + + frag_offset = 0; + 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 (4 + avail, 0, 0); + + /* fill one MTU or all available bytes */ + towrite = MIN (packet_len, rtpmpaenc->mtu); + + /* 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); + + payload_len -= 4; + + /* set timestamp */ + gst_rtpbuffer_set_timestamp (outbuf, + rtpmpaenc->first_ts * 90000 / GST_SECOND); + gst_rtpbuffer_set_payload_type (outbuf, GST_RTP_PAYLOAD_MPA); + gst_rtpbuffer_set_seq (outbuf, rtpmpaenc->seqnum++); + + payload = gst_rtpbuffer_get_payload (outbuf); + payload[0] = 0; + payload[1] = 0; + payload[2] = frag_offset >> 8; + payload[3] = frag_offset & 0xff; + + data = (guint8 *) gst_adapter_peek (rtpmpaenc->adapter, payload_len); + memcpy (&payload[4], data, payload_len); + gst_adapter_flush (rtpmpaenc->adapter, payload_len); + + GST_BUFFER_TIMESTAMP (outbuf) = rtpmpaenc->first_ts; + + ret = gst_pad_push (rtpmpaenc->srcpad, outbuf); + + avail -= payload_len; + frag_offset += payload_len; + } + + return ret; +} + +static GstFlowReturn +gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstRtpMPAEnc *rtpmpaenc; + GstFlowReturn ret; + guint size, avail; + guint packet_len; + + rtpmpaenc = GST_RTP_MPA_ENC (gst_pad_get_parent (pad)); + + size = GST_BUFFER_SIZE (buffer); + avail = gst_adapter_available (rtpmpaenc->adapter); + + /* get packet length of previous data and this new data, + * payload length includes a 4 byte header */ + packet_len = gst_rtpbuffer_calc_packet_len (4 + avail + size, 0, 0); + + /* if this buffer is going to overflow the packet, flush what we + * have. */ + if (packet_len > rtpmpaenc->mtu) { + ret = gst_rtpmpaenc_flush (rtpmpaenc); + avail = 0; + } + + gst_adapter_push (rtpmpaenc->adapter, buffer); + + if (avail == 0) { + rtpmpaenc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + } + gst_object_unref (rtpmpaenc); + + ret = GST_FLOW_OK; + + return ret; +} + +static void +gst_rtpmpaenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpMPAEnc *rtpmpaenc; + + rtpmpaenc = GST_RTP_MPA_ENC (object); + + switch (prop_id) { + case PROP_MTU: + rtpmpaenc->mtu = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtpmpaenc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpMPAEnc *rtpmpaenc; + + rtpmpaenc = GST_RTP_MPA_ENC (object); + + switch (prop_id) { + case PROP_MTU: + g_value_set_uint (value, rtpmpaenc->mtu); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtpmpaenc_change_state (GstElement * element) +{ + GstRtpMPAEnc *rtpmpaenc; + gint transition; + GstElementStateReturn ret; + + rtpmpaenc = GST_RTP_MPA_ENC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + rtpmpaenc->seqnum = 0; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtpmpaenc_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpmpaenc", + GST_RANK_NONE, GST_TYPE_RTP_MPA_ENC); +} diff --git a/gst/rtp/gstrtpmpaenc.h b/gst/rtp/gstrtpmpaenc.h new file mode 100644 index 00000000..5a03c7cb --- /dev/null +++ b/gst/rtp/gstrtpmpaenc.h @@ -0,0 +1,65 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_MPA_ENC_H__ +#define __GST_RTP_MPA_ENC_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_MPA_ENC \ + (gst_rtpmpaenc_get_type()) +#define GST_RTP_MPA_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_MPA_ENC,GstRtpMPAEnc)) +#define GST_RTP_MPA_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MPA_ENC,GstRtpMPAEnc)) +#define GST_IS_RTP_MPA_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_MPA_ENC)) +#define GST_IS_RTP_MPA_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_MPA_ENC)) + +typedef struct _GstRtpMPAEnc GstRtpMPAEnc; +typedef struct _GstRtpMPAEncClass GstRtpMPAEncClass; + +struct _GstRtpMPAEnc +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + GstClockTime first_ts; + guint16 seqnum; + + guint mtu; +}; + +struct _GstRtpMPAEncClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtpmpaenc_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_MPA_ENC_H__ */ diff --git a/gst/rtp/gstrtpmpapay.c b/gst/rtp/gstrtpmpapay.c new file mode 100644 index 00000000..6c77291f --- /dev/null +++ b/gst/rtp/gstrtpmpapay.c @@ -0,0 +1,331 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 <string.h> + +#include <gst/rtp/gstrtpbuffer.h> + +#include "gstrtpmpaenc.h" + +/* elementfactory information */ +static GstElementDetails gst_rtp_mpaenc_details = { + "RTP packet parser", + "Codec/Parser/Network", + "Extracts MPEG audio from RTP packets", + "Wim Taymans <wim@fluendo.com>" +}; + +/* RtpMPAEnc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_MTU 1024 + +enum +{ + PROP_0, + PROP_MTU +}; + +static GstStaticPadTemplate gst_rtpmpaenc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/mpeg") + ); + +static GstStaticPadTemplate gst_rtpmpaenc_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp") + ); + + +static void gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass); +static void gst_rtpmpaenc_base_init (GstRtpMPAEncClass * klass); +static void gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc); + +static GstFlowReturn gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_rtpmpaenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtpmpaenc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstElementStateReturn gst_rtpmpaenc_change_state (GstElement * element); + +static GstElementClass *parent_class = NULL; + +static GType +gst_rtpmpaenc_get_type (void) +{ + static GType rtpmpaenc_type = 0; + + if (!rtpmpaenc_type) { + static const GTypeInfo rtpmpaenc_info = { + sizeof (GstRtpMPAEncClass), + (GBaseInitFunc) gst_rtpmpaenc_base_init, + NULL, + (GClassInitFunc) gst_rtpmpaenc_class_init, + NULL, + NULL, + sizeof (GstRtpMPAEnc), + 0, + (GInstanceInitFunc) gst_rtpmpaenc_init, + }; + + rtpmpaenc_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstRtpMPAEnc", + &rtpmpaenc_info, 0); + } + return rtpmpaenc_type; +} + +static void +gst_rtpmpaenc_base_init (GstRtpMPAEncClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpaenc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtpmpaenc_sink_template)); + + gst_element_class_set_details (element_class, &gst_rtp_mpaenc_details); +} + +static void +gst_rtpmpaenc_class_init (GstRtpMPAEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_rtpmpaenc_set_property; + gobject_class->get_property = gst_rtpmpaenc_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, + g_param_spec_uint ("mtu", "MTU", + "Maximum size of one packet", + 28, G_MAXUINT, DEFAULT_MTU, G_PARAM_READWRITE)); + + gstelement_class->change_state = gst_rtpmpaenc_change_state; +} + +static void +gst_rtpmpaenc_init (GstRtpMPAEnc * rtpmpaenc) +{ + rtpmpaenc->srcpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpaenc_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->srcpad); + + rtpmpaenc->sinkpad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_rtpmpaenc_sink_template), "sink"); + gst_pad_set_chain_function (rtpmpaenc->sinkpad, gst_rtpmpaenc_chain); + gst_element_add_pad (GST_ELEMENT (rtpmpaenc), rtpmpaenc->sinkpad); + + rtpmpaenc->adapter = gst_adapter_new (); + rtpmpaenc->mtu = DEFAULT_MTU; +} + +static GstFlowReturn +gst_rtpmpaenc_flush (GstRtpMPAEnc * rtpmpaenc) +{ + guint avail; + GstBuffer *outbuf; + GstFlowReturn ret; + guint16 frag_offset; + + /* 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. In the case the + * adapter has more than one MTU, we need to split the MPA data + * over multiple packets. The frag_offset in each packet header + * needs to be updated with the position in the MPA frame. */ + avail = gst_adapter_available (rtpmpaenc->adapter); + + ret = GST_FLOW_OK; + + frag_offset = 0; + 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 (4 + avail, 0, 0); + + /* fill one MTU or all available bytes */ + towrite = MIN (packet_len, rtpmpaenc->mtu); + + /* 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); + + payload_len -= 4; + + /* set timestamp */ + gst_rtpbuffer_set_timestamp (outbuf, + rtpmpaenc->first_ts * 90000 / GST_SECOND); + gst_rtpbuffer_set_payload_type (outbuf, GST_RTP_PAYLOAD_MPA); + gst_rtpbuffer_set_seq (outbuf, rtpmpaenc->seqnum++); + + payload = gst_rtpbuffer_get_payload (outbuf); + payload[0] = 0; + payload[1] = 0; + payload[2] = frag_offset >> 8; + payload[3] = frag_offset & 0xff; + + data = (guint8 *) gst_adapter_peek (rtpmpaenc->adapter, payload_len); + memcpy (&payload[4], data, payload_len); + gst_adapter_flush (rtpmpaenc->adapter, payload_len); + + GST_BUFFER_TIMESTAMP (outbuf) = rtpmpaenc->first_ts; + + ret = gst_pad_push (rtpmpaenc->srcpad, outbuf); + + avail -= payload_len; + frag_offset += payload_len; + } + + return ret; +} + +static GstFlowReturn +gst_rtpmpaenc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstRtpMPAEnc *rtpmpaenc; + GstFlowReturn ret; + guint size, avail; + guint packet_len; + + rtpmpaenc = GST_RTP_MPA_ENC (gst_pad_get_parent (pad)); + + size = GST_BUFFER_SIZE (buffer); + avail = gst_adapter_available (rtpmpaenc->adapter); + + /* get packet length of previous data and this new data, + * payload length includes a 4 byte header */ + packet_len = gst_rtpbuffer_calc_packet_len (4 + avail + size, 0, 0); + + /* if this buffer is going to overflow the packet, flush what we + * have. */ + if (packet_len > rtpmpaenc->mtu) { + ret = gst_rtpmpaenc_flush (rtpmpaenc); + avail = 0; + } + + gst_adapter_push (rtpmpaenc->adapter, buffer); + + if (avail == 0) { + rtpmpaenc->first_ts = GST_BUFFER_TIMESTAMP (buffer); + } + gst_object_unref (rtpmpaenc); + + ret = GST_FLOW_OK; + + return ret; +} + +static void +gst_rtpmpaenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstRtpMPAEnc *rtpmpaenc; + + rtpmpaenc = GST_RTP_MPA_ENC (object); + + switch (prop_id) { + case PROP_MTU: + rtpmpaenc->mtu = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_rtpmpaenc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstRtpMPAEnc *rtpmpaenc; + + rtpmpaenc = GST_RTP_MPA_ENC (object); + + switch (prop_id) { + case PROP_MTU: + g_value_set_uint (value, rtpmpaenc->mtu); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_rtpmpaenc_change_state (GstElement * element) +{ + GstRtpMPAEnc *rtpmpaenc; + gint transition; + GstElementStateReturn ret; + + rtpmpaenc = GST_RTP_MPA_ENC (element); + transition = GST_STATE_TRANSITION (element); + + switch (transition) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + rtpmpaenc->seqnum = 0; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); + + switch (transition) { + case GST_STATE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +gboolean +gst_rtpmpaenc_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpmpaenc", + GST_RANK_NONE, GST_TYPE_RTP_MPA_ENC); +} diff --git a/gst/rtp/gstrtpmpapay.h b/gst/rtp/gstrtpmpapay.h new file mode 100644 index 00000000..5a03c7cb --- /dev/null +++ b/gst/rtp/gstrtpmpapay.h @@ -0,0 +1,65 @@ +/* Gnome-Streamer + * Copyright (C) <2005> Wim Taymans <wim@fluendo.com> + * + * 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 details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_MPA_ENC_H__ +#define __GST_RTP_MPA_ENC_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_MPA_ENC \ + (gst_rtpmpaenc_get_type()) +#define GST_RTP_MPA_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_MPA_ENC,GstRtpMPAEnc)) +#define GST_RTP_MPA_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_MPA_ENC,GstRtpMPAEnc)) +#define GST_IS_RTP_MPA_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_MPA_ENC)) +#define GST_IS_RTP_MPA_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_MPA_ENC)) + +typedef struct _GstRtpMPAEnc GstRtpMPAEnc; +typedef struct _GstRtpMPAEncClass GstRtpMPAEncClass; + +struct _GstRtpMPAEnc +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + GstClockTime first_ts; + guint16 seqnum; + + guint mtu; +}; + +struct _GstRtpMPAEncClass +{ + GstElementClass parent_class; +}; + +gboolean gst_rtpmpaenc_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_RTP_MPA_ENC_H__ */ diff --git a/gst/rtp/rtp-packet.c b/gst/rtp/rtp-packet.c deleted file mode 100644 index f33772b5..00000000 --- a/gst/rtp/rtp-packet.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - Librtp - a library for the RTP/RTCP protocol - Copyright (C) 2000 Roland Dreier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <glib.h> - -#include "rtp-packet.h" - -Rtp_Packet -rtp_packet_new_take_data (gpointer data, guint data_len) -{ - Rtp_Packet packet; - - //g_return_val_if_fail(data_len < RTP_MTU, NULL); - - packet = g_malloc (sizeof *packet); - - packet->data = data; - packet->data_len = data_len; - - return packet; -} - -Rtp_Packet -rtp_packet_new_copy_data (gpointer data, guint data_len) -{ - Rtp_Packet packet; - - //g_return_val_if_fail(data_len < RTP_MTU, NULL); - - packet = g_malloc (sizeof *packet); - - packet->data = g_memdup (data, data_len); - packet->data_len = data_len; - - return packet; -} - -Rtp_Packet -rtp_packet_new_allocate (guint payload_len, guint pad_len, guint csrc_count) -{ - guint len; - Rtp_Packet packet; - - g_return_val_if_fail (csrc_count <= 15, NULL); - - len = RTP_HEADER_LEN + csrc_count * sizeof (guint32) - + payload_len + pad_len; - - //g_return_val_if_fail(len < RTP_MTU, NULL); - - packet = g_malloc (sizeof *packet); - - packet->data_len = len; - packet->data = g_malloc (len); - - return (packet); -} - - -void -rtp_packet_free (Rtp_Packet packet) -{ - g_return_if_fail (packet != NULL); - - g_free (packet->data); - g_free (packet); -} - -/*Rtp_Packet -rtp_packet_read(int fd, struct sockaddr *fromaddr, socklen_t *fromlen) -{ - int packlen; - gpointer buf; - - buf = g_malloc(RTP_MTU); - - packlen = recvfrom(fd, buf, RTP_MTU, 0, fromaddr, fromlen); - - if (packlen < 0) { - g_error("rtp_packet_read: recvfrom: %d %s", errno, strerror(errno)); - //exit(1); - return NULL; - } - - return rtp_packet_new_take_data(buf, packlen); -}*/ - -/*void -rtp_packet_send(Rtp_Packet packet, int fd, struct sockaddr *toaddr, socklen_t tolen) -{ - g_return_if_fail(packet != NULL); - - sendto(fd, (void *) packet -> data, - packet -> data_len, 0, - toaddr, tolen); -}*/ - -guint8 -rtp_packet_get_version (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return ((Rtp_Header) packet->data)->version; -} - -void -rtp_packet_set_version (Rtp_Packet packet, guint8 version) -{ - g_return_if_fail (packet != NULL); - g_return_if_fail (version < 0x04); - - ((Rtp_Header) packet->data)->version = version; -} - -guint8 -rtp_packet_get_padding (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return ((Rtp_Header) packet->data)->padding; -} - -void -rtp_packet_set_padding (Rtp_Packet packet, guint8 padding) -{ - g_return_if_fail (packet != NULL); - g_return_if_fail (padding < 0x02); - - ((Rtp_Header) packet->data)->padding = padding; -} - -guint8 -rtp_packet_get_csrc_count (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return ((Rtp_Header) packet->data)->csrc_count; -} - -guint8 -rtp_packet_get_extension (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return ((Rtp_Header) packet->data)->extension; -} - -void -rtp_packet_set_extension (Rtp_Packet packet, guint8 extension) -{ - g_return_if_fail (packet != NULL); - g_return_if_fail (extension < 0x02); - - ((Rtp_Header) packet->data)->extension = extension; -} - -void -rtp_packet_set_csrc_count (Rtp_Packet packet, guint8 csrc_count) -{ - g_return_if_fail (packet != NULL); - g_return_if_fail (csrc_count < 0x04); - - ((Rtp_Header) packet->data)->csrc_count = csrc_count; -} - -guint8 -rtp_packet_get_marker (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return ((Rtp_Header) packet->data)->marker; -} - -void -rtp_packet_set_marker (Rtp_Packet packet, guint8 marker) -{ - g_return_if_fail (packet != NULL); - g_return_if_fail (marker < 0x02); - - ((Rtp_Header) packet->data)->marker = marker; -} - -guint8 -rtp_packet_get_payload_type (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return ((Rtp_Header) packet->data)->payload_type; -} - -void -rtp_packet_set_payload_type (Rtp_Packet packet, guint8 payload_type) -{ - g_return_if_fail (packet != NULL); - g_return_if_fail (payload_type < 0x80); - - ((Rtp_Header) packet->data)->payload_type = payload_type; -} - -guint16 -rtp_packet_get_seq (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return g_ntohs (((Rtp_Header) packet->data)->seq); -} - -void -rtp_packet_set_seq (Rtp_Packet packet, guint16 seq) -{ - g_return_if_fail (packet != NULL); - - ((Rtp_Header) packet->data)->seq = g_htons (seq); -} - -guint32 -rtp_packet_get_timestamp (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return g_ntohl (((Rtp_Header) packet->data)->timestamp); -} - -void -rtp_packet_set_timestamp (Rtp_Packet packet, guint32 timestamp) -{ - g_return_if_fail (packet != NULL); - - ((Rtp_Header) packet->data)->timestamp = g_htonl (timestamp); -} - -guint32 -rtp_packet_get_ssrc (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return g_ntohl (((Rtp_Header) packet->data)->ssrc); -} - -void -rtp_packet_set_ssrc (Rtp_Packet packet, guint32 ssrc) -{ - g_return_if_fail (packet != NULL); - - ((Rtp_Header) packet->data)->ssrc = g_htonl (ssrc); -} - -guint -rtp_packet_get_payload_len (Rtp_Packet packet) -{ - guint len; - - g_return_val_if_fail (packet != NULL, 0); - - len = packet->data_len - - RTP_HEADER_LEN - rtp_packet_get_csrc_count (packet) * sizeof (guint32); - - if (rtp_packet_get_padding (packet)) { - len -= ((guint8 *) packet->data)[packet->data_len - 1]; - } - - return len; -} - -gpointer -rtp_packet_get_payload (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, NULL); - - return ((char *) packet->data) - + RTP_HEADER_LEN + rtp_packet_get_csrc_count (packet) * sizeof (guint32); -} - -guint -rtp_packet_get_packet_len (Rtp_Packet packet) -{ - g_return_val_if_fail (packet != NULL, 0); - - return packet->data_len; -} diff --git a/gst/rtp/rtp-packet.h b/gst/rtp/rtp-packet.h deleted file mode 100644 index f731c5f0..00000000 --- a/gst/rtp/rtp-packet.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - Gnome-o-Phone - A program for internet telephony - Copyright (C) 1999 Roland Dreier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ -*/ - -#ifndef _RTP_PACKET_H -#define _RTP_PACKET_H 1 - -#include <sys/types.h> -#include <glib.h> - -#ifdef __sun -#include <sys/uio.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define RTP_VERSION 2 -#define RTP_HEADER_LEN 12 -#define RTP_MTU 2048 - -typedef struct Rtp_Header *Rtp_Header; - -struct Rtp_Packet_Struct { - gpointer data; - guint data_len; -}; - -struct Rtp_Header { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - unsigned int csrc_count:4; /* CSRC count */ - unsigned int extension:1; /* header extension flag */ - unsigned int padding:1; /* padding flag */ - unsigned int version:2; /* protocol version */ - unsigned int payload_type:7; /* payload type */ - unsigned int marker:1; /* marker bit */ -#elif G_BYTE_ORDER == G_BIG_ENDIAN - unsigned int version:2; /* protocol version */ - unsigned int padding:1; /* padding flag */ - unsigned int extension:1; /* header extension flag */ - unsigned int csrc_count:4; /* CSRC count */ - unsigned int marker:1; /* marker bit */ - unsigned int payload_type:7; /* payload type */ -#else -#error "G_BYTE_ORDER should be big or little endian." -#endif - guint16 seq; /* sequence number */ - guint32 timestamp; /* timestamp */ - guint32 ssrc; /* synchronization source */ - guint32 csrc[1]; /* optional CSRC list */ -}; - -typedef struct Rtp_Packet_Struct *Rtp_Packet; - -Rtp_Packet rtp_packet_new_take_data(gpointer data, guint data_len); -Rtp_Packet rtp_packet_new_copy_data(gpointer data, guint data_len); -Rtp_Packet rtp_packet_new_allocate(guint payload_len, - guint pad_len, guint csrc_count); -void rtp_packet_free(Rtp_Packet packet); -//Rtp_Packet rtp_packet_read(int fd, struct sockaddr *fromaddr, socklen_t *fromlen); -//void rtp_packet_send(Rtp_Packet packet, int fd, struct sockaddr *toaddr, socklen_t tolen); -guint8 rtp_packet_get_version(Rtp_Packet packet); -void rtp_packet_set_version(Rtp_Packet packet, guint8 version); -guint8 rtp_packet_get_padding(Rtp_Packet packet); -void rtp_packet_set_padding(Rtp_Packet packet, guint8 padding); -guint8 rtp_packet_get_csrc_count(Rtp_Packet packet); -guint8 rtp_packet_get_extension(Rtp_Packet packet); -void rtp_packet_set_extension(Rtp_Packet packet, guint8 extension); -void rtp_packet_set_csrc_count(Rtp_Packet packet, guint8 csrc_count); -guint8 rtp_packet_get_marker(Rtp_Packet packet); -void rtp_packet_set_marker(Rtp_Packet packet, guint8 marker); -guint8 rtp_packet_get_payload_type(Rtp_Packet packet); -void rtp_packet_set_payload_type(Rtp_Packet packet, guint8 payload_type); -guint16 rtp_packet_get_seq(Rtp_Packet packet); -void rtp_packet_set_seq(Rtp_Packet packet, guint16 seq); -guint32 rtp_packet_get_timestamp(Rtp_Packet packet); -void rtp_packet_set_timestamp(Rtp_Packet packet, guint32 timestamp); -guint32 rtp_packet_get_ssrc(Rtp_Packet packet); -void rtp_packet_set_ssrc(Rtp_Packet packet, guint32 ssrc); -guint rtp_packet_get_payload_len(Rtp_Packet packet); -gpointer rtp_packet_get_payload(Rtp_Packet packet); -guint rtp_packet_get_packet_len(Rtp_Packet packet); - -#ifdef __cplusplus -} -#endif - -#endif /* rtp-packet.h */ |