2 * Copyright (C) <2007> Leandro Melo de Sales <leandroal@gmail.com>
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.
21 * SECTION:element-dccpserversrc
22 * @see_also: dccpclientsink, dccpclientsrc, dccpserversink
24 * This element wait for connection from a client and receive data.
25 * <ulink url="http://www.linuxfoundation.org/en/Net:DCCP">DCCP</ulink> (Datagram
26 * Congestion Control Protocol) is a Transport Layer protocol like
30 * <title>Example pipeline</title>
33 * gst-launch -v filesrc location=music.mp3 ! mp3parse ! dccpclientsink host=localhost port=9011 ccid=2
36 * gst-launch -v dccpserversrc port=9011 ccid=2 ! decodebin ! alsasink
39 * This example pipeline will send a MP3 stream to the server using DCCP.
40 * The server will decode the MP3 and play it.
41 * Run the server pipeline first than the client pipeline.
51 #include "gstdccpserversrc.h"
55 #define DCCP_DEFAULT_CAPS NULL
75 static gboolean gst_dccp_server_src_stop (GstBaseSrc * bsrc);
77 GST_DEBUG_CATEGORY_STATIC (dccpserversrc_debug);
79 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
84 GST_BOILERPLATE (GstDCCPServerSrc, gst_dccp_server_src, GstPushSrc,
87 static guint gst_dccp_server_src_signals[LAST_SIGNAL] = { 0 };
90 * Read a buffer from the server socket
92 * @return GST_FLOW_OK if the send operation was successful, GST_FLOW_ERROR otherwise.
95 gst_dccp_server_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
97 GstDCCPServerSrc *src;
98 GstFlowReturn ret = GST_FLOW_OK;
100 src = GST_DCCP_SERVER_SRC (psrc);
102 GST_LOG_OBJECT (src, "reading a buffer");
104 ret = gst_dccp_read_buffer (GST_ELEMENT (src), src->client_sock_fd, outbuf);
106 if (ret == GST_FLOW_OK) {
108 "Returning buffer from _get of size %d, ts %"
109 GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT
110 ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
111 GST_BUFFER_SIZE (*outbuf),
112 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*outbuf)),
113 GST_TIME_ARGS (GST_BUFFER_DURATION (*outbuf)),
114 GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf));
116 if (!gst_caps_is_equal (src->caps, GST_CAPS_ANY)) {
117 gst_buffer_set_caps (*outbuf, src->caps);
125 * Set the value of a property for the server src.
128 gst_dccp_server_src_set_property (GObject * object, guint prop_id,
129 const GValue * value, GParamSpec * pspec)
131 GstDCCPServerSrc *src = GST_DCCP_SERVER_SRC (object);
135 src->port = g_value_get_int (value);
137 case PROP_CLIENT_SOCK_FD:
138 src->client_sock_fd = g_value_get_int (value);
141 src->closed = g_value_get_boolean (value);
144 src->ccid = g_value_get_int (value);
148 const GstCaps *new_caps_val = gst_value_get_caps (value);
152 if (new_caps_val == NULL) {
153 new_caps = gst_caps_new_any ();
155 new_caps = gst_caps_copy (new_caps_val);
158 old_caps = src->caps;
159 src->caps = new_caps;
161 gst_caps_unref (old_caps);
163 gst_pad_set_caps (GST_BASE_SRC (src)->srcpad, new_caps);
167 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
173 * Get a given property value for the server src.
176 gst_dccp_server_src_get_property (GObject * object, guint prop_id,
177 GValue * value, GParamSpec * pspec)
179 GstDCCPServerSrc *src = GST_DCCP_SERVER_SRC (object);
183 g_value_set_int (value, src->port);
185 case PROP_CLIENT_SOCK_FD:
186 g_value_set_int (value, src->client_sock_fd);
189 g_value_set_boolean (value, src->closed);
192 gst_value_set_caps (value, src->caps);
195 g_value_set_int (value, src->ccid);
198 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
204 * Starts the element. If the sockfd property was not the default, this method
205 * will create a new server socket and wait for a client connection.
207 * @param bsrc - the element
208 * @return TRUE if the send operation was successful, FALSE otherwise.
211 gst_dccp_server_src_start (GstBaseSrc * bsrc)
213 GstDCCPServerSrc *src = GST_DCCP_SERVER_SRC (bsrc);
215 if (src->client_sock_fd == DCCP_DEFAULT_CLIENT_SOCK_FD) {
217 if ((src->sock_fd = gst_dccp_create_new_socket (GST_ELEMENT (src))) < 0) {
221 if (!gst_dccp_make_address_reusable (GST_ELEMENT (src), src->sock_fd)) {
225 /* name the server socket */
226 memset (&src->server_sin, 0, sizeof (src->server_sin));
227 src->server_sin.sin_family = AF_INET; /* network socket */
228 src->server_sin.sin_port = htons (src->port); /* on port */
229 src->server_sin.sin_addr.s_addr = htonl (INADDR_ANY); /* for hosts */
232 if (!gst_dccp_bind_server_socket (GST_ELEMENT (src), src->sock_fd,
237 if (!gst_dccp_set_ccid (GST_ELEMENT (src), src->sock_fd, src->ccid)) {
241 if (!gst_dccp_listen_server_socket (GST_ELEMENT (src), src->sock_fd)) {
245 src->client_sock_fd = gst_dccp_server_wait_connections (GST_ELEMENT (src),
247 if (src->client_sock_fd == -1) {
251 /* the socket is connected */
252 g_signal_emit (src, gst_dccp_server_src_signals[SIGNAL_CONNECTED], 0,
253 src->client_sock_fd);
261 gst_dccp_server_src_base_init (gpointer g_class)
263 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
265 gst_element_class_add_static_pad_template (element_class, &srctemplate);
267 gst_element_class_set_details_simple (element_class, "DCCP server source",
269 "Receive data as a server over the network via DCCP",
270 "E-Phone Team at Federal University of Campina Grande <leandroal@gmail.com>");
275 gst_dccp_server_src_init (GstDCCPServerSrc * this,
276 GstDCCPServerSrcClass * g_class)
278 this->port = DCCP_DEFAULT_PORT;
279 this->sock_fd = DCCP_DEFAULT_SOCK_FD;
280 this->client_sock_fd = DCCP_DEFAULT_CLIENT_SOCK_FD;
281 this->closed = DCCP_DEFAULT_CLOSED;
282 this->ccid = DCCP_DEFAULT_CCID;
283 this->caps = DCCP_DEFAULT_CAPS;
285 gst_base_src_set_format (GST_BASE_SRC (this), GST_FORMAT_TIME);
287 /* Checking if the version of the gstreamer is bigger that 0.10.15 */
288 #if ((GST_VERSION_MAJOR > 0) || \
289 (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR > 10) || \
290 (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 10 && GST_VERSION_MICRO >= 15))
291 gst_base_src_set_do_timestamp (GST_BASE_SRC (this), TRUE);
294 /* FIXME is this correct? */
295 gst_base_src_set_live (GST_BASE_SRC (this), TRUE);
300 gst_dccp_server_src_finalize (GObject * gobject)
302 GstDCCPServerSrc *this = GST_DCCP_SERVER_SRC (gobject);
305 gst_caps_unref (this->caps);
309 G_OBJECT_CLASS (parent_class)->finalize (gobject);
314 gst_dccp_server_src_stop (GstBaseSrc * bsrc)
316 GstDCCPServerSrc *src;
318 src = GST_DCCP_SERVER_SRC (bsrc);
320 gst_dccp_socket_close (GST_ELEMENT (src), &(src->sock_fd));
321 if (src->client_sock_fd != DCCP_DEFAULT_CLIENT_SOCK_FD && src->closed == TRUE) {
322 gst_dccp_socket_close (GST_ELEMENT (src), &(src->client_sock_fd));
329 gst_dccp_server_src_class_init (GstDCCPServerSrcClass * klass)
331 GObjectClass *gobject_class;
332 GstBaseSrcClass *gstbasesrc_class;
333 GstPushSrcClass *gstpush_src_class;
335 gobject_class = (GObjectClass *) klass;
336 gstbasesrc_class = (GstBaseSrcClass *) klass;
337 gstpush_src_class = (GstPushSrcClass *) klass;
339 gobject_class->set_property = gst_dccp_server_src_set_property;
340 gobject_class->get_property = gst_dccp_server_src_get_property;
342 gobject_class->finalize = gst_dccp_server_src_finalize;
344 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PORT,
345 g_param_spec_int ("port", "Port",
346 "The port to listen to", 0, G_MAXUINT16,
347 DCCP_DEFAULT_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
349 g_object_class_install_property (gobject_class, PROP_CLIENT_SOCK_FD,
350 g_param_spec_int ("sockfd", "Socket fd",
351 "The client socket file descriptor", -1, G_MAXINT,
352 DCCP_DEFAULT_CLIENT_SOCK_FD,
353 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
355 g_object_class_install_property (gobject_class, PROP_CLOSED,
356 g_param_spec_boolean ("close-socket", "Close socket",
357 "Close client socket at the end of stream", DCCP_DEFAULT_CLOSED,
358 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
360 g_object_class_install_property (gobject_class, PROP_CCID,
361 g_param_spec_int ("ccid", "CCID",
362 "The Congestion Control IDentified to be used", 2, G_MAXINT,
363 DCCP_DEFAULT_CCID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
365 g_object_class_install_property (gobject_class, PROP_CAPS,
366 g_param_spec_boxed ("caps", "Caps",
367 "The caps of the source pad", GST_TYPE_CAPS,
368 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
372 * GstDccpServerSrc::connected:
373 * @src: the gstdccpserversrc element that emitted this signal
374 * @fd: the connected socket file descriptor
376 * Reports that the element has connected, giving the fd of the socket
378 gst_dccp_server_src_signals[SIGNAL_CONNECTED] =
379 g_signal_new ("connected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
380 G_STRUCT_OFFSET (GstDCCPServerSrcClass, connected), NULL, NULL,
381 gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
383 gstbasesrc_class->start = gst_dccp_server_src_start;
384 gstbasesrc_class->stop = gst_dccp_server_src_stop;
386 gstpush_src_class->create = gst_dccp_server_src_create;
388 GST_DEBUG_CATEGORY_INIT (dccpserversrc_debug, "dccpserversrc", 0,
389 "DCCP Server Source");