Complete the move of the RTP plugin

Original commit message from CVS:
Complete the move of the RTP plugin
This commit is contained in:
Christian Schaller 2003-03-02 10:16:26 +00:00
parent ab71414650
commit a1a3853e87
17 changed files with 2209 additions and 27 deletions

View file

@ -73,12 +73,10 @@ GST_CHECK_FEATURE(EXPERIMENTAL, [enable building of experimental plug-ins],,
[
AC_MSG_WARN(building experimental plug-ins)
USE_TARKIN="yes"
USE_RTP="yes"
USE_SHOUT2="yes"
],[
AC_MSG_NOTICE(not building experimental plug-ins)
USE_TARKIN="no"
USE_RTP="no"
USE_SHOUT2="no"
])
@ -762,22 +760,6 @@ GST_CHECK_FEATURE(RAW1394, [raw1394 library], dv1394src, [
AC_SUBST(RAW1394_LIBS)
])
dnl *** rtp ***
dnl FIXME : adapt and make it work
translit(dnm, m, l) AM_CONDITIONAL(USE_RTP, true)
GST_CHECK_FEATURE(RTP, [RTP library], rtpenc rtpdec,[
AC_CHECK_LIB(ortp, ortp_init, HAVE_RTP=yes, HAVE_RTP=no, $GST_CFLAGS $GST_LIBS)
RTP_LIBS="-lortp"
AC_SUBST(RTP_LIBS)
])
dnl FIXME header check needs to use GLIB_CFLAGS in order to succeed for rtp
dnl can use GST_* which should have GLIB_* info
dnl AC_CHECK_HEADERS(rtp/rtp.h, HAVE_LIBRTP=yes, HAVE_LIBRTP=no)
dnl AC_CHECK_HEADERS(rtp/rtp-packet.h, :, HAVE_LIBRTP=no)
dnl AC_CHECK_HEADERS(rtp/rtcp-packet.h, :, HAVE_LIBRTP=no)
dnl AC_CHECK_HEADERS(rtp/rtp-audio.h, :, HAVE_LIBRTP=no)
dnl *** SDL ***
translit(dnm, m, l) AM_CONDITIONAL(USE_SDL, true)
GST_CHECK_FEATURE(SDL, [SDL plug-in], sdlvideosink, [
@ -1056,6 +1038,7 @@ gst/passthrough/Makefile
gst/playondemand/Makefile
gst/qtdemux/Makefile
gst/rtjpeg/Makefile
gst/rtp/Makefile
gst/silence/Makefile
gst/sine/Makefile
gst/smooth/Makefile
@ -1120,7 +1103,6 @@ ext/mjpegtools/Makefile
ext/mpeg2dec/Makefile
ext/openquicktime/Makefile
ext/raw1394/Makefile
ext/rtp/Makefile
ext/sdl/Makefile
ext/shout/Makefile
ext/shout2/Makefile

View file

@ -196,12 +196,6 @@ else
RAW1394_DIR=
endif
if USE_RTP
RTP_DIR=rtp
else
RTP_DIR=
endif
if USE_SDL
SDL_DIR=sdl
else
@ -271,7 +265,7 @@ SUBDIRS=$(A52DEC_DIR) $(AALIB_DIR) $(ALSA_DIR) \
$(LADSPA_DIR) $(LAME_DIR) $(LCS_DIR) \
$(LIBDV_DIR) $(LIBFAME_DIR) $(LIBPNG_DIR) \
$(MAD_DIR) $(MIKMOD_DIR) $(MJPEGTOOLS_DIR) $(MPEG2DEC_DIR) \
$(OPENQUICKTIME_DIR) $(RAW1394_DIR) $(RTP_DIR) \
$(OPENQUICKTIME_DIR) $(RAW1394_DIR) \
$(SDL_DIR) $(SHOUT_DIR) $(SIDPLAY_DIR) \
$(SMOOTHWAVE_DIR) $(SWFDEC_DIR) $(TARKIN_DIR) \
$(VORBIS_DIR) $(XMMS_DIR) $(SNAPSHOT_DIR)
@ -285,6 +279,6 @@ DIST_SUBDIRS=\
hermes http ivorbis jack jpeg \
ladspa lame lcs libfame libpng \
mad mikmod mjpegtools mpeg2dec \
openquicktime raw1394 rtp \
openquicktime raw1394 \
sdl snapshot shout shout2 sidplay \
smoothwave swfdec tarkin vorbis xmms

10
gst/rtp/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@
plugin_LTLIBRARIES = libgstrtp.la
libgstrtp_la_SOURCES = gstrtp.c gstrtpL16enc.c gstrtpL16parse.c rtp-packet.c
libgstrtp_la_CFLAGS = $(GST_CFLAGS)
libgstrtp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstrtpL16enc.h gstrtpL16parse.h gstrtp-common.h rtp-packet.h

53
gst/rtp/README Normal file
View file

@ -0,0 +1,53 @@
TODO
----
- implement packing up to the MTU.
- discont events in the case of packet loss
- figure out the clocking.
- implement various RFCs dealing with different payload types.
(as modules?)
- Throw-out the the caps-nego & other session control things to the
Application Developer( App ), by turning rtcp work into, signals
in gstrtpsend & props/args in gstrtprecv.
The App would then be free to use any sort of session control
protocal like RTSP.( done )
Relevant RFCs
-------------
1889 RTP: A Transport Protocol for Real-Time Applications.
2198 RTP Payload for Redundant Audio Data.
3119 A More Loss-Tolerant RTP Payload Format for MP3 Audio.
2793 RTP Payload for Text Conversation.
2032 RTP Payload Format for H.261 Video Streams.
2190 RTP Payload Format for H.263 Video Streams.
2250 RTP Payload Format for MPEG1/MPEG2 Video.
2343 RTP Payload Format for Bundled MPEG.
2429 RTP Payload Format for the 1998 Version of ITU-T Rec. H.263 Video
2431 RTP Payload Format for BT.656 Video Encoding.
2435 RTP Payload Format for JPEG-compressed Video.
3016 RTP Payload Format for MPEG-4 Audio/Visual Streams.
3047 RTP Payload Format for ITU-T Recommendation G.722.1.
2733 An RTP Payload Format for Generic Forward Error Correction.
2833 RTP Payload for DTMF Digits, Telephony Tones and Telephony
Signals.
2862 RTP Payload Format for Real-Time Pointers.
1890 RTP Profile for Audio and Video Conferences with Minimal Control.
2508 Compressing IP/UDP/RTP Headers for Low-Speed Serial Links.
do we care?
-----------
2029 RTP Payload Format of Sun's CellB Video Encoding.
usefull
-------
http://www.iana.org/assignments/rtp-parameters

9
gst/rtp/TODO Normal file
View file

@ -0,0 +1,9 @@
*GstRtpRecv:
*gstrtprecv.c
*For Sequencing:
* timestamp
* algorithm
*For Video:
* payload_t

48
gst/rtp/gstrtp-common.h Normal file
View file

@ -0,0 +1,48 @@
/* 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_GSM = 3,
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

37
gst/rtp/gstrtp.c Normal file
View file

@ -0,0 +1,37 @@
/* 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.
*/
#include "gstrtpL16enc.h"
#include "gstrtpL16parse.h"
static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
gst_rtpL16enc_plugin_init (module, plugin);
gst_rtpL16parse_plugin_init (module, plugin);
return TRUE;
}
GstPluginDesc plugin_desc = {
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"rtp",
plugin_init
};

338
gst/rtp/gstrtpL16depay.c Normal file
View file

@ -0,0 +1,338 @@
/* GStreamer
* 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
*/
#include <string.h>
#include "gstrtpL16parse.h"
#include "gstrtp-common.h"
/* elementfactory information */
static GstElementDetails gst_rtp_L16parse_details = {
"RTP packet parser",
"RtpL16Parse",
"GPL",
"Extracts raw audio from RTP packets",
VERSION,
"Zeeshan Ali <zak147@yahoo.com>",
"(C) 2003",
};
/* RtpL16Parse signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
ARG_0,
ARG_FREQUENCY,
ARG_PAYLOAD_TYPE,
};
GST_PAD_TEMPLATE_FACTORY (src_factory,
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"audio_raw",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT_RANGE (1000, 48000),
"channels", GST_PROPS_INT_RANGE (1, 2))
)
GST_PAD_TEMPLATE_FACTORY (sink_factory,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"rtp",
"application/x-rtp",
NULL)
);
static void gst_rtpL16parse_class_init (GstRtpL16ParseClass * klass);
static void gst_rtpL16parse_init (GstRtpL16Parse * rtpL16parse);
static void gst_rtpL16parse_chain (GstPad * pad, GstBuffer * buf);
static void gst_rtpL16parse_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_rtpL16parse_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstElementStateReturn gst_rtpL16parse_change_state (GstElement * element);
static GstElementClass *parent_class = NULL;
static GType gst_rtpL16parse_get_type (void)
{
static GType rtpL16parse_type = 0;
if (!rtpL16parse_type) {
static const GTypeInfo rtpL16parse_info = {
sizeof (GstRtpL16ParseClass),
NULL,
NULL,
(GClassInitFunc) gst_rtpL16parse_class_init,
NULL,
NULL,
sizeof (GstRtpL16Parse),
0,
(GInstanceInitFunc) gst_rtpL16parse_init,
};
rtpL16parse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstRtpL16Parse", &rtpL16parse_info, 0);
}
return rtpL16parse_type;
}
static void
gst_rtpL16parse_class_init (GstRtpL16ParseClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PAYLOAD_TYPE,
g_param_spec_int ("payload_type", "payload_type", "payload type",
G_MININT, G_MAXINT, PAYLOAD_L16_STEREO, G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREQUENCY,
g_param_spec_int ("frequency", "frequency", "frequency",
G_MININT, G_MAXINT, 44100, G_PARAM_READWRITE));
gobject_class->set_property = gst_rtpL16parse_set_property;
gobject_class->get_property = gst_rtpL16parse_get_property;
gstelement_class->change_state = gst_rtpL16parse_change_state;
}
static void
gst_rtpL16parse_init (GstRtpL16Parse * rtpL16parse)
{
rtpL16parse->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_factory), "src");
rtpL16parse->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_factory), "sink");
gst_element_add_pad (GST_ELEMENT (rtpL16parse), rtpL16parse->srcpad);
gst_element_add_pad (GST_ELEMENT (rtpL16parse), rtpL16parse->sinkpad);
gst_pad_set_chain_function (rtpL16parse->sinkpad, gst_rtpL16parse_chain);
rtpL16parse->frequency = 44100;
rtpL16parse->channels = 2;
rtpL16parse->payload_type = PAYLOAD_L16_STEREO;
}
void
gst_rtpL16parse_ntohs (GstBuffer *buf)
{
guint16 *i, *len;
/* FIXME: is this code correct or even sane at all? */
i = (guint16 *) GST_BUFFER_DATA(buf);
len = i + GST_BUFFER_SIZE (buf) / sizeof (guint16 *);
for (; i<len; i++) {
*i = g_ntohs (*i);
}
}
void
gst_rtpL16_caps_nego (GstRtpL16Parse *rtpL16parse)
{
GstCaps *caps;
caps = GST_CAPS_NEW (
"audio_raw",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT (rtpL16parse->frequency),
"channels", GST_PROPS_INT (rtpL16parse->channels));
gst_pad_try_set_caps (rtpL16parse->srcpad, caps);
}
void
gst_rtpL16parse_payloadtype_change (GstRtpL16Parse *rtpL16parse, rtp_payload_t pt)
{
rtpL16parse->payload_type = pt;
switch (pt) {
case PAYLOAD_L16_MONO:
rtpL16parse->channels = 1;
break;
case PAYLOAD_L16_STEREO:
rtpL16parse->channels = 2;
break;
default:
g_warning ("unkown payload_t %d\n", pt);
}
gst_rtpL16_caps_nego (rtpL16parse);
}
static void
gst_rtpL16parse_chain (GstPad * pad, GstBuffer * buf)
{
GstRtpL16Parse *rtpL16parse;
GstBuffer *outbuf;
Rtp_Packet packet;
rtp_payload_t pt;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
rtpL16parse = GST_RTP_L16_PARSE (GST_OBJECT_PARENT (pad));
g_return_if_fail (rtpL16parse != NULL);
g_return_if_fail (GST_IS_RTP_L16_PARSE (rtpL16parse));
if (GST_IS_EVENT (buf)) {
GstEvent *event = GST_EVENT (buf);
gst_pad_event_default (pad, event);
return;
}
if (GST_PAD_CAPS (rtpL16parse->srcpad) == NULL) {
gst_rtpL16_caps_nego (rtpL16parse);
}
packet = rtp_packet_new_copy_data (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
pt = rtp_packet_get_payload_type (packet);
if (pt != rtpL16parse->payload_type) {
gst_rtpL16parse_payloadtype_change (rtpL16parse, pt);
}
outbuf = gst_buffer_new ();
GST_BUFFER_SIZE (outbuf) = rtp_packet_get_payload_len (packet);
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
GST_BUFFER_TIMESTAMP (outbuf) = g_ntohl (rtp_packet_get_timestamp (packet)) * GST_SECOND;
memcpy (GST_BUFFER_DATA (outbuf), rtp_packet_get_payload (packet), GST_BUFFER_SIZE (outbuf));
GST_DEBUG (0,"gst_rtpL16parse_chain: pushing buffer of size %d", GST_BUFFER_SIZE(outbuf));
/* FIXME: According to RFC 1890, this is required, right? */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
gst_rtpL16parse_ntohs (outbuf);
#endif
gst_pad_push (rtpL16parse->srcpad, outbuf);
rtp_packet_free (packet);
gst_buffer_unref (buf);
}
static void
gst_rtpL16parse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstRtpL16Parse *rtpL16parse;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_PARSE (object));
rtpL16parse = GST_RTP_L16_PARSE (object);
switch (prop_id) {
case ARG_PAYLOAD_TYPE:
gst_rtpL16parse_payloadtype_change (rtpL16parse, g_value_get_int (value));
break;
case ARG_FREQUENCY:
rtpL16parse->frequency = g_value_get_int (value);
break;
default:
break;
}
}
static void
gst_rtpL16parse_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
{
GstRtpL16Parse *rtpL16parse;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_PARSE (object));
rtpL16parse = GST_RTP_L16_PARSE (object);
switch (prop_id) {
case ARG_PAYLOAD_TYPE:
g_value_set_int (value, rtpL16parse->payload_type);
break;
case ARG_FREQUENCY:
g_value_set_int (value, rtpL16parse->frequency);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstElementStateReturn
gst_rtpL16parse_change_state (GstElement * element)
{
GstRtpL16Parse *rtpL16parse;
g_return_val_if_fail (GST_IS_RTP_L16_PARSE (element), GST_STATE_FAILURE);
rtpL16parse = GST_RTP_L16_PARSE (element);
GST_DEBUG (0, "state pending %d\n", GST_STATE_PENDING (element));
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
break;
default:
break;
}
/* if we haven't failed already, give the parent class a chance to ;-) */
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
}
gboolean
gst_rtpL16parse_plugin_init (GModule * module, GstPlugin * plugin)
{
GstElementFactory *rtpL16parse;
rtpL16parse = gst_element_factory_new ("rtpL16parse", GST_TYPE_RTP_L16_PARSE, &gst_rtp_L16parse_details);
g_return_val_if_fail (rtpL16parse != NULL, FALSE);
gst_element_factory_add_pad_template (rtpL16parse, GST_PAD_TEMPLATE_GET (src_factory));
gst_element_factory_add_pad_template (rtpL16parse, GST_PAD_TEMPLATE_GET (sink_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (rtpL16parse));
return TRUE;
}

73
gst/rtp/gstrtpL16depay.h Normal file
View file

@ -0,0 +1,73 @@
/* 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_L16_PARSE_H__
#define __GST_RTP_L16_PARSE_H__
#include <gst/gst.h>
#include "rtp-packet.h"
#include "gstrtp-common.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Definition of structure storing data for this element. */
typedef struct _GstRtpL16Parse GstRtpL16Parse;
struct _GstRtpL16Parse
{
GstElement element;
GstPad *sinkpad;
GstPad *srcpad;
guint frequency;
guint channels;
rtp_payload_t payload_type;
};
/* Standard definition defining a class for this element. */
typedef struct _GstRtpL16ParseClass GstRtpL16ParseClass;
struct _GstRtpL16ParseClass
{
GstElementClass parent_class;
};
/* Standard macros for defining types for this element. */
#define GST_TYPE_RTP_L16_PARSE \
(gst_rtpL16parse_get_type())
#define GST_RTP_L16_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_L16_PARSE,GstRtpL16Parse))
#define GST_RTP_L16_PARSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_L16_PARSE,GstRtpL16Parse))
#define GST_IS_RTP_L16_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_L16_PARSE))
#define GST_IS_RTP_L16_PARSE_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_L16_PARSE))
gboolean gst_rtpL16parse_plugin_init (GModule * module, GstPlugin * plugin);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_RTP_L16_PARSE_H__ */

326
gst/rtp/gstrtpL16enc.c Normal file
View file

@ -0,0 +1,326 @@
/* GStreamer
* 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.
*/
#include <string.h>
#include "gstrtpL16enc.h"
/* elementfactory information */
static GstElementDetails gst_rtpL16enc_details = {
"RTP RAW Audio Encoder",
"RtpL16Enc",
"LGPL",
"Encodes Raw Audio into an RTP packet",
VERSION,
"Zeeshan Ali <zak147@yahoo.com>",
"(C) 2003",
};
/* RtpL16Enc signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
/* FILL ME */
ARG_0,
};
GST_PAD_TEMPLATE_FACTORY (sink_factory,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"audio_raw",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT_RANGE (1000, 48000),
"channels", GST_PROPS_INT_RANGE (1, 2)
)
);
GST_PAD_TEMPLATE_FACTORY (src_factory,
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"rtp",
"application/x-rtp",
NULL)
);
static void gst_rtpL16enc_class_init (GstRtpL16EncClass * klass);
static void gst_rtpL16enc_init (GstRtpL16Enc * rtpL16enc);
static void gst_rtpL16enc_chain (GstPad * pad, GstBuffer * buf);
static void gst_rtpL16enc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_rtpL16enc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstPadLinkReturn gst_rtpL16enc_sinkconnect (GstPad * pad, GstCaps * caps);
static GstElementStateReturn gst_rtpL16enc_change_state (GstElement * element);
static GstElementClass *parent_class = NULL;
static GType gst_rtpL16enc_get_type (void)
{
static GType rtpL16enc_type = 0;
if (!rtpL16enc_type) {
static const GTypeInfo rtpL16enc_info = {
sizeof (GstRtpL16EncClass),
NULL,
NULL,
(GClassInitFunc) gst_rtpL16enc_class_init,
NULL,
NULL,
sizeof (GstRtpL16Enc),
0,
(GInstanceInitFunc) gst_rtpL16enc_init,
};
rtpL16enc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstRtpL16Enc", &rtpL16enc_info, 0);
}
return rtpL16enc_type;
}
static void
gst_rtpL16enc_class_init (GstRtpL16EncClass * 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_rtpL16enc_set_property;
gobject_class->get_property = gst_rtpL16enc_get_property;
gstelement_class->change_state = gst_rtpL16enc_change_state;
}
static void
gst_rtpL16enc_init (GstRtpL16Enc * rtpL16enc)
{
rtpL16enc->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_factory), "sink");
rtpL16enc->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_factory), "src");
gst_element_add_pad (GST_ELEMENT (rtpL16enc), rtpL16enc->sinkpad);
gst_element_add_pad (GST_ELEMENT (rtpL16enc), rtpL16enc->srcpad);
gst_pad_set_chain_function (rtpL16enc->sinkpad, gst_rtpL16enc_chain);
gst_pad_set_link_function (rtpL16enc->sinkpad, gst_rtpL16enc_sinkconnect);
rtpL16enc->frequency = 44100;
rtpL16enc->channels = 2;
rtpL16enc->next_time = 0;
rtpL16enc->time_interval = 0;
rtpL16enc->seq = 0;
rtpL16enc->ssrc = random ();
}
static GstPadLinkReturn
gst_rtpL16enc_sinkconnect (GstPad * pad, GstCaps * caps)
{
GstRtpL16Enc *rtpL16enc;
rtpL16enc = GST_RTP_L16_ENC (gst_pad_get_parent (pad));
gst_caps_get_int (caps, "rate", &rtpL16enc->frequency);
gst_caps_get_int (caps, "channels", &rtpL16enc->channels);
/* Pre-calculate what we can */
rtpL16enc->time_interval = GST_SECOND / (2 * rtpL16enc->channels * rtpL16enc->frequency);
return GST_PAD_LINK_OK;
}
void
gst_rtpL16enc_htons (GstBuffer *buf)
{
guint16 *i, *len;
/* FIXME: is this code correct or even sane at all? */
i = (guint16 *) GST_BUFFER_DATA(buf);
len = i + GST_BUFFER_SIZE (buf) / sizeof (guint16 *);
for (; i<len; i++) {
*i = g_htons (*i);
}
}
static void
gst_rtpL16enc_chain (GstPad * pad, GstBuffer * buf)
{
GstRtpL16Enc *rtpL16enc;
GstBuffer *outbuf;
Rtp_Packet packet;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
rtpL16enc = GST_RTP_L16_ENC (GST_OBJECT_PARENT (pad));
g_return_if_fail (rtpL16enc != NULL);
g_return_if_fail (GST_IS_RTP_L16_ENC (rtpL16enc));
if (GST_IS_EVENT (buf)) {
GstEvent *event = GST_EVENT (buf);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_DISCONTINUOUS:
GST_DEBUG (GST_CAT_EVENT, "discont");
rtpL16enc->next_time = 0;
gst_pad_event_default (pad, event);
return;
default:
gst_pad_event_default (pad, event);
return;
}
}
/* We only need the header */
packet = rtp_packet_new_allocate (0, 0, 0);
rtp_packet_set_csrc_count (packet, 0);
rtp_packet_set_extension (packet, 0);
rtp_packet_set_padding (packet, 0);
rtp_packet_set_version (packet, RTP_VERSION);
rtp_packet_set_marker (packet, 0);
rtp_packet_set_ssrc (packet, g_htonl (rtpL16enc->ssrc));
rtp_packet_set_seq (packet, g_htons (rtpL16enc->seq));
rtp_packet_set_timestamp (packet, g_htonl ((guint32) rtpL16enc->next_time / GST_SECOND));
if (rtpL16enc->channels == 1) {
rtp_packet_set_payload_type (packet, (guint8) PAYLOAD_L16_MONO);
}
else {
rtp_packet_set_payload_type (packet, (guint8) PAYLOAD_L16_STEREO);
}
/* FIXME: According to RFC 1890, this is required, right? */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
gst_rtpL16enc_htons (buf);
#endif
outbuf = gst_buffer_new ();
GST_BUFFER_SIZE (outbuf) = rtp_packet_get_packet_len (packet) + GST_BUFFER_SIZE (buf);
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
GST_BUFFER_TIMESTAMP (outbuf) = rtpL16enc->next_time;
memcpy (GST_BUFFER_DATA (outbuf), packet->data, rtp_packet_get_packet_len (packet));
memcpy (GST_BUFFER_DATA (outbuf) + rtp_packet_get_packet_len(packet), GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
GST_DEBUG (0,"gst_rtpL16enc_chain: pushing buffer of size %d", GST_BUFFER_SIZE(outbuf));
gst_pad_push (rtpL16enc->srcpad, outbuf);
++rtpL16enc->seq;
rtpL16enc->next_time += rtpL16enc->time_interval * GST_BUFFER_SIZE (buf);
rtp_packet_free (packet);
gst_buffer_unref (buf);
}
static void
gst_rtpL16enc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstRtpL16Enc *rtpL16enc;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_ENC (object));
rtpL16enc = GST_RTP_L16_ENC (object);
switch (prop_id) {
default:
break;
}
}
static void
gst_rtpL16enc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
{
GstRtpL16Enc *rtpL16enc;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_ENC (object));
rtpL16enc = GST_RTP_L16_ENC (object);
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstElementStateReturn
gst_rtpL16enc_change_state (GstElement * element)
{
GstRtpL16Enc *rtpL16enc;
g_return_val_if_fail (GST_IS_RTP_L16_ENC (element), GST_STATE_FAILURE);
rtpL16enc = GST_RTP_L16_ENC (element);
GST_DEBUG (0, "state pending %d\n", GST_STATE_PENDING (element));
/* if going down into NULL state, close the file if it's open */
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
break;
default:
break;
}
/* if we haven't failed already, give the parent class a chance to ;-) */
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
}
gboolean
gst_rtpL16enc_plugin_init (GModule * module, GstPlugin * plugin)
{
GstElementFactory *rtpL16enc;
rtpL16enc = gst_element_factory_new ("rtpL16enc", GST_TYPE_RTP_L16_ENC, &gst_rtpL16enc_details);
g_return_val_if_fail (rtpL16enc != NULL, FALSE);
gst_element_factory_add_pad_template (rtpL16enc, GST_PAD_TEMPLATE_GET (sink_factory));
gst_element_factory_add_pad_template (rtpL16enc, GST_PAD_TEMPLATE_GET (src_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (rtpL16enc));
return TRUE;
}

80
gst/rtp/gstrtpL16enc.h Normal file
View file

@ -0,0 +1,80 @@
/* 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_L16_ENC_H__
#define __GST_RTP_L16_ENC_H__
#include <gst/gst.h>
#include "rtp-packet.h"
#include "gstrtp-common.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Definition of structure storing data for this element. */
typedef struct _GstRtpL16Enc GstRtpL16Enc;
struct _GstRtpL16Enc
{
GstElement element;
GstPad *sinkpad;
GstPad *srcpad;
guint frequency;
guint channels;
/* the timestamp of the next frame */
guint64 next_time;
/* the interval between frames */
guint64 time_interval;
guint32 ssrc;
guint16 seq;
};
/* Standard definition defining a class for this element. */
typedef struct _GstRtpL16EncClass GstRtpL16EncClass;
struct _GstRtpL16EncClass
{
GstElementClass parent_class;
};
/* Standard macros for defining types for this element. */
#define GST_TYPE_RTP_L16_ENC \
(gst_rtpL16enc_get_type())
#define GST_RTP_L16_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_L16_ENC,GstRtpL16Enc))
#define GST_RTP_L16_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_L16_ENC,GstRtpL16Enc))
#define GST_IS_RTP_L16_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_L16_ENC))
#define GST_IS_RTP_L16_ENC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_L16_ENC))
gboolean gst_rtpL16enc_plugin_init (GModule * module, GstPlugin * plugin);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_RTP_L16_ENC_H__ */

338
gst/rtp/gstrtpL16parse.c Normal file
View file

@ -0,0 +1,338 @@
/* GStreamer
* 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
*/
#include <string.h>
#include "gstrtpL16parse.h"
#include "gstrtp-common.h"
/* elementfactory information */
static GstElementDetails gst_rtp_L16parse_details = {
"RTP packet parser",
"RtpL16Parse",
"GPL",
"Extracts raw audio from RTP packets",
VERSION,
"Zeeshan Ali <zak147@yahoo.com>",
"(C) 2003",
};
/* RtpL16Parse signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
ARG_0,
ARG_FREQUENCY,
ARG_PAYLOAD_TYPE,
};
GST_PAD_TEMPLATE_FACTORY (src_factory,
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"audio_raw",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT_RANGE (1000, 48000),
"channels", GST_PROPS_INT_RANGE (1, 2))
)
GST_PAD_TEMPLATE_FACTORY (sink_factory,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"rtp",
"application/x-rtp",
NULL)
);
static void gst_rtpL16parse_class_init (GstRtpL16ParseClass * klass);
static void gst_rtpL16parse_init (GstRtpL16Parse * rtpL16parse);
static void gst_rtpL16parse_chain (GstPad * pad, GstBuffer * buf);
static void gst_rtpL16parse_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_rtpL16parse_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstElementStateReturn gst_rtpL16parse_change_state (GstElement * element);
static GstElementClass *parent_class = NULL;
static GType gst_rtpL16parse_get_type (void)
{
static GType rtpL16parse_type = 0;
if (!rtpL16parse_type) {
static const GTypeInfo rtpL16parse_info = {
sizeof (GstRtpL16ParseClass),
NULL,
NULL,
(GClassInitFunc) gst_rtpL16parse_class_init,
NULL,
NULL,
sizeof (GstRtpL16Parse),
0,
(GInstanceInitFunc) gst_rtpL16parse_init,
};
rtpL16parse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstRtpL16Parse", &rtpL16parse_info, 0);
}
return rtpL16parse_type;
}
static void
gst_rtpL16parse_class_init (GstRtpL16ParseClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PAYLOAD_TYPE,
g_param_spec_int ("payload_type", "payload_type", "payload type",
G_MININT, G_MAXINT, PAYLOAD_L16_STEREO, G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREQUENCY,
g_param_spec_int ("frequency", "frequency", "frequency",
G_MININT, G_MAXINT, 44100, G_PARAM_READWRITE));
gobject_class->set_property = gst_rtpL16parse_set_property;
gobject_class->get_property = gst_rtpL16parse_get_property;
gstelement_class->change_state = gst_rtpL16parse_change_state;
}
static void
gst_rtpL16parse_init (GstRtpL16Parse * rtpL16parse)
{
rtpL16parse->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_factory), "src");
rtpL16parse->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_factory), "sink");
gst_element_add_pad (GST_ELEMENT (rtpL16parse), rtpL16parse->srcpad);
gst_element_add_pad (GST_ELEMENT (rtpL16parse), rtpL16parse->sinkpad);
gst_pad_set_chain_function (rtpL16parse->sinkpad, gst_rtpL16parse_chain);
rtpL16parse->frequency = 44100;
rtpL16parse->channels = 2;
rtpL16parse->payload_type = PAYLOAD_L16_STEREO;
}
void
gst_rtpL16parse_ntohs (GstBuffer *buf)
{
guint16 *i, *len;
/* FIXME: is this code correct or even sane at all? */
i = (guint16 *) GST_BUFFER_DATA(buf);
len = i + GST_BUFFER_SIZE (buf) / sizeof (guint16 *);
for (; i<len; i++) {
*i = g_ntohs (*i);
}
}
void
gst_rtpL16_caps_nego (GstRtpL16Parse *rtpL16parse)
{
GstCaps *caps;
caps = GST_CAPS_NEW (
"audio_raw",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT (rtpL16parse->frequency),
"channels", GST_PROPS_INT (rtpL16parse->channels));
gst_pad_try_set_caps (rtpL16parse->srcpad, caps);
}
void
gst_rtpL16parse_payloadtype_change (GstRtpL16Parse *rtpL16parse, rtp_payload_t pt)
{
rtpL16parse->payload_type = pt;
switch (pt) {
case PAYLOAD_L16_MONO:
rtpL16parse->channels = 1;
break;
case PAYLOAD_L16_STEREO:
rtpL16parse->channels = 2;
break;
default:
g_warning ("unkown payload_t %d\n", pt);
}
gst_rtpL16_caps_nego (rtpL16parse);
}
static void
gst_rtpL16parse_chain (GstPad * pad, GstBuffer * buf)
{
GstRtpL16Parse *rtpL16parse;
GstBuffer *outbuf;
Rtp_Packet packet;
rtp_payload_t pt;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
rtpL16parse = GST_RTP_L16_PARSE (GST_OBJECT_PARENT (pad));
g_return_if_fail (rtpL16parse != NULL);
g_return_if_fail (GST_IS_RTP_L16_PARSE (rtpL16parse));
if (GST_IS_EVENT (buf)) {
GstEvent *event = GST_EVENT (buf);
gst_pad_event_default (pad, event);
return;
}
if (GST_PAD_CAPS (rtpL16parse->srcpad) == NULL) {
gst_rtpL16_caps_nego (rtpL16parse);
}
packet = rtp_packet_new_copy_data (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
pt = rtp_packet_get_payload_type (packet);
if (pt != rtpL16parse->payload_type) {
gst_rtpL16parse_payloadtype_change (rtpL16parse, pt);
}
outbuf = gst_buffer_new ();
GST_BUFFER_SIZE (outbuf) = rtp_packet_get_payload_len (packet);
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
GST_BUFFER_TIMESTAMP (outbuf) = g_ntohl (rtp_packet_get_timestamp (packet)) * GST_SECOND;
memcpy (GST_BUFFER_DATA (outbuf), rtp_packet_get_payload (packet), GST_BUFFER_SIZE (outbuf));
GST_DEBUG (0,"gst_rtpL16parse_chain: pushing buffer of size %d", GST_BUFFER_SIZE(outbuf));
/* FIXME: According to RFC 1890, this is required, right? */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
gst_rtpL16parse_ntohs (outbuf);
#endif
gst_pad_push (rtpL16parse->srcpad, outbuf);
rtp_packet_free (packet);
gst_buffer_unref (buf);
}
static void
gst_rtpL16parse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstRtpL16Parse *rtpL16parse;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_PARSE (object));
rtpL16parse = GST_RTP_L16_PARSE (object);
switch (prop_id) {
case ARG_PAYLOAD_TYPE:
gst_rtpL16parse_payloadtype_change (rtpL16parse, g_value_get_int (value));
break;
case ARG_FREQUENCY:
rtpL16parse->frequency = g_value_get_int (value);
break;
default:
break;
}
}
static void
gst_rtpL16parse_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
{
GstRtpL16Parse *rtpL16parse;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_PARSE (object));
rtpL16parse = GST_RTP_L16_PARSE (object);
switch (prop_id) {
case ARG_PAYLOAD_TYPE:
g_value_set_int (value, rtpL16parse->payload_type);
break;
case ARG_FREQUENCY:
g_value_set_int (value, rtpL16parse->frequency);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstElementStateReturn
gst_rtpL16parse_change_state (GstElement * element)
{
GstRtpL16Parse *rtpL16parse;
g_return_val_if_fail (GST_IS_RTP_L16_PARSE (element), GST_STATE_FAILURE);
rtpL16parse = GST_RTP_L16_PARSE (element);
GST_DEBUG (0, "state pending %d\n", GST_STATE_PENDING (element));
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
break;
default:
break;
}
/* if we haven't failed already, give the parent class a chance to ;-) */
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
}
gboolean
gst_rtpL16parse_plugin_init (GModule * module, GstPlugin * plugin)
{
GstElementFactory *rtpL16parse;
rtpL16parse = gst_element_factory_new ("rtpL16parse", GST_TYPE_RTP_L16_PARSE, &gst_rtp_L16parse_details);
g_return_val_if_fail (rtpL16parse != NULL, FALSE);
gst_element_factory_add_pad_template (rtpL16parse, GST_PAD_TEMPLATE_GET (src_factory));
gst_element_factory_add_pad_template (rtpL16parse, GST_PAD_TEMPLATE_GET (sink_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (rtpL16parse));
return TRUE;
}

73
gst/rtp/gstrtpL16parse.h Normal file
View file

@ -0,0 +1,73 @@
/* 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_L16_PARSE_H__
#define __GST_RTP_L16_PARSE_H__
#include <gst/gst.h>
#include "rtp-packet.h"
#include "gstrtp-common.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Definition of structure storing data for this element. */
typedef struct _GstRtpL16Parse GstRtpL16Parse;
struct _GstRtpL16Parse
{
GstElement element;
GstPad *sinkpad;
GstPad *srcpad;
guint frequency;
guint channels;
rtp_payload_t payload_type;
};
/* Standard definition defining a class for this element. */
typedef struct _GstRtpL16ParseClass GstRtpL16ParseClass;
struct _GstRtpL16ParseClass
{
GstElementClass parent_class;
};
/* Standard macros for defining types for this element. */
#define GST_TYPE_RTP_L16_PARSE \
(gst_rtpL16parse_get_type())
#define GST_RTP_L16_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_L16_PARSE,GstRtpL16Parse))
#define GST_RTP_L16_PARSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_L16_PARSE,GstRtpL16Parse))
#define GST_IS_RTP_L16_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_L16_PARSE))
#define GST_IS_RTP_L16_PARSE_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_L16_PARSE))
gboolean gst_rtpL16parse_plugin_init (GModule * module, GstPlugin * plugin);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_RTP_L16_PARSE_H__ */

326
gst/rtp/gstrtpL16pay.c Normal file
View file

@ -0,0 +1,326 @@
/* GStreamer
* 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.
*/
#include <string.h>
#include "gstrtpL16enc.h"
/* elementfactory information */
static GstElementDetails gst_rtpL16enc_details = {
"RTP RAW Audio Encoder",
"RtpL16Enc",
"LGPL",
"Encodes Raw Audio into an RTP packet",
VERSION,
"Zeeshan Ali <zak147@yahoo.com>",
"(C) 2003",
};
/* RtpL16Enc signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
/* FILL ME */
ARG_0,
};
GST_PAD_TEMPLATE_FACTORY (sink_factory,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"audio_raw",
"audio/raw",
"format", GST_PROPS_STRING ("int"),
"law", GST_PROPS_INT (0),
"endianness", GST_PROPS_INT (G_BYTE_ORDER),
"signed", GST_PROPS_BOOLEAN (TRUE),
"width", GST_PROPS_INT (16),
"depth", GST_PROPS_INT (16),
"rate", GST_PROPS_INT_RANGE (1000, 48000),
"channels", GST_PROPS_INT_RANGE (1, 2)
)
);
GST_PAD_TEMPLATE_FACTORY (src_factory,
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"rtp",
"application/x-rtp",
NULL)
);
static void gst_rtpL16enc_class_init (GstRtpL16EncClass * klass);
static void gst_rtpL16enc_init (GstRtpL16Enc * rtpL16enc);
static void gst_rtpL16enc_chain (GstPad * pad, GstBuffer * buf);
static void gst_rtpL16enc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_rtpL16enc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstPadLinkReturn gst_rtpL16enc_sinkconnect (GstPad * pad, GstCaps * caps);
static GstElementStateReturn gst_rtpL16enc_change_state (GstElement * element);
static GstElementClass *parent_class = NULL;
static GType gst_rtpL16enc_get_type (void)
{
static GType rtpL16enc_type = 0;
if (!rtpL16enc_type) {
static const GTypeInfo rtpL16enc_info = {
sizeof (GstRtpL16EncClass),
NULL,
NULL,
(GClassInitFunc) gst_rtpL16enc_class_init,
NULL,
NULL,
sizeof (GstRtpL16Enc),
0,
(GInstanceInitFunc) gst_rtpL16enc_init,
};
rtpL16enc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstRtpL16Enc", &rtpL16enc_info, 0);
}
return rtpL16enc_type;
}
static void
gst_rtpL16enc_class_init (GstRtpL16EncClass * 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_rtpL16enc_set_property;
gobject_class->get_property = gst_rtpL16enc_get_property;
gstelement_class->change_state = gst_rtpL16enc_change_state;
}
static void
gst_rtpL16enc_init (GstRtpL16Enc * rtpL16enc)
{
rtpL16enc->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_factory), "sink");
rtpL16enc->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (src_factory), "src");
gst_element_add_pad (GST_ELEMENT (rtpL16enc), rtpL16enc->sinkpad);
gst_element_add_pad (GST_ELEMENT (rtpL16enc), rtpL16enc->srcpad);
gst_pad_set_chain_function (rtpL16enc->sinkpad, gst_rtpL16enc_chain);
gst_pad_set_link_function (rtpL16enc->sinkpad, gst_rtpL16enc_sinkconnect);
rtpL16enc->frequency = 44100;
rtpL16enc->channels = 2;
rtpL16enc->next_time = 0;
rtpL16enc->time_interval = 0;
rtpL16enc->seq = 0;
rtpL16enc->ssrc = random ();
}
static GstPadLinkReturn
gst_rtpL16enc_sinkconnect (GstPad * pad, GstCaps * caps)
{
GstRtpL16Enc *rtpL16enc;
rtpL16enc = GST_RTP_L16_ENC (gst_pad_get_parent (pad));
gst_caps_get_int (caps, "rate", &rtpL16enc->frequency);
gst_caps_get_int (caps, "channels", &rtpL16enc->channels);
/* Pre-calculate what we can */
rtpL16enc->time_interval = GST_SECOND / (2 * rtpL16enc->channels * rtpL16enc->frequency);
return GST_PAD_LINK_OK;
}
void
gst_rtpL16enc_htons (GstBuffer *buf)
{
guint16 *i, *len;
/* FIXME: is this code correct or even sane at all? */
i = (guint16 *) GST_BUFFER_DATA(buf);
len = i + GST_BUFFER_SIZE (buf) / sizeof (guint16 *);
for (; i<len; i++) {
*i = g_htons (*i);
}
}
static void
gst_rtpL16enc_chain (GstPad * pad, GstBuffer * buf)
{
GstRtpL16Enc *rtpL16enc;
GstBuffer *outbuf;
Rtp_Packet packet;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
rtpL16enc = GST_RTP_L16_ENC (GST_OBJECT_PARENT (pad));
g_return_if_fail (rtpL16enc != NULL);
g_return_if_fail (GST_IS_RTP_L16_ENC (rtpL16enc));
if (GST_IS_EVENT (buf)) {
GstEvent *event = GST_EVENT (buf);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_DISCONTINUOUS:
GST_DEBUG (GST_CAT_EVENT, "discont");
rtpL16enc->next_time = 0;
gst_pad_event_default (pad, event);
return;
default:
gst_pad_event_default (pad, event);
return;
}
}
/* We only need the header */
packet = rtp_packet_new_allocate (0, 0, 0);
rtp_packet_set_csrc_count (packet, 0);
rtp_packet_set_extension (packet, 0);
rtp_packet_set_padding (packet, 0);
rtp_packet_set_version (packet, RTP_VERSION);
rtp_packet_set_marker (packet, 0);
rtp_packet_set_ssrc (packet, g_htonl (rtpL16enc->ssrc));
rtp_packet_set_seq (packet, g_htons (rtpL16enc->seq));
rtp_packet_set_timestamp (packet, g_htonl ((guint32) rtpL16enc->next_time / GST_SECOND));
if (rtpL16enc->channels == 1) {
rtp_packet_set_payload_type (packet, (guint8) PAYLOAD_L16_MONO);
}
else {
rtp_packet_set_payload_type (packet, (guint8) PAYLOAD_L16_STEREO);
}
/* FIXME: According to RFC 1890, this is required, right? */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
gst_rtpL16enc_htons (buf);
#endif
outbuf = gst_buffer_new ();
GST_BUFFER_SIZE (outbuf) = rtp_packet_get_packet_len (packet) + GST_BUFFER_SIZE (buf);
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
GST_BUFFER_TIMESTAMP (outbuf) = rtpL16enc->next_time;
memcpy (GST_BUFFER_DATA (outbuf), packet->data, rtp_packet_get_packet_len (packet));
memcpy (GST_BUFFER_DATA (outbuf) + rtp_packet_get_packet_len(packet), GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
GST_DEBUG (0,"gst_rtpL16enc_chain: pushing buffer of size %d", GST_BUFFER_SIZE(outbuf));
gst_pad_push (rtpL16enc->srcpad, outbuf);
++rtpL16enc->seq;
rtpL16enc->next_time += rtpL16enc->time_interval * GST_BUFFER_SIZE (buf);
rtp_packet_free (packet);
gst_buffer_unref (buf);
}
static void
gst_rtpL16enc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstRtpL16Enc *rtpL16enc;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_ENC (object));
rtpL16enc = GST_RTP_L16_ENC (object);
switch (prop_id) {
default:
break;
}
}
static void
gst_rtpL16enc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
{
GstRtpL16Enc *rtpL16enc;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_RTP_L16_ENC (object));
rtpL16enc = GST_RTP_L16_ENC (object);
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstElementStateReturn
gst_rtpL16enc_change_state (GstElement * element)
{
GstRtpL16Enc *rtpL16enc;
g_return_val_if_fail (GST_IS_RTP_L16_ENC (element), GST_STATE_FAILURE);
rtpL16enc = GST_RTP_L16_ENC (element);
GST_DEBUG (0, "state pending %d\n", GST_STATE_PENDING (element));
/* if going down into NULL state, close the file if it's open */
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
break;
default:
break;
}
/* if we haven't failed already, give the parent class a chance to ;-) */
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
}
gboolean
gst_rtpL16enc_plugin_init (GModule * module, GstPlugin * plugin)
{
GstElementFactory *rtpL16enc;
rtpL16enc = gst_element_factory_new ("rtpL16enc", GST_TYPE_RTP_L16_ENC, &gst_rtpL16enc_details);
g_return_val_if_fail (rtpL16enc != NULL, FALSE);
gst_element_factory_add_pad_template (rtpL16enc, GST_PAD_TEMPLATE_GET (sink_factory));
gst_element_factory_add_pad_template (rtpL16enc, GST_PAD_TEMPLATE_GET (src_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (rtpL16enc));
return TRUE;
}

80
gst/rtp/gstrtpL16pay.h Normal file
View file

@ -0,0 +1,80 @@
/* 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_L16_ENC_H__
#define __GST_RTP_L16_ENC_H__
#include <gst/gst.h>
#include "rtp-packet.h"
#include "gstrtp-common.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Definition of structure storing data for this element. */
typedef struct _GstRtpL16Enc GstRtpL16Enc;
struct _GstRtpL16Enc
{
GstElement element;
GstPad *sinkpad;
GstPad *srcpad;
guint frequency;
guint channels;
/* the timestamp of the next frame */
guint64 next_time;
/* the interval between frames */
guint64 time_interval;
guint32 ssrc;
guint16 seq;
};
/* Standard definition defining a class for this element. */
typedef struct _GstRtpL16EncClass GstRtpL16EncClass;
struct _GstRtpL16EncClass
{
GstElementClass parent_class;
};
/* Standard macros for defining types for this element. */
#define GST_TYPE_RTP_L16_ENC \
(gst_rtpL16enc_get_type())
#define GST_RTP_L16_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_L16_ENC,GstRtpL16Enc))
#define GST_RTP_L16_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_L16_ENC,GstRtpL16Enc))
#define GST_IS_RTP_L16_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_L16_ENC))
#define GST_IS_RTP_L16_ENC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_L16_ENC))
gboolean gst_rtpL16enc_plugin_init (GModule * module, GstPlugin * plugin);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_RTP_L16_ENC_H__ */

311
gst/rtp/rtp-packet.c Normal file
View file

@ -0,0 +1,311 @@
/*
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 "rtp-packet.h"
#include <glib.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.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;
}

104
gst/rtp/rtp-packet.h Normal file
View file

@ -0,0 +1,104 @@
/*
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 <glib.h>
#include <netinet/in.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
RTP_VERSION = 2,
RTP_HEADER_LEN = 12,
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 */