diff options
author | Andy Wingo <wingo@pobox.com> | 2001-12-22 23:27:31 +0000 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2001-12-22 23:27:31 +0000 |
commit | 185612aae3b8acae2b32e0e6561691a7c640cd0d (patch) | |
tree | 7cd1990c3df5c63f402f3e0bdf6b51b3ed58fc41 /gst/udp | |
parent | 87dab192cf5792f847a22e0c3e9afe78553739b5 (diff) |
Initial revision
Original commit message from CVS:
Initial revision
Diffstat (limited to 'gst/udp')
-rw-r--r-- | gst/udp/.gitignore | 7 | ||||
-rw-r--r-- | gst/udp/Makefile.am | 10 | ||||
-rw-r--r-- | gst/udp/README | 28 | ||||
-rw-r--r-- | gst/udp/gstudp.c | 52 | ||||
-rw-r--r-- | gst/udp/gstudpsink.c | 301 | ||||
-rw-r--r-- | gst/udp/gstudpsink.h | 91 | ||||
-rw-r--r-- | gst/udp/gstudpsrc.c | 300 | ||||
-rw-r--r-- | gst/udp/gstudpsrc.h | 88 |
8 files changed, 877 insertions, 0 deletions
diff --git a/gst/udp/.gitignore b/gst/udp/.gitignore new file mode 100644 index 00000000..08f5ed37 --- /dev/null +++ b/gst/udp/.gitignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +*.o +*.lo +*.la +.deps +.libs diff --git a/gst/udp/Makefile.am b/gst/udp/Makefile.am new file mode 100644 index 00000000..0cd25aac --- /dev/null +++ b/gst/udp/Makefile.am @@ -0,0 +1,10 @@ +filterdir = $(libdir)/gst + +filter_LTLIBRARIES = libgstudp.la + +libgstudp_la_SOURCES = gstudp.c gstudpsrc.c gstudpsink.c +libgstudp_la_CFLAGS = $(GST_CFLAGS) + +noinst_HEADERS = gstudpsink.h gstudpsrc.h + +EXTRA_DIST = README diff --git a/gst/udp/README b/gst/udp/README new file mode 100644 index 00000000..e032e74f --- /dev/null +++ b/gst/udp/README @@ -0,0 +1,28 @@ +* What is UDP src/sink? + +This plugin is *not* meant to be a professional stream broadcast +solution, like icecast or realaudio or whatever. + +This plugin is basically for testing and simple hacks: raw audio +or packetized gsm should be fine. + + +* Shortcomings + +Even given our modest ambitions, the current code is doesn't handle +caps negotiation robustly. + + +* Todo + +This plugin should offer different modes for caps negotiation: none, +udp, or tcp. The udp mode should include the caps every five packets +(approx). The tcp mode can do bi-directional negotiation. + +Perhaps this plugin can be the example of how to do caps negotiation +via a point-to-point protocol. + + +12 Sep 2001 +Wim Taymans <wim.taymans@chello.be> +Joshua N Pritikin <vishnu@pobox.com> diff --git a/gst/udp/gstudp.c b/gst/udp/gstudp.c new file mode 100644 index 00000000..8bea9876 --- /dev/null +++ b/gst/udp/gstudp.c @@ -0,0 +1,52 @@ +/* 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 "gstudpsrc.h" +#include "gstudpsink.h" + +/* elementfactory information */ +extern GstElementDetails gst_udpsrc_details; +extern GstElementDetails gst_udpsink_details; + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *src, *sink; + + /* create an elementfactory for the udpsrc element */ + sink = gst_elementfactory_new ("udpsink",GST_TYPE_UDPSINK, + &gst_udpsink_details); + g_return_val_if_fail (sink != NULL, FALSE); + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (sink)); + + src = gst_elementfactory_new ("udpsrc",GST_TYPE_UDPSRC, + &gst_udpsrc_details); + g_return_val_if_fail (src != NULL, FALSE); + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (src)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "udp", + plugin_init +}; diff --git a/gst/udp/gstudpsink.c b/gst/udp/gstudpsink.c new file mode 100644 index 00000000..81d7a952 --- /dev/null +++ b/gst/udp/gstudpsink.c @@ -0,0 +1,301 @@ +/* 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 "gstudpsink.h" + +#define UDP_DEFAULT_HOST "localhost" +#define UDP_DEFAULT_PORT 4951 + +/* elementfactory information */ +GstElementDetails gst_udpsink_details = { + "UDP packet sender", + "Transport/", + "", + VERSION, + "Wim Taymans <wim.taymans@chello.be>", + "(C) 2001", +}; + +/* UDPSink signals and args */ +enum { + FRAME_ENCODED, + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_HOST, + ARG_PORT, + /* FILL ME */ +}; + +static void gst_udpsink_class_init (GstUDPSink *klass); +static void gst_udpsink_init (GstUDPSink *udpsink); + +static void gst_udpsink_chain (GstPad *pad,GstBuffer *buf); +static GstElementStateReturn gst_udpsink_change_state (GstElement *element); + +static void gst_udpsink_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void gst_udpsink_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); + + +static GstElementClass *parent_class = NULL; +//static guint gst_udpsink_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_udpsink_get_type (void) +{ + static GType udpsink_type = 0; + + + if (!udpsink_type) { + static const GTypeInfo udpsink_info = { + sizeof(GstUDPSinkClass), + NULL, + NULL, + (GClassInitFunc)gst_udpsink_class_init, + NULL, + NULL, + sizeof(GstUDPSink), + 0, + (GInstanceInitFunc)gst_udpsink_init, + NULL + }; + udpsink_type = g_type_register_static (GST_TYPE_ELEMENT, "GstUDPSink", &udpsink_info, 0); + } + return udpsink_type; +} + +static void +gst_udpsink_class_init (GstUDPSink *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_HOST, + g_param_spec_string ("host", "nost", "The host to send the packets to", + UDP_DEFAULT_HOST, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PORT, + g_param_spec_int ("port", "port", "The port to send the packets to", + 0, 32768, UDP_DEFAULT_PORT, G_PARAM_READWRITE)); + + gobject_class->set_property = gst_udpsink_set_property; + gobject_class->get_property = gst_udpsink_get_property; + + gstelement_class->change_state = gst_udpsink_change_state; +} + + +static void +gst_udpsink_newcaps (GstPad *pad, GstCaps *caps) +{ + GstUDPSink *udpsink; + struct sockaddr_in serv_addr; + struct hostent *serverhost; + int fd; + FILE *f; +#ifndef GST_DISABLE_LOADSAVE + xmlDocPtr doc; +#endif + + udpsink = GST_UDPSINK (gst_pad_get_parent (pad)); + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + perror("socket"); + return; + } + memset(&serv_addr, 0, sizeof(serv_addr)); + /* its a name rather than an ipnum */ + serverhost = gethostbyname(udpsink->host); + if (serverhost == (struct hostent *)0) { + perror("gethostbyname"); + return; + } + memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(udpsink->port); + + if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) { + g_printerr ("udpsink: connect to %s port %d failed: %s\n", + udpsink->host, udpsink->port, sys_errlist[errno]); + return; + } + f = fdopen (dup (fd), "wb"); + +#ifndef GST_DISABLE_LOADSAVE + doc = xmlNewDoc ("1.0"); + doc->xmlRootNode = xmlNewDocNode (doc, NULL, "NewCaps", NULL); + + gst_caps_save_thyself (caps, doc->xmlRootNode); + xmlDocDump(f, doc); +#endif + + fclose (f); + close (fd); +} + +static void +gst_udpsink_init (GstUDPSink *udpsink) +{ + /* create the sink and src pads */ + udpsink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + gst_element_add_pad (GST_ELEMENT (udpsink), udpsink->sinkpad); + gst_pad_set_chain_function (udpsink->sinkpad, gst_udpsink_chain); + gst_pad_set_newcaps_function (udpsink->sinkpad, gst_udpsink_newcaps); + + udpsink->host = g_strdup (UDP_DEFAULT_HOST); + udpsink->port = UDP_DEFAULT_PORT; +} + +static void +gst_udpsink_chain (GstPad *pad, GstBuffer *buf) +{ + GstUDPSink *udpsink; + int tolen; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + udpsink = GST_UDPSINK (GST_OBJECT_PARENT (pad)); + + tolen = sizeof(udpsink->theiraddr); + + if (sendto (udpsink->sock, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), 0, + (struct sockaddr *) &udpsink->theiraddr, tolen) == -1) + { + perror("sending"); + } + + gst_buffer_unref(buf); +} + +static void +gst_udpsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstUDPSink *udpsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_UDPSINK(object)); + udpsink = GST_UDPSINK(object); + + switch (prop_id) { + case ARG_HOST: + if (udpsink->host != NULL) g_free(udpsink->host); + if (g_value_get_string (value) == NULL) + udpsink->host = NULL; + else + udpsink->host = g_strdup (g_value_get_string (value)); + break; + case ARG_PORT: + udpsink->port = g_value_get_int (value); + break; + default: + break; + } +} + +static void +gst_udpsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstUDPSink *udpsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_UDPSINK(object)); + udpsink = GST_UDPSINK(object); + + switch (prop_id) { + case ARG_HOST: + g_value_set_string (value, udpsink->host); + break; + case ARG_PORT: + g_value_set_int (value, udpsink->port); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +// create a socket for sending to remote machine +static gboolean +gst_udpsink_init_send (GstUDPSink *sink) +{ + struct hostent *he; + + bzero (&sink->theiraddr, sizeof (sink->theiraddr)); + sink->theiraddr.sin_family = AF_INET; // host byte order + sink->theiraddr.sin_port = htons (sink->port); // short, network byte order + if ((he = gethostbyname (sink->host)) == NULL) { + perror("gethostbyname"); + return FALSE; + } + sink->theiraddr.sin_addr = *((struct in_addr *) he->h_addr); + + if ((sink->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1) { + perror("socket"); + return FALSE; + } + + GST_FLAG_SET (sink, GST_UDPSINK_OPEN); + + return TRUE; +} + +static void +gst_udpsink_close (GstUDPSink *sink) +{ + close (sink->sock); + + GST_FLAG_UNSET (sink, GST_UDPSINK_OPEN); +} + +static GstElementStateReturn +gst_udpsink_change_state (GstElement *element) +{ + g_return_val_if_fail (GST_IS_UDPSINK (element), GST_STATE_FAILURE); + + if (GST_STATE_PENDING (element) == GST_STATE_NULL) { + if (GST_FLAG_IS_SET (element, GST_UDPSINK_OPEN)) + gst_udpsink_close (GST_UDPSINK (element)); + } else { + if (!GST_FLAG_IS_SET (element, GST_UDPSINK_OPEN)) { + if (!gst_udpsink_init_send (GST_UDPSINK (element))) + return GST_STATE_FAILURE; + } + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; +} + diff --git a/gst/udp/gstudpsink.h b/gst/udp/gstudpsink.h new file mode 100644 index 00000000..4a7c335b --- /dev/null +++ b/gst/udp/gstudpsink.h @@ -0,0 +1,91 @@ +/* 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_UDPSINK_H__ +#define __GST_UDPSINK_H__ + + +#include <config.h> +#include <gst/gst.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <fcntl.h> + +#define GST_TYPE_UDPSINK \ + (gst_udpsink_get_type()) +#define GST_UDPSINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_UDPSINK,GstUDPSink)) +#define GST_UDPSINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_UDPSINK,GstUDPSink)) +#define GST_IS_UDPSINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_UDPSINK)) +#define GST_IS_UDPSINK_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_UDPSINK)) + +typedef struct _GstUDPSink GstUDPSink; +typedef struct _GstUDPSinkClass GstUDPSinkClass; + +typedef enum { + GST_UDPSINK_OPEN = GST_ELEMENT_FLAG_LAST, + + GST_UDPSINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2, +} GstUDPSinkFlags; + +struct _GstUDPSink { + GstElement element; + + /* pads */ + GstPad *sinkpad,*srcpad; + + int sock; + struct sockaddr_in theiraddr; + + gint port; + gchar *host; +}; + +struct _GstUDPSinkClass { + GstElementClass parent_class; + +}; + +GType gst_udpsink_get_type(void); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_UDPSINK_H__ */ diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c new file mode 100644 index 00000000..4400a064 --- /dev/null +++ b/gst/udp/gstudpsrc.c @@ -0,0 +1,300 @@ +/* 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 "gstudpsrc.h" + +#define UDP_DEFAULT_PORT 4951 + +/* elementfactory information */ +GstElementDetails gst_udpsrc_details = { + "UDP packet receiver", + "Transport/", + "", + VERSION, + "Wim Taymans <wim.taymans@chello.be>", + "(C) 2001", +}; + +/* UDPSrc signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_PORT, + /* FILL ME */ +}; + +static void gst_udpsrc_class_init (GstUDPSrc *klass); +static void gst_udpsrc_init (GstUDPSrc *udpsrc); + +static GstBuffer* gst_udpsrc_get (GstPad *pad); +static GstElementStateReturn + gst_udpsrc_change_state (GstElement *element); + +static void gst_udpsrc_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void gst_udpsrc_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); + +static GstElementClass *parent_class = NULL; +//static guint gst_udpsrc_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_udpsrc_get_type (void) +{ + static GType udpsrc_type = 0; + + + if (!udpsrc_type) { + static const GTypeInfo udpsrc_info = { + sizeof(GstUDPSrcClass), + NULL, + NULL, + (GClassInitFunc)gst_udpsrc_class_init, + NULL, + NULL, + sizeof(GstUDPSrc), + 0, + (GInstanceInitFunc)gst_udpsrc_init, + NULL + }; + udpsrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstUDPSrc", &udpsrc_info, 0); + } + return udpsrc_type; +} + +static void +gst_udpsrc_class_init (GstUDPSrc *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_PORT, + g_param_spec_int ("port", "port", "The port to receive the packets from", + 0, 32768, UDP_DEFAULT_PORT, G_PARAM_READWRITE)); + + gobject_class->set_property = gst_udpsrc_set_property; + gobject_class->get_property = gst_udpsrc_get_property; + + gstelement_class->change_state = gst_udpsrc_change_state; +} + + +static void +gst_udpsrc_init (GstUDPSrc *udpsrc) +{ + /* create the src and src pads */ + udpsrc->srcpad = gst_pad_new ("src", GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (udpsrc), udpsrc->srcpad); + gst_pad_set_get_function (udpsrc->srcpad, gst_udpsrc_get); + + udpsrc->port = UDP_DEFAULT_PORT; +} + +static GstBuffer* +gst_udpsrc_get (GstPad *pad) +{ + GstUDPSrc *udpsrc; + GstBuffer *outbuf; + struct sockaddr_in tmpaddr; + int len, numbytes; + fd_set read_fds; + + g_return_val_if_fail (pad != NULL, NULL); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + udpsrc = GST_UDPSRC (GST_OBJECT_PARENT (pad)); + + FD_ZERO (&read_fds); + FD_SET (udpsrc->control_sock, &read_fds); + FD_SET (udpsrc->sock, &read_fds); + + if (select (udpsrc->control_sock+1, &read_fds, NULL, NULL, NULL) > 0) { + if (FD_ISSET (udpsrc->control_sock, &read_fds)) { +#ifndef GST_DISABLE_LOADSAVE + guchar *buf; + int ret; + int fdread; + struct sockaddr addr; + socklen_t len; + xmlDocPtr doc; + GstCaps *caps; + + buf = g_malloc (1024*10); + + len = sizeof (struct sockaddr); + fdread = accept (udpsrc->control_sock, &addr, &len); + if (fdread < 0) { + perror ("accept"); + } + + ret = read (fdread, buf, 1024*10); + if (ret < 0) { + perror ("read"); + } + buf[ret] = '\0'; + doc = xmlParseMemory(buf, ret); + caps = gst_caps_load_thyself(doc->xmlRootNode); + + gst_pad_set_caps (udpsrc->srcpad, caps); + +#endif + outbuf = NULL; + } + else { + outbuf = gst_buffer_new (); + GST_BUFFER_DATA (outbuf) = g_malloc (24000); + GST_BUFFER_SIZE (outbuf) = 24000; + + numbytes = recvfrom (udpsrc->sock, GST_BUFFER_DATA (outbuf), + GST_BUFFER_SIZE (outbuf), 0, (struct sockaddr *)&tmpaddr, &len); + + if (numbytes != -1) { + GST_BUFFER_SIZE (outbuf) = numbytes; + } + else { + perror ("recvfrom"); + gst_buffer_unref (outbuf); + outbuf = NULL; + } + + } + } + else { + perror ("select"); + outbuf = NULL; + } + return outbuf; +} + + +static void +gst_udpsrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstUDPSrc *udpsrc; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_UDPSRC(object)); + udpsrc = GST_UDPSRC(object); + + switch (prop_id) { + case ARG_PORT: + udpsrc->port = g_value_get_int (value); + break; + default: + break; + } +} + +static void +gst_udpsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstUDPSrc *udpsrc; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_UDPSRC(object)); + udpsrc = GST_UDPSRC(object); + + switch (prop_id) { + case ARG_PORT: + g_value_set_int (value, udpsrc->port); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +// create a socket for sending to remote machine +static gboolean +gst_udpsrc_init_receive (GstUDPSrc *src) +{ + bzero (&src->myaddr, sizeof (src->myaddr)); + src->myaddr.sin_family = AF_INET; // host byte order + src->myaddr.sin_port = htons (src->port); // short, network byte order + src->myaddr.sin_addr.s_addr = INADDR_ANY; + + if ((src->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1) { + perror("socket"); + return FALSE; + } + + if (bind (src->sock, (struct sockaddr *) &src->myaddr, sizeof (src->myaddr)) == -1) { + perror("bind"); + return FALSE; + } + + if ((src->control_sock = socket (AF_INET, SOCK_STREAM, 0)) == -1) { + perror("control_socket"); + return FALSE; + } + + if (bind (src->control_sock, (struct sockaddr *) &src->myaddr, sizeof (src->myaddr)) == -1) { + perror("control_bind"); + return FALSE; + } + if (listen (src->control_sock, 5) == -1) { + perror("listen"); + return FALSE; + } + fcntl (src->control_sock, F_SETFL, O_NONBLOCK); + + GST_FLAG_SET (src, GST_UDPSRC_OPEN); + + return TRUE; +} + +static void +gst_udpsrc_close (GstUDPSrc *src) +{ + close (src->sock); + + GST_FLAG_UNSET (src, GST_UDPSRC_OPEN); +} + +static GstElementStateReturn +gst_udpsrc_change_state (GstElement *element) +{ + g_return_val_if_fail (GST_IS_UDPSRC (element), GST_STATE_FAILURE); + + if (GST_STATE_PENDING (element) == GST_STATE_NULL) { + if (GST_FLAG_IS_SET (element, GST_UDPSRC_OPEN)) + gst_udpsrc_close (GST_UDPSRC (element)); + } else { + if (!GST_FLAG_IS_SET (element, GST_UDPSRC_OPEN)) { + if (!gst_udpsrc_init_receive (GST_UDPSRC (element))) + return GST_STATE_FAILURE; + } + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; +} + diff --git a/gst/udp/gstudpsrc.h b/gst/udp/gstudpsrc.h new file mode 100644 index 00000000..cf0d1d38 --- /dev/null +++ b/gst/udp/gstudpsrc.h @@ -0,0 +1,88 @@ +/* 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_UDPSRC_H__ +#define __GST_UDPSRC_H__ + +#include <config.h> +#include <gst/gst.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <fcntl.h> + +#define GST_TYPE_UDPSRC \ + (gst_udpsrc_get_type()) +#define GST_UDPSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_UDPSRC,GstUDPSrc)) +#define GST_UDPSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_UDPSRC,GstUDPSrc)) +#define GST_IS_UDPSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_UDPSRC)) +#define GST_IS_UDPSRC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_UDPSRC)) + +typedef struct _GstUDPSrc GstUDPSrc; +typedef struct _GstUDPSrcClass GstUDPSrcClass; + +typedef enum { + GST_UDPSRC_OPEN = GST_ELEMENT_FLAG_LAST, + + GST_UDPSRC_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2, +} GstUDPSrcFlags; + +struct _GstUDPSrc { + GstElement element; + + /* pads */ + GstPad *sinkpad,*srcpad; + + int port; + int sock; + int control_sock; + struct sockaddr_in myaddr; +}; + +struct _GstUDPSrcClass { + GstElementClass parent_class; +}; + +GType gst_udpsrc_get_type(void); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_UDPSRC_H__ */ |