nicesrc: Use gst_buffer_fill
[sipe-libnice.git] / gst / gstnicesrc.c
blobf264d28a3c8ba8d243f14d177d56c4bcb300a6a9
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006, 2007 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * (C) 2006, 2007 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
24 * Contributors:
25 * Dafydd Harries, Collabora Ltd.
27 * Alternatively, the contents of this file may be used under the terms of the
28 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
29 * case the provisions of LGPL are applicable instead of those above. If you
30 * wish to allow use of your version of this file only under the terms of the
31 * LGPL and not to allow others to use your version of this file under the
32 * MPL, indicate your decision by deleting the provisions above and replace
33 * them with the notice and other provisions required by the LGPL. If you do
34 * not delete the provisions above, a recipient may use your version of this
35 * file under either the MPL or the LGPL.
37 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif
41 #include <string.h>
43 #include "gstnicesrc.h"
45 GST_DEBUG_CATEGORY_STATIC (nicesrc_debug);
46 #define GST_CAT_DEFAULT nicesrc_debug
49 #define BUFFER_SIZE (65536)
51 static GstFlowReturn
52 gst_nice_src_create (
53 GstPushSrc *basesrc,
54 GstBuffer **buffer);
56 static gboolean
57 gst_nice_src_unlock (
58 GstBaseSrc *basesrc);
60 static gboolean
61 gst_nice_src_unlock_stop (
62 GstBaseSrc *basesrc);
64 static void
65 gst_nice_src_set_property (
66 GObject *object,
67 guint prop_id,
68 const GValue *value,
69 GParamSpec *pspec);
71 static void
72 gst_nice_src_get_property (
73 GObject *object,
74 guint prop_id,
75 GValue *value,
76 GParamSpec *pspec);
79 static void
80 gst_nice_src_dispose (GObject *object);
82 static GstStateChangeReturn
83 gst_nice_src_change_state (
84 GstElement * element,
85 GstStateChange transition);
87 static GstStaticPadTemplate gst_nice_src_src_template =
88 GST_STATIC_PAD_TEMPLATE (
89 "src",
90 GST_PAD_SRC,
91 GST_PAD_ALWAYS,
92 GST_STATIC_CAPS_ANY);
94 G_DEFINE_TYPE (GstNiceSrc, gst_nice_src, GST_TYPE_PUSH_SRC);
96 enum
98 PROP_AGENT = 1,
99 PROP_STREAM,
100 PROP_COMPONENT
104 static void
105 gst_nice_src_class_init (GstNiceSrcClass *klass)
107 GstPushSrcClass *gstpushsrc_class;
108 GstBaseSrcClass *gstbasesrc_class;
109 GstElementClass *gstelement_class;
110 GObjectClass *gobject_class;
112 GST_DEBUG_CATEGORY_INIT (nicesrc_debug, "nicesrc",
113 0, "libnice source");
115 gstpushsrc_class = (GstPushSrcClass *) klass;
116 gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create);
118 gstbasesrc_class = (GstBaseSrcClass *) klass;
119 gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock);
120 gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop);
122 gobject_class = (GObjectClass *) klass;
123 gobject_class->set_property = gst_nice_src_set_property;
124 gobject_class->get_property = gst_nice_src_get_property;
125 gobject_class->dispose = gst_nice_src_dispose;
127 gstelement_class = (GstElementClass *) klass;
128 gstelement_class->change_state = gst_nice_src_change_state;
130 gst_element_class_add_pad_template (gstelement_class,
131 gst_static_pad_template_get (&gst_nice_src_src_template));
132 gst_element_class_set_metadata (gstelement_class,
133 "ICE source",
134 "Source",
135 "Interactive UDP connectivity establishment",
136 "Dafydd Harries <dafydd.harries@collabora.co.uk>");
138 g_object_class_install_property (gobject_class, PROP_AGENT,
139 g_param_spec_object (
140 "agent",
141 "Agent",
142 "The NiceAgent this source is bound to",
143 NICE_TYPE_AGENT,
144 G_PARAM_READWRITE));
146 g_object_class_install_property (gobject_class, PROP_STREAM,
147 g_param_spec_uint (
148 "stream",
149 "Stream ID",
150 "The ID of the stream to read from",
152 G_MAXUINT,
154 G_PARAM_READWRITE));
156 g_object_class_install_property (gobject_class, PROP_COMPONENT,
157 g_param_spec_uint (
158 "component",
159 "Component ID",
160 "The ID of the component to read from",
162 G_MAXUINT,
164 G_PARAM_READWRITE));
167 static void
168 gst_nice_src_init (GstNiceSrc *src)
170 gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
171 gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
172 gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
173 src->agent = NULL;
174 src->stream_id = 0;
175 src->component_id = 0;
176 src->mainctx = g_main_context_new ();
177 src->mainloop = g_main_loop_new (src->mainctx, FALSE);
178 src->unlocked = FALSE;
179 src->idle_source = NULL;
180 src->outbufs = g_queue_new ();
183 static void
184 gst_nice_src_read_callback (NiceAgent *agent,
185 guint stream_id,
186 guint component_id,
187 guint len,
188 gchar *buf,
189 gpointer data)
191 GstBaseSrc *basesrc = GST_BASE_SRC (data);
192 GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc);
193 GstBuffer *buffer = NULL;
195 GST_LOG_OBJECT (agent, "Got buffer, getting out of the main loop");
197 buffer = gst_buffer_new_allocate (NULL, len, NULL);
198 gst_buffer_fill (buffer, 0, buf, len);
199 g_queue_push_tail (nicesrc->outbufs, buffer);
201 g_main_loop_quit (nicesrc->mainloop);
204 static gboolean
205 gst_nice_src_unlock_idler (gpointer data)
207 GstNiceSrc *nicesrc = GST_NICE_SRC (data);
209 GST_OBJECT_LOCK (nicesrc);
210 if (nicesrc->unlocked)
211 g_main_loop_quit (nicesrc->mainloop);
213 if (nicesrc->idle_source) {
214 g_source_destroy (nicesrc->idle_source);
215 g_source_unref (nicesrc->idle_source);
216 nicesrc->idle_source = NULL;
218 GST_OBJECT_UNLOCK (nicesrc);
220 return FALSE;
223 static gboolean
224 gst_nice_src_unlock (GstBaseSrc *src)
226 GstNiceSrc *nicesrc = GST_NICE_SRC (src);
228 GST_OBJECT_LOCK (src);
229 nicesrc->unlocked = TRUE;
231 g_main_loop_quit (nicesrc->mainloop);
233 if (!nicesrc->idle_source) {
234 nicesrc->idle_source = g_idle_source_new ();
235 g_source_set_priority (nicesrc->idle_source, G_PRIORITY_HIGH);
236 g_source_set_callback (nicesrc->idle_source, gst_nice_src_unlock_idler, src, NULL);
237 g_source_attach (nicesrc->idle_source, g_main_loop_get_context (nicesrc->mainloop));
239 GST_OBJECT_UNLOCK (src);
241 return TRUE;
244 static gboolean
245 gst_nice_src_unlock_stop (GstBaseSrc *src)
247 GstNiceSrc *nicesrc = GST_NICE_SRC (src);
249 GST_OBJECT_LOCK (src);
250 nicesrc->unlocked = FALSE;
251 if (nicesrc->idle_source) {
252 g_source_destroy (nicesrc->idle_source);
253 g_source_unref(nicesrc->idle_source);
255 nicesrc->idle_source = NULL;
256 GST_OBJECT_UNLOCK (src);
258 return TRUE;
261 static GstFlowReturn
262 gst_nice_src_create (
263 GstPushSrc *basesrc,
264 GstBuffer **buffer)
266 GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc);
268 GST_LOG_OBJECT (nicesrc, "create called");
270 GST_OBJECT_LOCK (basesrc);
271 if (nicesrc->unlocked) {
272 GST_OBJECT_UNLOCK (basesrc);
273 return GST_FLOW_FLUSHING;
275 GST_OBJECT_UNLOCK (basesrc);
277 if (g_queue_is_empty (nicesrc->outbufs))
278 g_main_loop_run (nicesrc->mainloop);
280 *buffer = g_queue_pop_head (nicesrc->outbufs);
281 if (*buffer != NULL) {
282 GST_LOG_OBJECT (nicesrc, "Got buffer, pushing");
283 return GST_FLOW_OK;
284 } else {
285 GST_LOG_OBJECT (nicesrc, "Got interrupting, returning wrong-state");
286 return GST_FLOW_FLUSHING;
291 static void
292 gst_nice_src_dispose (GObject *object)
294 GstNiceSrc *src = GST_NICE_SRC (object);
296 if (src->agent)
297 g_object_unref (src->agent);
298 src->agent = NULL;
300 if (src->mainloop)
301 g_main_loop_unref (src->mainloop);
302 src->mainloop = NULL;
304 if (src->mainctx)
305 g_main_context_unref (src->mainctx);
306 src->mainctx = NULL;
308 if (src->outbufs)
309 g_queue_free (src->outbufs);
310 src->outbufs = NULL;
312 G_OBJECT_CLASS (gst_nice_src_parent_class)->dispose (object);
315 static void
316 gst_nice_src_set_property (
317 GObject *object,
318 guint prop_id,
319 const GValue *value,
320 GParamSpec *pspec)
322 GstNiceSrc *src = GST_NICE_SRC (object);
324 switch (prop_id)
326 case PROP_AGENT:
327 if (src->agent)
328 GST_ERROR_OBJECT (object,
329 "Changing the agent on a nice src not allowed");
330 else
331 src->agent = g_value_dup_object (value);
332 break;
334 case PROP_STREAM:
335 src->stream_id = g_value_get_uint (value);
336 break;
338 case PROP_COMPONENT:
339 src->component_id = g_value_get_uint (value);
340 break;
342 default:
343 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
344 break;
348 static void
349 gst_nice_src_get_property (
350 GObject *object,
351 guint prop_id,
352 GValue *value,
353 GParamSpec *pspec)
355 GstNiceSrc *src = GST_NICE_SRC (object);
357 switch (prop_id)
359 case PROP_AGENT:
360 g_value_set_object (value, src->agent);
361 break;
363 case PROP_STREAM:
364 g_value_set_uint (value, src->stream_id);
365 break;
367 case PROP_COMPONENT:
368 g_value_set_uint (value, src->component_id);
369 break;
371 default:
372 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
373 break;
377 static GstStateChangeReturn
378 gst_nice_src_change_state (GstElement * element, GstStateChange transition)
380 GstNiceSrc *src;
381 GstStateChangeReturn ret;
383 src = GST_NICE_SRC (element);
385 switch (transition) {
386 case GST_STATE_CHANGE_NULL_TO_READY:
387 if (src->agent == NULL || src->stream_id == 0 || src->component_id == 0)
389 GST_ERROR_OBJECT (element,
390 "Trying to start Nice source without an agent set");
391 return GST_STATE_CHANGE_FAILURE;
393 else
395 nice_agent_attach_recv (src->agent, src->stream_id, src->component_id,
396 src->mainctx, gst_nice_src_read_callback, (gpointer) src);
398 break;
399 case GST_STATE_CHANGE_READY_TO_NULL:
400 nice_agent_attach_recv (src->agent, src->stream_id, src->component_id,
401 src->mainctx, NULL, NULL);
402 break;
403 default:
404 break;
407 ret = GST_ELEMENT_CLASS (gst_nice_src_parent_class)->change_state (element,
408 transition);
410 return ret;