2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
24 #include "gstudpsink.h"
26 #define UDP_DEFAULT_HOST "localhost"
27 #define UDP_DEFAULT_PORT 4951
29 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
34 /* elementfactory information */
35 static GstElementDetails gst_udpsink_details =
36 GST_ELEMENT_DETAILS ("UDP packet sender",
38 "Send data over the network via UDP",
39 "Wim Taymans <wim.taymans@chello.be>");
41 /* UDPSink signals and args */
56 static void gst_udpsink_base_init (gpointer g_class);
57 static void gst_udpsink_class_init (GstUDPSink * klass);
58 static void gst_udpsink_init (GstUDPSink * udpsink);
60 static void gst_udpsink_get_times (GstBaseSink * sink, GstBuffer * buffer,
61 GstClockTime * start, GstClockTime * end);
62 static GstFlowReturn gst_udpsink_render (GstBaseSink * sink,
64 static GstElementStateReturn gst_udpsink_change_state (GstElement * element);
66 static void gst_udpsink_set_property (GObject * object, guint prop_id,
67 const GValue * value, GParamSpec * pspec);
68 static void gst_udpsink_get_property (GObject * object, guint prop_id,
69 GValue * value, GParamSpec * pspec);
71 static GstElementClass *parent_class = NULL;
73 /*static guint gst_udpsink_signals[LAST_SIGNAL] = { 0 }; */
76 gst_udpsink_get_type (void)
78 static GType udpsink_type = 0;
81 static const GTypeInfo udpsink_info = {
82 sizeof (GstUDPSinkClass),
83 gst_udpsink_base_init,
85 (GClassInitFunc) gst_udpsink_class_init,
90 (GInstanceInitFunc) gst_udpsink_init,
95 g_type_register_static (GST_TYPE_BASESINK, "GstUDPSink", &udpsink_info,
102 gst_udpsink_base_init (gpointer g_class)
104 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
106 gst_element_class_add_pad_template (element_class,
107 gst_static_pad_template_get (&sink_template));
109 gst_element_class_set_details (element_class, &gst_udpsink_details);
113 gst_udpsink_class_init (GstUDPSink * klass)
115 GObjectClass *gobject_class;
116 GstElementClass *gstelement_class;
117 GstBaseSinkClass *gstbasesink_class;
119 gobject_class = (GObjectClass *) klass;
120 gstelement_class = (GstElementClass *) klass;
121 gstbasesink_class = (GstBaseSinkClass *) klass;
123 parent_class = g_type_class_ref (GST_TYPE_BASESINK);
125 gobject_class->set_property = gst_udpsink_set_property;
126 gobject_class->get_property = gst_udpsink_get_property;
128 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HOST,
129 g_param_spec_string ("host", "host",
130 "The host/IP/Multicast group to send the packets to",
131 UDP_DEFAULT_HOST, G_PARAM_READWRITE));
132 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PORT,
133 g_param_spec_int ("port", "port", "The port to send the packets to",
134 0, 32768, UDP_DEFAULT_PORT, G_PARAM_READWRITE));
136 gstelement_class->change_state = gst_udpsink_change_state;
138 gstbasesink_class->get_times = gst_udpsink_get_times;
139 gstbasesink_class->render = gst_udpsink_render;
144 gst_udpsink_init (GstUDPSink * udpsink)
146 udpsink->host = g_strdup (UDP_DEFAULT_HOST);
147 udpsink->port = UDP_DEFAULT_PORT;
151 gst_udpsink_get_times (GstBaseSink * sink, GstBuffer * buffer,
152 GstClockTime * start, GstClockTime * end)
154 *start = GST_BUFFER_TIMESTAMP (buffer);
155 *end = *start + GST_BUFFER_DURATION (buffer);
159 gst_udpsink_render (GstBaseSink * sink, GstBuffer * buffer)
165 udpsink = GST_UDPSINK (sink);
167 size = GST_BUFFER_SIZE (buffer);
168 data = GST_BUFFER_DATA (buffer);
171 ret = sendto (udpsink->sock, data, size, 0,
172 (struct sockaddr *) &udpsink->theiraddr, sizeof (udpsink->theiraddr));
175 if (errno != EINTR && errno != EAGAIN)
184 GST_DEBUG ("got send error");
185 return GST_FLOW_ERROR;
190 gst_udpsink_set_property (GObject * object, guint prop_id, const GValue * value,
195 udpsink = GST_UDPSINK (object);
199 if (udpsink->host != NULL)
200 g_free (udpsink->host);
201 if (g_value_get_string (value) == NULL)
202 udpsink->host = NULL;
204 udpsink->host = g_strdup (g_value_get_string (value));
207 udpsink->port = g_value_get_int (value);
215 gst_udpsink_get_property (GObject * object, guint prop_id, GValue * value,
220 udpsink = GST_UDPSINK (object);
224 g_value_set_string (value, udpsink->host);
227 g_value_set_int (value, udpsink->port);
230 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
236 /* create a socket for sending to remote machine */
238 gst_udpsink_init_send (GstUDPSink * sink)
244 memset (&sink->theiraddr, 0, sizeof (sink->theiraddr));
245 sink->theiraddr.sin_family = AF_INET; /* host byte order */
246 sink->theiraddr.sin_port = htons (sink->port); /* short, network byte order */
248 /* if its an IP address */
249 if (inet_aton (sink->host, &addr)) {
250 /* check if its a multicast address */
251 if ((ntohl (addr.s_addr) & 0xe0000000) == 0xe0000000) {
252 sink->multi_addr.imr_multiaddr.s_addr = addr.s_addr;
253 sink->multi_addr.imr_interface.s_addr = INADDR_ANY;
255 sink->theiraddr.sin_addr = sink->multi_addr.imr_multiaddr;
257 /* Joining the multicast group */
258 setsockopt (sink->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &sink->multi_addr,
259 sizeof (sink->multi_addr));
263 sink->theiraddr.sin_addr = *((struct in_addr *) &addr);
267 /* we dont need to lookup for localhost */
268 else if (strcmp (sink->host, UDP_DEFAULT_HOST) == 0 &&
269 inet_aton ("127.0.0.1", &addr)) {
270 sink->theiraddr.sin_addr = *((struct in_addr *) &addr);
273 /* if its a hostname */
274 else if ((he = gethostbyname (sink->host))) {
275 sink->theiraddr.sin_addr = *((struct in_addr *) he->h_addr);
279 perror ("hostname lookup error?");
283 if ((sink->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
289 setsockopt (sink->sock, SOL_SOCKET, SO_BROADCAST, &bc_val, sizeof (bc_val));
295 gst_udpsink_close (GstUDPSink * sink)
300 static GstElementStateReturn
301 gst_udpsink_change_state (GstElement * element)
303 GstElementStateReturn ret;
307 sink = GST_UDPSINK (element);
308 transition = GST_STATE_TRANSITION (element);
310 switch (transition) {
311 case GST_STATE_READY_TO_PAUSED:
312 if (!gst_udpsink_init_send (sink))
319 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
321 switch (transition) {
322 case GST_STATE_PAUSED_TO_READY:
323 gst_udpsink_close (sink);
333 return GST_STATE_FAILURE;