71 * |
71 * |
72 * Note that clock slection and distribution is normally handled by the |
72 * Note that clock slection and distribution is normally handled by the |
73 * toplevel #GstPipeline so the clock functions are only to be used in very |
73 * toplevel #GstPipeline so the clock functions are only to be used in very |
74 * specific situations. |
74 * specific situations. |
75 * |
75 * |
76 * Last reviewed on 2006-03-12 (0.10.5) |
76 * Last reviewed on 2009-05-29 (0.10.24) |
77 */ |
77 */ |
78 |
78 |
79 #include "gst_private.h" |
79 #include "gst_private.h" |
80 #include <glib.h> |
80 #include <glib.h> |
81 #include <stdarg.h> |
81 #include <stdarg.h> |
146 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self); |
147 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self); |
147 #endif |
148 #endif |
148 |
149 |
149 static GstObjectClass *parent_class = NULL; |
150 static GstObjectClass *parent_class = NULL; |
150 static guint gst_element_signals[LAST_SIGNAL] = { 0 }; |
151 static guint gst_element_signals[LAST_SIGNAL] = { 0 }; |
|
152 |
|
153 /* this is used in gstelementfactory.c:gst_element_register() */ |
|
154 GQuark _gst_elementclass_factory = 0; |
151 #ifdef __SYMBIAN32__ |
155 #ifdef __SYMBIAN32__ |
152 EXPORT_C |
156 EXPORT_C |
153 #endif |
157 #endif |
154 |
158 |
155 |
159 |
156 GType |
160 GType |
157 gst_element_get_type (void) |
161 gst_element_get_type (void) |
158 { |
162 { |
159 static GType gst_element_type = 0; |
163 static volatile gsize gst_element_type = 0; |
160 |
164 |
161 if (G_UNLIKELY (gst_element_type == 0)) { |
165 if (g_once_init_enter (&gst_element_type)) { |
|
166 GType _type; |
162 static const GTypeInfo element_info = { |
167 static const GTypeInfo element_info = { |
163 sizeof (GstElementClass), |
168 sizeof (GstElementClass), |
164 gst_element_base_class_init, |
169 gst_element_base_class_init, |
165 gst_element_base_class_finalize, |
170 gst_element_base_class_finalize, |
166 (GClassInitFunc) gst_element_class_init, |
171 (GClassInitFunc) gst_element_class_init, |
170 0, |
175 0, |
171 (GInstanceInitFunc) gst_element_init, |
176 (GInstanceInitFunc) gst_element_init, |
172 NULL |
177 NULL |
173 }; |
178 }; |
174 |
179 |
175 gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement", |
180 _type = g_type_register_static (GST_TYPE_OBJECT, "GstElement", |
176 &element_info, G_TYPE_FLAG_ABSTRACT); |
181 &element_info, G_TYPE_FLAG_ABSTRACT); |
|
182 |
|
183 _gst_elementclass_factory = |
|
184 g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY"); |
|
185 g_once_init_leave (&gst_element_type, _type); |
177 } |
186 } |
178 return gst_element_type; |
187 return gst_element_type; |
179 } |
188 } |
180 |
189 |
181 static void |
190 static void |
256 * of doing things. |
265 * of doing things. |
257 * See http://bugzilla.gnome.org/show_bug.cgi?id=491501 |
266 * See http://bugzilla.gnome.org/show_bug.cgi?id=491501 |
258 */ |
267 */ |
259 memset (&element_class->details, 0, sizeof (GstElementDetails)); |
268 memset (&element_class->details, 0, sizeof (GstElementDetails)); |
260 element_class->padtemplates = NULL; |
269 element_class->padtemplates = NULL; |
|
270 |
|
271 /* set the factory, see gst_element_register() */ |
|
272 element_class->elementfactory = |
|
273 g_type_get_qdata (G_TYPE_FROM_CLASS (element_class), |
|
274 _gst_elementclass_factory); |
|
275 GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class), |
|
276 element_class->elementfactory); |
261 } |
277 } |
262 |
278 |
263 static void |
279 static void |
264 gst_element_base_class_finalize (gpointer g_class) |
280 gst_element_base_class_finalize (gpointer g_class) |
265 { |
281 { |
320 * @element: a #GstElement to release the request pad of. |
336 * @element: a #GstElement to release the request pad of. |
321 * @pad: the #GstPad to release. |
337 * @pad: the #GstPad to release. |
322 * |
338 * |
323 * Makes the element free the previously requested pad as obtained |
339 * Makes the element free the previously requested pad as obtained |
324 * with gst_element_get_request_pad(). |
340 * with gst_element_get_request_pad(). |
|
341 * |
|
342 * This does not unref the pad. If the pad was created by using |
|
343 * gst_element_get_request_pad(), gst_element_release_request_pad() needs to be |
|
344 * followed by gst_object_unref() to free the @pad. |
325 * |
345 * |
326 * MT safe. |
346 * MT safe. |
327 */ |
347 */ |
328 #ifdef __SYMBIAN32__ |
348 #ifdef __SYMBIAN32__ |
329 EXPORT_C |
349 EXPORT_C |
546 * @element: a #GstElement. |
566 * @element: a #GstElement. |
547 * |
567 * |
548 * Returns the base time of the element. The base time is the |
568 * Returns the base time of the element. The base time is the |
549 * absolute time of the clock when this element was last put to |
569 * absolute time of the clock when this element was last put to |
550 * PLAYING. Subtracting the base time from the clock time gives |
570 * PLAYING. Subtracting the base time from the clock time gives |
551 * the stream time of the element. |
571 * the running time of the element. |
552 * |
572 * |
553 * Returns: the base time of the element. |
573 * Returns: the base time of the element. |
554 * |
574 * |
555 * MT safe. |
575 * MT safe. |
556 */ |
576 */ |
570 GST_OBJECT_UNLOCK (element); |
590 GST_OBJECT_UNLOCK (element); |
571 |
591 |
572 return result; |
592 return result; |
573 } |
593 } |
574 |
594 |
575 #ifndef GST_DISABLE_INDEX |
595 /** |
|
596 * gst_element_set_start_time: |
|
597 * @element: a #GstElement. |
|
598 * @time: the base time to set. |
|
599 * |
|
600 * Set the start time of an element. The start time of the element is the |
|
601 * running time of the element when it last went to the PAUSED state. In READY |
|
602 * or after a flushing seek, it is set to 0. |
|
603 * |
|
604 * Toplevel elements like #GstPipeline will manage the start_time and |
|
605 * base_time on its children. Setting the start_time to #GST_CLOCK_TIME_NONE |
|
606 * on such a toplevel element will disable the distribution of the base_time to |
|
607 * the children and can be useful if the application manages the base_time |
|
608 * itself, for example if you want to synchronize capture from multiple |
|
609 * pipelines, and you can also ensure that the pipelines have the same clock. |
|
610 * |
|
611 * MT safe. |
|
612 * |
|
613 * Since: 0.10.24 |
|
614 */ |
|
615 #ifdef __SYMBIAN32__ |
|
616 EXPORT_C |
|
617 #endif |
|
618 |
|
619 void |
|
620 gst_element_set_start_time (GstElement * element, GstClockTime time) |
|
621 { |
|
622 GstClockTime old; |
|
623 |
|
624 g_return_if_fail (GST_IS_ELEMENT (element)); |
|
625 |
|
626 GST_OBJECT_LOCK (element); |
|
627 old = GST_ELEMENT_START_TIME (element); |
|
628 GST_ELEMENT_START_TIME (element) = time; |
|
629 GST_OBJECT_UNLOCK (element); |
|
630 |
|
631 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, |
|
632 "set start_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT, |
|
633 GST_TIME_ARGS (time), GST_TIME_ARGS (old)); |
|
634 } |
|
635 |
|
636 /** |
|
637 * gst_element_get_start_time: |
|
638 * @element: a #GstElement. |
|
639 * |
|
640 * Returns the start time of the element. The start time is the |
|
641 * running time of the clock when this element was last put to PAUSED. |
|
642 * |
|
643 * Usually the start_time is managed by a toplevel element such as |
|
644 * #GstPipeline. |
|
645 * |
|
646 * MT safe. |
|
647 * |
|
648 * Returns: the start time of the element. |
|
649 * |
|
650 * Since: 0.10.24 |
|
651 */ |
|
652 #ifdef __SYMBIAN32__ |
|
653 EXPORT_C |
|
654 #endif |
|
655 |
|
656 GstClockTime |
|
657 gst_element_get_start_time (GstElement * element) |
|
658 { |
|
659 GstClockTime result; |
|
660 |
|
661 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE); |
|
662 |
|
663 GST_OBJECT_LOCK (element); |
|
664 result = GST_ELEMENT_START_TIME (element); |
|
665 GST_OBJECT_UNLOCK (element); |
|
666 |
|
667 return result; |
|
668 } |
|
669 |
576 /** |
670 /** |
577 * gst_element_is_indexable: |
671 * gst_element_is_indexable: |
578 * @element: a #GstElement. |
672 * @element: a #GstElement. |
579 * |
673 * |
580 * Queries if the element can be indexed. |
674 * Queries if the element can be indexed. |
655 if (oclass->get_index) |
749 if (oclass->get_index) |
656 result = oclass->get_index (element); |
750 result = oclass->get_index (element); |
657 |
751 |
658 return result; |
752 return result; |
659 } |
753 } |
660 #endif |
|
661 |
754 |
662 /** |
755 /** |
663 * gst_element_add_pad: |
756 * gst_element_add_pad: |
664 * @element: a #GstElement to add the pad to. |
757 * @element: a #GstElement to add the pad to. |
665 * @pad: the #GstPad to add to the element. |
758 * @pad: the #GstPad to add to the element. |
1081 * @name: the name of the pad to retrieve. |
1174 * @name: the name of the pad to retrieve. |
1082 * |
1175 * |
1083 * Retrieves a pad from @element by name. Tries gst_element_get_static_pad() |
1176 * Retrieves a pad from @element by name. Tries gst_element_get_static_pad() |
1084 * first, then gst_element_get_request_pad(). |
1177 * first, then gst_element_get_request_pad(). |
1085 * |
1178 * |
1086 * <note>Usage of this function is not recommended as it is unclear if the reference |
1179 * Deprecated: This function is deprecated as it's unclear if the reference |
1087 * to the result pad should be released with gst_object_unref() in case of a static pad |
1180 * to the result pad should be released with gst_object_unref() in case of a static pad |
1088 * or gst_element_release_request_pad() in case of a request pad.</note> |
1181 * or gst_element_release_request_pad() in case of a request pad. |
|
1182 * Use gst_element_get_static_pad() or gst_element_get_request_pad() instead. |
1089 * |
1183 * |
1090 * Returns: the #GstPad if found, otherwise %NULL. Unref or Release after usage, |
1184 * Returns: the #GstPad if found, otherwise %NULL. Unref or Release after usage, |
1091 * depending on the type of the pad. |
1185 * depending on the type of the pad. |
1092 */ |
1186 */ |
1093 #ifdef __SYMBIAN32__ |
1187 #ifndef GST_REMOVE_DEPRECATED |
1094 EXPORT_C |
1188 #ifdef __SYMBIAN32__ |
1095 #endif |
1189 EXPORT_C |
1096 |
1190 #endif |
1097 GstPad * |
1191 GstPad * |
1098 gst_element_get_pad (GstElement * element, const gchar * name) |
1192 gst_element_get_pad (GstElement * element, const gchar * name) |
1099 { |
1193 { |
1100 GstPad *pad; |
1194 GstPad *pad; |
1101 |
1195 |
1106 if (!pad) |
1200 if (!pad) |
1107 pad = gst_element_get_request_pad (element, name); |
1201 pad = gst_element_get_request_pad (element, name); |
1108 |
1202 |
1109 return pad; |
1203 return pad; |
1110 } |
1204 } |
|
1205 #endif /* GST_REMOVE_DEPRECATED */ |
1111 |
1206 |
1112 static GstIteratorItem |
1207 static GstIteratorItem |
1113 iterate_pad (GstIterator * it, GstPad * pad) |
1208 iterate_pad (GstIterator * it, GstPad * pad) |
1114 { |
1209 { |
1115 gst_object_ref (pad); |
1210 gst_object_ref (pad); |
1791 gchar *sent_debug; |
1886 gchar *sent_debug; |
1792 gboolean has_debug = TRUE; |
1887 gboolean has_debug = TRUE; |
1793 GstMessage *message = NULL; |
1888 GstMessage *message = NULL; |
1794 |
1889 |
1795 /* checks */ |
1890 /* checks */ |
1796 GST_DEBUG_OBJECT (element, "start"); |
1891 GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element, "start"); |
1797 g_return_if_fail (GST_IS_ELEMENT (element)); |
1892 g_return_if_fail (GST_IS_ELEMENT (element)); |
1798 g_return_if_fail ((type == GST_MESSAGE_ERROR) || |
1893 g_return_if_fail ((type == GST_MESSAGE_ERROR) || |
1799 (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO)); |
1894 (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO)); |
1800 |
1895 |
1801 /* check if we send the given text or the default error text */ |
1896 /* check if we send the given text or the default error text */ |
2052 g_time_val_add (&abstimeout, add); |
2148 g_time_val_add (&abstimeout, add); |
2053 timeval = &abstimeout; |
2149 timeval = &abstimeout; |
2054 } else { |
2150 } else { |
2055 timeval = NULL; |
2151 timeval = NULL; |
2056 } |
2152 } |
2057 /* get cookie to dected state change during waiting */ |
2153 /* get cookie to detect state changes during waiting */ |
2058 cookie = element->state_cookie; |
2154 cookie = element->state_cookie; |
2059 |
2155 |
2060 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, |
2156 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, |
2061 "waiting for element to commit state"); |
2157 "waiting for element to commit state"); |
2062 |
2158 |
2290 /* mark busy */ |
2386 /* mark busy */ |
2291 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; |
2387 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; |
2292 GST_OBJECT_UNLOCK (element); |
2388 GST_OBJECT_UNLOCK (element); |
2293 |
2389 |
2294 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, |
2390 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, |
2295 "committing state from %s to %s, pending %s", |
2391 "committing state from %s to %s, pending %s, next %s", |
2296 gst_element_state_get_name (old_state), |
2392 gst_element_state_get_name (old_state), |
2297 gst_element_state_get_name (old_next), |
2393 gst_element_state_get_name (old_next), |
2298 gst_element_state_get_name (pending)); |
2394 gst_element_state_get_name (pending), gst_element_state_get_name (next)); |
2299 |
2395 |
2300 message = gst_message_new_state_changed (GST_OBJECT_CAST (element), |
2396 message = gst_message_new_state_changed (GST_OBJECT_CAST (element), |
2301 old_state, old_next, pending); |
2397 old_state, old_next, pending); |
2302 gst_element_post_message (element, message); |
2398 gst_element_post_message (element, message); |
2303 |
2399 |
2347 return ret; |
2443 return ret; |
2348 } |
2444 } |
2349 } |
2445 } |
2350 |
2446 |
2351 /** |
2447 /** |
2352 * gst_element_lost_state: |
2448 * gst_element_lost_state_full: |
2353 * @element: a #GstElement the state is lost of |
2449 * @element: a #GstElement the state is lost of |
|
2450 * @new_base_time: if a new base time should be distributed |
2354 * |
2451 * |
2355 * Brings the element to the lost state. The current state of the |
2452 * Brings the element to the lost state. The current state of the |
2356 * element is copied to the pending state so that any call to |
2453 * element is copied to the pending state so that any call to |
2357 * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC. |
2454 * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC. |
2358 * |
2455 * |
2359 * An ASYNC_START message is posted with an indication to distribute a new |
2456 * An ASYNC_START message is posted with indication to distribute a new |
2360 * base_time to the element. |
2457 * base_time to the element when @new_base_time is %TRUE. |
2361 * If the element was PLAYING, it will go to PAUSED. The element |
2458 * If the element was PLAYING, it will go to PAUSED. The element |
2362 * will be restored to its PLAYING state by the parent pipeline when it |
2459 * will be restored to its PLAYING state by the parent pipeline when it |
2363 * prerolls again. |
2460 * prerolls again. |
2364 * |
2461 * |
2365 * This is mostly used for elements that lost their preroll buffer |
2462 * This is mostly used for elements that lost their preroll buffer |
2370 * |
2467 * |
2371 * This function is used internally and should normally not be called from |
2468 * This function is used internally and should normally not be called from |
2372 * plugins or applications. |
2469 * plugins or applications. |
2373 * |
2470 * |
2374 * MT safe. |
2471 * MT safe. |
|
2472 * |
|
2473 * Since: 0.10.24 |
2375 */ |
2474 */ |
2376 #ifdef __SYMBIAN32__ |
2475 #ifdef __SYMBIAN32__ |
2377 EXPORT_C |
2476 EXPORT_C |
2378 #endif |
2477 #endif |
2379 |
2478 |
2380 void |
2479 void |
2381 gst_element_lost_state (GstElement * element) |
2480 gst_element_lost_state_full (GstElement * element, gboolean new_base_time) |
2382 { |
2481 { |
2383 GstState old_state, new_state; |
2482 GstState old_state, new_state; |
2384 GstMessage *message; |
2483 GstMessage *message; |
2385 |
2484 |
2386 g_return_if_fail (GST_IS_ELEMENT (element)); |
2485 g_return_if_fail (GST_IS_ELEMENT (element)); |
2387 |
2486 |
2388 GST_OBJECT_LOCK (element); |
2487 GST_OBJECT_LOCK (element); |
2389 if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING || |
2488 if (GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE) |
2390 GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE) |
|
2391 goto nothing_lost; |
2489 goto nothing_lost; |
|
2490 |
|
2491 if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING) |
|
2492 goto only_async_start; |
2392 |
2493 |
2393 old_state = GST_STATE (element); |
2494 old_state = GST_STATE (element); |
2394 |
2495 |
2395 /* when we were PLAYING, the new state is PAUSED. We will also not |
2496 /* when we were PLAYING, the new state is PAUSED. We will also not |
2396 * automatically go to PLAYING but let the parent bin(s) set us to PLAYING |
2497 * automatically go to PLAYING but let the parent bin(s) set us to PLAYING |
2406 |
2507 |
2407 GST_STATE (element) = new_state; |
2508 GST_STATE (element) = new_state; |
2408 GST_STATE_NEXT (element) = new_state; |
2509 GST_STATE_NEXT (element) = new_state; |
2409 GST_STATE_PENDING (element) = new_state; |
2510 GST_STATE_PENDING (element) = new_state; |
2410 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; |
2511 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC; |
|
2512 if (new_base_time) |
|
2513 GST_ELEMENT_START_TIME (element) = 0; |
2411 GST_OBJECT_UNLOCK (element); |
2514 GST_OBJECT_UNLOCK (element); |
2412 |
2515 |
2413 message = gst_message_new_state_changed (GST_OBJECT_CAST (element), |
2516 message = gst_message_new_state_changed (GST_OBJECT_CAST (element), |
2414 new_state, new_state, new_state); |
2517 new_state, new_state, new_state); |
2415 gst_element_post_message (element, message); |
2518 gst_element_post_message (element, message); |
2416 |
2519 |
2417 message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE); |
2520 message = |
|
2521 gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time); |
2418 gst_element_post_message (element, message); |
2522 gst_element_post_message (element, message); |
2419 |
2523 |
2420 return; |
2524 return; |
2421 |
2525 |
2422 nothing_lost: |
2526 nothing_lost: |
2423 { |
2527 { |
2424 GST_OBJECT_UNLOCK (element); |
2528 GST_OBJECT_UNLOCK (element); |
2425 return; |
2529 return; |
2426 } |
2530 } |
|
2531 only_async_start: |
|
2532 { |
|
2533 GST_OBJECT_UNLOCK (element); |
|
2534 |
|
2535 message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE); |
|
2536 gst_element_post_message (element, message); |
|
2537 return; |
|
2538 } |
|
2539 } |
|
2540 |
|
2541 /** |
|
2542 * gst_element_lost_state: |
|
2543 * @element: a #GstElement the state is lost of |
|
2544 * |
|
2545 * Brings the element to the lost state. This function calls |
|
2546 * gst_element_lost_state_full() with the new_base_time set to %TRUE. |
|
2547 * |
|
2548 * This function is used internally and should normally not be called from |
|
2549 * plugins or applications. |
|
2550 * |
|
2551 * MT safe. |
|
2552 */ |
|
2553 #ifdef __SYMBIAN32__ |
|
2554 EXPORT_C |
|
2555 #endif |
|
2556 |
|
2557 void |
|
2558 gst_element_lost_state (GstElement * element) |
|
2559 { |
|
2560 gst_element_lost_state_full (element, TRUE); |
2427 } |
2561 } |
2428 |
2562 |
2429 /** |
2563 /** |
2430 * gst_element_set_state: |
2564 * gst_element_set_state: |
2431 * @element: a #GstElement to change state of. |
2565 * @element: a #GstElement to change state of. |
2438 * This function can return #GST_STATE_CHANGE_ASYNC, in which case the |
2572 * This function can return #GST_STATE_CHANGE_ASYNC, in which case the |
2439 * element will perform the remainder of the state change asynchronously in |
2573 * element will perform the remainder of the state change asynchronously in |
2440 * another thread. |
2574 * another thread. |
2441 * An application can use gst_element_get_state() to wait for the completion |
2575 * An application can use gst_element_get_state() to wait for the completion |
2442 * of the state change or it can wait for a state change message on the bus. |
2576 * of the state change or it can wait for a state change message on the bus. |
|
2577 * |
|
2578 * State changes to %GST_STATE_READY or %GST_STATE_NULL never return |
|
2579 * #GST_STATE_CHANGE_ASYNC. |
2443 * |
2580 * |
2444 * Returns: Result of the state change using #GstStateChangeReturn. |
2581 * Returns: Result of the state change using #GstStateChangeReturn. |
2445 * |
2582 * |
2446 * MT safe. |
2583 * MT safe. |
2447 */ |
2584 */ |
2502 old_pending = GST_STATE_PENDING (element); |
2639 old_pending = GST_STATE_PENDING (element); |
2503 |
2640 |
2504 /* this is the (new) state we should go to. TARGET is the last state we set on |
2641 /* this is the (new) state we should go to. TARGET is the last state we set on |
2505 * the element. */ |
2642 * the element. */ |
2506 if (state != GST_STATE_TARGET (element)) { |
2643 if (state != GST_STATE_TARGET (element)) { |
|
2644 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, |
|
2645 "setting target state to %s", gst_element_state_get_name (state)); |
2507 GST_STATE_TARGET (element) = state; |
2646 GST_STATE_TARGET (element) = state; |
2508 /* increment state cookie so that we can track each state change. We only do |
2647 /* increment state cookie so that we can track each state change. We only do |
2509 * this if this is actually a new state change. */ |
2648 * this if this is actually a new state change. */ |
2510 element->state_cookie++; |
2649 element->state_cookie++; |
2511 } |
2650 } |
2598 GstStateChangeReturn |
2737 GstStateChangeReturn |
2599 gst_element_change_state (GstElement * element, GstStateChange transition) |
2738 gst_element_change_state (GstElement * element, GstStateChange transition) |
2600 { |
2739 { |
2601 GstElementClass *oclass; |
2740 GstElementClass *oclass; |
2602 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; |
2741 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; |
2603 GstState current; |
|
2604 GstState next; |
|
2605 |
2742 |
2606 oclass = GST_ELEMENT_GET_CLASS (element); |
2743 oclass = GST_ELEMENT_GET_CLASS (element); |
2607 |
|
2608 /* start with the current state. */ |
|
2609 current = (GstState) GST_STATE_TRANSITION_CURRENT (transition); |
|
2610 next = GST_STATE_TRANSITION_NEXT (transition); |
|
2611 |
2744 |
2612 /* call the state change function so it can set the state */ |
2745 /* call the state change function so it can set the state */ |
2613 if (oclass->change_state) |
2746 if (oclass->change_state) |
2614 ret = (oclass->change_state) (element, transition); |
2747 ret = (oclass->change_state) (element, transition); |
2615 else |
2748 else |
2795 return TRUE; |
2928 return TRUE; |
2796 |
2929 |
2797 /* ERRORS */ |
2930 /* ERRORS */ |
2798 src_failed: |
2931 src_failed: |
2799 { |
2932 { |
2800 GST_DEBUG_OBJECT (element, "source pads_activate failed"); |
2933 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, |
|
2934 "source pads_activate failed"); |
2801 return FALSE; |
2935 return FALSE; |
2802 } |
2936 } |
2803 sink_failed: |
2937 sink_failed: |
2804 { |
2938 { |
2805 GST_DEBUG_OBJECT (element, "sink pads_activate failed"); |
2939 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, |
|
2940 "sink pads_activate failed"); |
2806 return FALSE; |
2941 return FALSE; |
2807 } |
2942 } |
2808 caps_failed: |
2943 caps_failed: |
2809 { |
2944 { |
2810 GST_DEBUG_OBJECT (element, "failed to clear caps on pads"); |
2945 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element, |
|
2946 "failed to clear caps on pads"); |
2811 return FALSE; |
2947 return FALSE; |
2812 } |
2948 } |
2813 } |
2949 } |
2814 |
2950 |
2815 /* is called with STATE_LOCK */ |
2951 /* is called with STATE_LOCK */ |
2816 static GstStateChangeReturn |
2952 static GstStateChangeReturn |
2817 gst_element_change_state_func (GstElement * element, GstStateChange transition) |
2953 gst_element_change_state_func (GstElement * element, GstStateChange transition) |
2818 { |
2954 { |
2819 GstState state, next; |
2955 GstState state, next; |
2820 GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; |
2956 GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; |
|
2957 GstClock **clock_p; |
2821 |
2958 |
2822 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE); |
2959 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE); |
2823 |
2960 |
2824 state = (GstState) GST_STATE_TRANSITION_CURRENT (transition); |
2961 state = (GstState) GST_STATE_TRANSITION_CURRENT (transition); |
2825 next = GST_STATE_TRANSITION_NEXT (transition); |
2962 next = GST_STATE_TRANSITION_NEXT (transition); |
2852 if (!gst_element_pads_activate (element, FALSE)) { |
2989 if (!gst_element_pads_activate (element, FALSE)) { |
2853 result = GST_STATE_CHANGE_FAILURE; |
2990 result = GST_STATE_CHANGE_FAILURE; |
2854 } else { |
2991 } else { |
2855 gst_element_set_base_time (element, 0); |
2992 gst_element_set_base_time (element, 0); |
2856 } |
2993 } |
|
2994 |
|
2995 /* In null state release the reference to the clock */ |
|
2996 GST_OBJECT_LOCK (element); |
|
2997 clock_p = &element->clock; |
|
2998 gst_object_replace ((GstObject **) clock_p, NULL); |
|
2999 GST_OBJECT_UNLOCK (element); |
2857 break; |
3000 break; |
2858 default: |
3001 default: |
2859 /* this will catch real but unhandled state changes; |
3002 /* this will catch real but unhandled state changes; |
2860 * can only be caused by: |
3003 * can only be caused by: |
2861 * - a new state was added |
3004 * - a new state was added |
3029 else if (G_IS_PARAM_SPEC_ENUM (spec)) |
3172 else if (G_IS_PARAM_SPEC_ENUM (spec)) |
3030 contents = g_strdup_printf ("%d", g_value_get_enum (&value)); |
3173 contents = g_strdup_printf ("%d", g_value_get_enum (&value)); |
3031 else if (G_IS_PARAM_SPEC_INT64 (spec)) |
3174 else if (G_IS_PARAM_SPEC_INT64 (spec)) |
3032 contents = g_strdup_printf ("%" G_GINT64_FORMAT, |
3175 contents = g_strdup_printf ("%" G_GINT64_FORMAT, |
3033 g_value_get_int64 (&value)); |
3176 g_value_get_int64 (&value)); |
3034 else |
3177 else if (GST_VALUE_HOLDS_STRUCTURE (&value)) { |
|
3178 if (g_value_get_boxed (&value) != NULL) { |
|
3179 contents = g_strdup_value_contents (&value); |
|
3180 } else { |
|
3181 contents = g_strdup ("NULL"); |
|
3182 } |
|
3183 } else |
3035 contents = g_strdup_value_contents (&value); |
3184 contents = g_strdup_value_contents (&value); |
3036 |
3185 |
3037 xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents); |
3186 xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents); |
3038 g_free (contents); |
3187 g_free (contents); |
3039 |
3188 |
3041 } |
3190 } |
3042 } |
3191 } |
3043 |
3192 |
3044 g_free (specs); |
3193 g_free (specs); |
3045 |
3194 |
3046 pads = GST_ELEMENT_PADS (element); |
3195 pads = g_list_last (GST_ELEMENT_PADS (element)); |
3047 |
3196 |
3048 while (pads) { |
3197 while (pads) { |
3049 GstPad *pad = GST_PAD_CAST (pads->data); |
3198 GstPad *pad = GST_PAD_CAST (pads->data); |
3050 |
3199 |
3051 /* figure out if it's a direct pad or a ghostpad */ |
3200 /* figure out if it's a direct pad or a ghostpad */ |
3052 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) { |
3201 if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) { |
3053 xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL); |
3202 xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL); |
3054 |
3203 |
3055 gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag); |
3204 gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag); |
3056 } |
3205 } |
3057 pads = g_list_next (pads); |
3206 pads = g_list_previous (pads); |
3058 } |
3207 } |
3059 |
3208 |
3060 return parent; |
3209 return parent; |
3061 } |
3210 } |
3062 |
3211 |