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
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.
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.
43 #include "gstnicesrc.h"
45 GST_DEBUG_CATEGORY_STATIC (nicesrc_debug
);
46 #define GST_CAT_DEFAULT nicesrc_debug
49 #define BUFFER_SIZE (65536)
61 gst_nice_src_unlock_stop (
65 gst_nice_src_set_property (
72 gst_nice_src_get_property (
80 gst_nice_src_dispose (GObject
*object
);
82 static GstStateChangeReturn
83 gst_nice_src_change_state (
85 GstStateChange transition
);
87 static GstStaticPadTemplate gst_nice_src_src_template
=
88 GST_STATIC_PAD_TEMPLATE (
94 G_DEFINE_TYPE (GstNiceSrc
, gst_nice_src
, GST_TYPE_PUSH_SRC
);
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 #if GST_CHECK_VERSION (1,0,0)
133 gst_element_class_set_metadata (gstelement_class
,
135 gst_element_class_set_details_simple (gstelement_class
,
139 "Interactive UDP connectivity establishment",
140 "Dafydd Harries <dafydd.harries@collabora.co.uk>");
142 g_object_class_install_property (gobject_class
, PROP_AGENT
,
143 g_param_spec_object (
146 "The NiceAgent this source is bound to",
150 g_object_class_install_property (gobject_class
, PROP_STREAM
,
154 "The ID of the stream to read from",
160 g_object_class_install_property (gobject_class
, PROP_COMPONENT
,
164 "The ID of the component to read from",
172 gst_nice_src_init (GstNiceSrc
*src
)
174 gst_base_src_set_live (GST_BASE_SRC (src
), TRUE
);
175 gst_base_src_set_format (GST_BASE_SRC (src
), GST_FORMAT_TIME
);
176 gst_base_src_set_do_timestamp (GST_BASE_SRC (src
), TRUE
);
179 src
->component_id
= 0;
180 src
->mainctx
= g_main_context_new ();
181 src
->mainloop
= g_main_loop_new (src
->mainctx
, FALSE
);
182 src
->unlocked
= FALSE
;
183 src
->idle_source
= NULL
;
184 src
->outbufs
= g_queue_new ();
188 gst_nice_src_read_callback (NiceAgent
*agent
,
195 GstBaseSrc
*basesrc
= GST_BASE_SRC (data
);
196 GstNiceSrc
*nicesrc
= GST_NICE_SRC (basesrc
);
197 GstBuffer
*buffer
= NULL
;
199 GST_LOG_OBJECT (agent
, "Got buffer, getting out of the main loop");
201 #if GST_CHECK_VERSION (1,0,0)
202 buffer
= gst_buffer_new_allocate (NULL
, len
, NULL
);
203 gst_buffer_fill (buffer
, 0, buf
, len
);
205 buffer
= gst_buffer_new_and_alloc (len
);
206 memcpy (GST_BUFFER_DATA (buffer
), buf
, len
);
208 g_queue_push_tail (nicesrc
->outbufs
, buffer
);
210 g_main_loop_quit (nicesrc
->mainloop
);
214 gst_nice_src_unlock_idler (gpointer data
)
216 GstNiceSrc
*nicesrc
= GST_NICE_SRC (data
);
218 GST_OBJECT_LOCK (nicesrc
);
219 if (nicesrc
->unlocked
)
220 g_main_loop_quit (nicesrc
->mainloop
);
222 if (nicesrc
->idle_source
) {
223 g_source_destroy (nicesrc
->idle_source
);
224 g_source_unref (nicesrc
->idle_source
);
225 nicesrc
->idle_source
= NULL
;
227 GST_OBJECT_UNLOCK (nicesrc
);
233 gst_nice_src_unlock (GstBaseSrc
*src
)
235 GstNiceSrc
*nicesrc
= GST_NICE_SRC (src
);
237 GST_OBJECT_LOCK (src
);
238 nicesrc
->unlocked
= TRUE
;
240 g_main_loop_quit (nicesrc
->mainloop
);
242 if (!nicesrc
->idle_source
) {
243 nicesrc
->idle_source
= g_idle_source_new ();
244 g_source_set_priority (nicesrc
->idle_source
, G_PRIORITY_HIGH
);
245 g_source_set_callback (nicesrc
->idle_source
, gst_nice_src_unlock_idler
, src
, NULL
);
246 g_source_attach (nicesrc
->idle_source
, g_main_loop_get_context (nicesrc
->mainloop
));
248 GST_OBJECT_UNLOCK (src
);
254 gst_nice_src_unlock_stop (GstBaseSrc
*src
)
256 GstNiceSrc
*nicesrc
= GST_NICE_SRC (src
);
258 GST_OBJECT_LOCK (src
);
259 nicesrc
->unlocked
= FALSE
;
260 if (nicesrc
->idle_source
) {
261 g_source_destroy (nicesrc
->idle_source
);
262 g_source_unref(nicesrc
->idle_source
);
264 nicesrc
->idle_source
= NULL
;
265 GST_OBJECT_UNLOCK (src
);
271 gst_nice_src_create (
275 GstNiceSrc
*nicesrc
= GST_NICE_SRC (basesrc
);
277 GST_LOG_OBJECT (nicesrc
, "create called");
279 GST_OBJECT_LOCK (basesrc
);
280 if (nicesrc
->unlocked
) {
281 GST_OBJECT_UNLOCK (basesrc
);
282 #if GST_CHECK_VERSION (1,0,0)
283 return GST_FLOW_FLUSHING
;
285 return GST_FLOW_WRONG_STATE
;
288 GST_OBJECT_UNLOCK (basesrc
);
290 if (g_queue_is_empty (nicesrc
->outbufs
))
291 g_main_loop_run (nicesrc
->mainloop
);
293 *buffer
= g_queue_pop_head (nicesrc
->outbufs
);
294 if (*buffer
!= NULL
) {
295 GST_LOG_OBJECT (nicesrc
, "Got buffer, pushing");
298 GST_LOG_OBJECT (nicesrc
, "Got interrupting, returning wrong-state");
299 #if GST_CHECK_VERSION (1,0,0)
300 return GST_FLOW_FLUSHING
;
302 return GST_FLOW_WRONG_STATE
;
309 gst_nice_src_dispose (GObject
*object
)
311 GstNiceSrc
*src
= GST_NICE_SRC (object
);
314 g_object_unref (src
->agent
);
318 g_main_loop_unref (src
->mainloop
);
319 src
->mainloop
= NULL
;
322 g_main_context_unref (src
->mainctx
);
326 g_queue_free (src
->outbufs
);
329 G_OBJECT_CLASS (gst_nice_src_parent_class
)->dispose (object
);
333 gst_nice_src_set_property (
339 GstNiceSrc
*src
= GST_NICE_SRC (object
);
345 GST_ERROR_OBJECT (object
,
346 "Changing the agent on a nice src not allowed");
348 src
->agent
= g_value_dup_object (value
);
352 src
->stream_id
= g_value_get_uint (value
);
356 src
->component_id
= g_value_get_uint (value
);
360 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
366 gst_nice_src_get_property (
372 GstNiceSrc
*src
= GST_NICE_SRC (object
);
377 g_value_set_object (value
, src
->agent
);
381 g_value_set_uint (value
, src
->stream_id
);
385 g_value_set_uint (value
, src
->component_id
);
389 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
394 static GstStateChangeReturn
395 gst_nice_src_change_state (GstElement
* element
, GstStateChange transition
)
398 GstStateChangeReturn ret
;
400 src
= GST_NICE_SRC (element
);
402 switch (transition
) {
403 case GST_STATE_CHANGE_NULL_TO_READY
:
404 if (src
->agent
== NULL
|| src
->stream_id
== 0 || src
->component_id
== 0)
406 GST_ERROR_OBJECT (element
,
407 "Trying to start Nice source without an agent set");
408 return GST_STATE_CHANGE_FAILURE
;
412 nice_agent_attach_recv (src
->agent
, src
->stream_id
, src
->component_id
,
413 src
->mainctx
, gst_nice_src_read_callback
, (gpointer
) src
);
416 case GST_STATE_CHANGE_READY_TO_NULL
:
417 nice_agent_attach_recv (src
->agent
, src
->stream_id
, src
->component_id
,
418 src
->mainctx
, NULL
, NULL
);
424 ret
= GST_ELEMENT_CLASS (gst_nice_src_parent_class
)->change_state (element
,