source: trunk/third/gstreamer/gst/gstscheduler.c @ 21448

Revision 21448, 26.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21447, which included commits to RCS files with non-trunk default branches.
Line 
1/* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 *                    2000 Wim Taymans <wim.taymans@chello.be>
4 *
5 * gstscheduler.c: Default scheduling code for most cases
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include "gst_private.h"
24
25#include "gstsystemclock.h"
26#include "gstscheduler.h"
27#include "gstinfo.h"
28#include "gstregistrypool.h"
29
30static void gst_scheduler_class_init (GstSchedulerClass * klass);
31static void gst_scheduler_init (GstScheduler * sched);
32static void gst_scheduler_dispose (GObject * object);
33
34static GstObjectClass *parent_class = NULL;
35
36static gchar *_default_name = NULL;
37
38GType
39gst_scheduler_get_type (void)
40{
41  static GType _gst_scheduler_type = 0;
42
43  if (!_gst_scheduler_type) {
44    static const GTypeInfo scheduler_info = {
45      sizeof (GstSchedulerClass),
46      NULL,
47      NULL,
48      (GClassInitFunc) gst_scheduler_class_init,
49      NULL,
50      NULL,
51      sizeof (GstScheduler),
52      0,
53      (GInstanceInitFunc) gst_scheduler_init,
54      NULL
55    };
56
57    _gst_scheduler_type =
58        g_type_register_static (GST_TYPE_OBJECT, "GstScheduler",
59        &scheduler_info, G_TYPE_FLAG_ABSTRACT);
60  }
61  return _gst_scheduler_type;
62}
63
64static void
65gst_scheduler_class_init (GstSchedulerClass * klass)
66{
67  GObjectClass *gobject_class;
68
69  gobject_class = (GObjectClass *) klass;
70
71  parent_class = g_type_class_ref (GST_TYPE_OBJECT);
72
73  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_scheduler_dispose);
74}
75
76static void
77gst_scheduler_init (GstScheduler * sched)
78{
79  sched->clock_providers = NULL;
80  sched->clock_receivers = NULL;
81  sched->schedulers = NULL;
82  sched->state = GST_SCHEDULER_STATE_NONE;
83  sched->parent = NULL;
84  sched->parent_sched = NULL;
85  sched->clock = NULL;
86}
87
88static void
89gst_scheduler_dispose (GObject * object)
90{
91  GstScheduler *sched = GST_SCHEDULER (object);
92
93  /* thse lists should all be NULL */
94  GST_DEBUG ("scheduler %p dispose %p %p %p",
95      object,
96      sched->clock_providers, sched->clock_receivers, sched->schedulers);
97
98  gst_object_replace ((GstObject **) & sched->current_clock, NULL);
99  gst_object_replace ((GstObject **) & sched->clock, NULL);
100
101  /* kids are held reference to, so dereference here. */
102  while (sched->schedulers != NULL) {
103    gst_scheduler_remove_scheduler (sched,
104        GST_SCHEDULER (sched->schedulers->data));
105  }
106
107  G_OBJECT_CLASS (parent_class)->dispose (object);
108}
109
110/**
111 * gst_scheduler_setup:
112 * @sched: the scheduler
113 *
114 * Prepare the scheduler.
115 */
116void
117gst_scheduler_setup (GstScheduler * sched)
118{
119  GstSchedulerClass *sclass;
120
121  g_return_if_fail (GST_IS_SCHEDULER (sched));
122
123  sclass = GST_SCHEDULER_GET_CLASS (sched);
124
125  if (sclass->setup)
126    sclass->setup (sched);
127}
128
129/**
130 * gst_scheduler_reset:
131 * @sched: a #GstScheduler to reset.
132 *
133 * Reset the schedulers.
134 */
135void
136gst_scheduler_reset (GstScheduler * sched)
137{
138  GstSchedulerClass *sclass;
139
140  g_return_if_fail (GST_IS_SCHEDULER (sched));
141
142  sclass = GST_SCHEDULER_GET_CLASS (sched);
143
144  if (sclass->reset)
145    sclass->reset (sched);
146}
147
148/**
149 * gst_scheduler_pad_link:
150 * @sched: the scheduler
151 * @srcpad: the srcpad to link
152 * @sinkpad: the sinkpad to link to
153 *
154 * Links the srcpad to the given sinkpad.
155 */
156void
157gst_scheduler_pad_link (GstScheduler * sched, GstPad * srcpad, GstPad * sinkpad)
158{
159  GstSchedulerClass *sclass;
160
161  g_return_if_fail (GST_IS_SCHEDULER (sched));
162  g_return_if_fail (GST_IS_PAD (srcpad));
163  g_return_if_fail (GST_IS_PAD (sinkpad));
164
165  sclass = GST_SCHEDULER_GET_CLASS (sched);
166
167  if (sclass->pad_link)
168    sclass->pad_link (sched, srcpad, sinkpad);
169}
170
171/**
172 * gst_scheduler_pad_unlink:
173 * @sched: the scheduler
174 * @srcpad: the srcpad to unlink
175 * @sinkpad: the sinkpad to unlink from
176 *
177 * Unlinks the srcpad from the given sinkpad.
178 */
179void
180gst_scheduler_pad_unlink (GstScheduler * sched, GstPad * srcpad,
181    GstPad * sinkpad)
182{
183  GstSchedulerClass *sclass;
184
185  g_return_if_fail (GST_IS_SCHEDULER (sched));
186  g_return_if_fail (GST_IS_PAD (srcpad));
187  g_return_if_fail (GST_IS_PAD (sinkpad));
188
189  sclass = GST_SCHEDULER_GET_CLASS (sched);
190
191  if (sclass->pad_unlink)
192    sclass->pad_unlink (sched, srcpad, sinkpad);
193}
194
195/**
196 * gst_scheduler_pad_select:
197 * @sched: the scheduler
198 * @padlist: the padlist to select on
199 *
200 * register the given padlist for a select operation.
201 *
202 * Returns: the pad which received a buffer.
203 */
204GstPad *
205gst_scheduler_pad_select (GstScheduler * sched, GList * padlist)
206{
207  g_return_val_if_fail (GST_IS_SCHEDULER (sched), NULL);
208  g_return_val_if_fail (padlist != NULL, NULL);
209
210  return NULL;
211}
212
213/**
214 * gst_scheduler_add_element:
215 * @sched: the scheduler
216 * @element: the element to add to the scheduler
217 *
218 * Add an element to the scheduler.
219 */
220void
221gst_scheduler_add_element (GstScheduler * sched, GstElement * element)
222{
223  GstSchedulerClass *sclass;
224  gboolean redistribute_clock = FALSE;
225
226  g_return_if_fail (GST_IS_SCHEDULER (sched));
227  g_return_if_fail (GST_IS_ELEMENT (element));
228
229  /* if it's already in this scheduler, don't bother doing anything */
230  if (GST_ELEMENT_SCHED (element) == sched) {
231    GST_CAT_DEBUG (GST_CAT_SCHEDULING, "element %s already in scheduler %p",
232        GST_ELEMENT_NAME (element), sched);
233    return;
234  }
235
236  /* if it's not inside this scheduler, it has to be NULL */
237  g_assert (GST_ELEMENT_SCHED (element) == NULL);
238
239  if (gst_element_provides_clock (element)) {
240    sched->clock_providers = g_list_prepend (sched->clock_providers, element);
241    GST_CAT_DEBUG (GST_CAT_CLOCK, "added clock provider %s",
242        GST_ELEMENT_NAME (element));
243    redistribute_clock = TRUE;
244  }
245  if (gst_element_requires_clock (element)) {
246    sched->clock_receivers = g_list_prepend (sched->clock_receivers, element);
247    GST_CAT_DEBUG (GST_CAT_CLOCK, "added clock receiver %s",
248        GST_ELEMENT_NAME (element));
249    redistribute_clock = TRUE;
250  }
251
252  gst_element_set_scheduler (element, sched);
253
254  if (redistribute_clock) {
255    GstClock *clock;
256
257    clock = gst_scheduler_get_clock (sched);
258    gst_scheduler_set_clock (sched, clock);
259  }
260
261  sclass = GST_SCHEDULER_GET_CLASS (sched);
262
263  if (sclass->add_element)
264    sclass->add_element (sched, element);
265}
266
267/**
268 * gst_scheduler_remove_element:
269 * @sched: the scheduler
270 * @element: the element to remove
271 *
272 * Remove an element from the scheduler.
273 */
274void
275gst_scheduler_remove_element (GstScheduler * sched, GstElement * element)
276{
277  GstSchedulerClass *sclass;
278  GList *link;
279  gboolean redistribute_clock = FALSE;
280
281  g_return_if_fail (GST_IS_SCHEDULER (sched));
282  g_return_if_fail (GST_IS_ELEMENT (element));
283
284  link = g_list_find (sched->clock_providers, element);
285  if (link) {
286    sched->clock_providers = g_list_delete_link (sched->clock_providers, link);
287    GST_CAT_DEBUG (GST_CAT_CLOCK, "removed clock provider %s",
288        GST_ELEMENT_NAME (element));
289    redistribute_clock = TRUE;
290  }
291  link = g_list_find (sched->clock_receivers, element);
292  if (link) {
293    sched->clock_receivers = g_list_delete_link (sched->clock_receivers, link);
294    GST_CAT_DEBUG (GST_CAT_CLOCK, "removed clock receiver %s",
295        GST_ELEMENT_NAME (element));
296    redistribute_clock = TRUE;
297  }
298
299  if (redistribute_clock) {
300    GstClock *clock;
301
302    clock = gst_scheduler_get_clock (sched);
303    gst_scheduler_set_clock (sched, clock);
304  }
305
306  sclass = GST_SCHEDULER_GET_CLASS (sched);
307
308  if (sclass->remove_element)
309    sclass->remove_element (sched, element);
310
311  gst_element_set_scheduler (element, NULL);
312}
313
314/**
315 * gst_scheduler_state_transition:
316 * @sched: the scheduler
317 * @element: the element with the state transition
318 * @transition: the state transition
319 *
320 * Tell the scheduler that an element changed its state.
321 *
322 * Returns: a GstElementStateReturn indicating success or failure
323 * of the state transition.
324 */
325GstElementStateReturn
326gst_scheduler_state_transition (GstScheduler * sched, GstElement * element,
327    gint transition)
328{
329  GstSchedulerClass *sclass;
330
331  g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_STATE_FAILURE);
332  g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
333
334  if (element == sched->parent && sched->parent_sched == NULL) {
335    /* FIXME is distributing the clock in the state change still needed
336     * when we distribute as soon as we add/remove elements? I think not.*/
337    switch (transition) {
338      case GST_STATE_READY_TO_PAUSED:
339      {
340        GstClock *clock = gst_scheduler_get_clock (sched);
341
342        GST_CAT_DEBUG (GST_CAT_CLOCK,
343            "scheduler READY to PAUSED clock is %p (%s)", clock,
344            (clock ? GST_OBJECT_NAME (clock) : "nil"));
345
346        gst_scheduler_set_clock (sched, clock);
347        break;
348      }
349    }
350  }
351
352  sclass = GST_SCHEDULER_GET_CLASS (sched);
353
354  if (sclass->state_transition)
355    return sclass->state_transition (sched, element, transition);
356
357  return GST_STATE_SUCCESS;
358}
359
360/**
361 * gst_scheduler_scheduling_change:
362 * @sched: the scheduler
363 * @element: the element that changed its scheduling strategy
364 *
365 * Tell the scheduler that an element changed its scheduling strategy.
366 * An element could, for example, change its loop function or changes
367 * from a loop based element to a chain based element.
368 */
369void
370gst_scheduler_scheduling_change (GstScheduler * sched, GstElement * element)
371{
372  GstSchedulerClass *sclass;
373
374  g_return_if_fail (GST_IS_SCHEDULER (sched));
375  g_return_if_fail (GST_IS_ELEMENT (element));
376
377  sclass = GST_SCHEDULER_GET_CLASS (sched);
378
379  if (sclass->scheduling_change)
380    sclass->scheduling_change (sched, element);
381}
382
383/**
384 * gst_scheduler_add_scheduler:
385 * @sched: a  #GstScheduler to add to
386 * @sched2: the #GstScheduler to add
387 *
388 * Notifies the scheduler that it has to monitor this scheduler.
389 */
390void
391gst_scheduler_add_scheduler (GstScheduler * sched, GstScheduler * sched2)
392{
393  GstSchedulerClass *sclass;
394
395  g_return_if_fail (GST_IS_SCHEDULER (sched));
396  g_return_if_fail (GST_IS_SCHEDULER (sched2));
397  g_return_if_fail (sched2->parent_sched == NULL);
398
399  GST_DEBUG ("gstscheduler: %p add scheduler %p", sched, sched2);
400
401  gst_object_ref (GST_OBJECT (sched2));
402  gst_object_ref (GST_OBJECT (sched));
403
404  sched->schedulers = g_list_prepend (sched->schedulers, sched2);
405  sched2->parent_sched = sched;
406
407  sclass = GST_SCHEDULER_GET_CLASS (sched);
408
409  if (sclass->add_scheduler)
410    sclass->add_scheduler (sched, sched2);
411}
412
413/**
414 * gst_scheduler_remove_scheduler:
415 * @sched: the scheduler
416 * @sched2: the scheduler to remove
417 *
418 a Notifies the scheduler that it can stop monitoring this scheduler.
419 */
420void
421gst_scheduler_remove_scheduler (GstScheduler * sched, GstScheduler * sched2)
422{
423  GstSchedulerClass *sclass;
424
425  g_return_if_fail (GST_IS_SCHEDULER (sched));
426  g_return_if_fail (GST_IS_SCHEDULER (sched2));
427  g_return_if_fail (sched2->parent_sched == sched);
428
429  GST_DEBUG ("gstscheduler: %p remove scheduler %p", sched, sched2);
430
431  sclass = GST_SCHEDULER_GET_CLASS (sched);
432
433  if (sclass->remove_scheduler)
434    sclass->remove_scheduler (sched, sched2);
435
436  sched->schedulers = g_list_remove (sched->schedulers, sched2);
437  sched2->parent_sched = NULL;
438
439  gst_object_unref (GST_OBJECT (sched2));
440  gst_object_unref (GST_OBJECT (sched));
441}
442
443/**
444 * gst_scheduler_lock_element:
445 * @sched: the scheduler
446 * @element: the element to lock
447 *
448 * Acquire a lock on the given element in the given scheduler.
449 */
450void
451gst_scheduler_lock_element (GstScheduler * sched, GstElement * element)
452{
453  g_return_if_fail (GST_IS_SCHEDULER (sched));
454  g_return_if_fail (GST_IS_ELEMENT (element));
455}
456
457/**
458 * gst_scheduler_unlock_element:
459 * @sched: the scheduler
460 * @element: the element to unlock
461 *
462 * Release the lock on the given element in the given scheduler.
463 */
464void
465gst_scheduler_unlock_element (GstScheduler * sched, GstElement * element)
466{
467  GstSchedulerClass *sclass;
468
469  g_return_if_fail (GST_IS_SCHEDULER (sched));
470  g_return_if_fail (GST_IS_ELEMENT (element));
471
472  sclass = GST_SCHEDULER_GET_CLASS (sched);
473}
474
475/**
476 * gst_scheduler_error:
477 * @sched: the scheduler
478 * @element: the element with the error
479 *
480 * Tell the scheduler an element was in error
481 */
482void
483gst_scheduler_error (GstScheduler * sched, GstElement * element)
484{
485  GstSchedulerClass *sclass;
486
487  g_return_if_fail (GST_IS_SCHEDULER (sched));
488  g_return_if_fail (GST_IS_ELEMENT (element));
489
490  sclass = GST_SCHEDULER_GET_CLASS (sched);
491
492  if (sclass->error)
493    sclass->error (sched, element);
494}
495
496/**
497 * gst_scheduler_yield:
498 * @sched: the scheduler
499 * @element: the element requesting a yield
500 *
501 * Tell the scheduler to schedule another element.
502 *
503 * Returns: TRUE if the element should save its state, FALSE
504 * if the scheduler can perform this action itself.
505 */
506gboolean
507gst_scheduler_yield (GstScheduler * sched, GstElement * element)
508{
509  GstSchedulerClass *sclass;
510
511  g_return_val_if_fail (GST_IS_SCHEDULER (sched), TRUE);
512  g_return_val_if_fail (GST_IS_ELEMENT (element), TRUE);
513
514  sclass = GST_SCHEDULER_GET_CLASS (sched);
515
516  if (sclass->yield)
517    return sclass->yield (sched, element);
518
519  return TRUE;
520}
521
522/**
523 * gst_scheduler_interrupt:
524 * @sched: the scheduler
525 * @element: the element requesting an interrupt
526 *
527 * Tell the scheduler to interrupt execution of this element.
528 *
529 * Returns: TRUE if the element should return NULL from the chain/get
530 * function.
531 */
532gboolean
533gst_scheduler_interrupt (GstScheduler * sched, GstElement * element)
534{
535  GstSchedulerClass *sclass;
536
537  g_return_val_if_fail (GST_IS_SCHEDULER (sched), FALSE);
538  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
539
540  sclass = GST_SCHEDULER_GET_CLASS (sched);
541
542  if (sclass->interrupt)
543    return sclass->interrupt (sched, element);
544
545  return FALSE;
546}
547
548/**
549 * gst_scheduler_get_clock:
550 * @sched: the scheduler
551 *
552 * Gets the current clock used by the scheduler.
553 *
554 * Returns: a GstClock
555 */
556GstClock *
557gst_scheduler_get_clock (GstScheduler * sched)
558{
559  GstClock *clock = NULL;
560
561  /* if we have a fixed clock, use that one */
562  if (GST_FLAG_IS_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK)) {
563    clock = sched->clock;
564
565    GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler using fixed clock %p (%s)",
566        clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
567  } else {
568    GList *schedulers = sched->schedulers;
569    GList *providers = sched->clock_providers;
570
571    /* try to get a clock from one of the schedulers we manage first */
572    while (schedulers) {
573      GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
574
575      clock = gst_scheduler_get_clock (scheduler);
576      if (clock) {
577        GST_CAT_DEBUG (GST_CAT_CLOCK,
578            "scheduler found managed sched clock %p (%s)",
579            clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
580        break;
581      }
582
583      schedulers = g_list_next (schedulers);
584    }
585    /* still no clock, try to find one in the providers */
586    while (!clock && providers) {
587      clock = gst_element_get_clock (GST_ELEMENT (providers->data));
588      if (clock)
589        GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler found provider clock: %p (%s)",
590            clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
591      providers = g_list_next (providers);
592    }
593    /* still no clock, use a system clock */
594    if (!clock && sched->parent_sched == NULL) {
595      clock = gst_system_clock_obtain ();
596      /* we unref since this function is not supposed to increase refcount
597       * of clock object returned; this is ok since the systemclock always
598       * has a refcount of at least one in the current code. */
599      gst_object_unref (GST_OBJECT (clock));
600      GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler obtained system clock: %p (%s)",
601          clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
602    }
603  }
604
605  return clock;
606}
607
608/**
609 * gst_scheduler_use_clock:
610 * @sched: the scheduler
611 * @clock: the clock to use
612 *
613 * Force the scheduler to use the given clock. The scheduler will
614 * always use the given clock even if new clock providers are added
615 * to this scheduler.
616 */
617void
618gst_scheduler_use_clock (GstScheduler * sched, GstClock * clock)
619{
620  g_return_if_fail (sched != NULL);
621  g_return_if_fail (GST_IS_SCHEDULER (sched));
622
623  GST_FLAG_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
624
625  gst_object_replace ((GstObject **) & sched->clock, (GstObject *) clock);
626
627  GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler using fixed clock %p (%s)", clock,
628      (clock ? GST_OBJECT_NAME (clock) : "nil"));
629}
630
631/**
632 * gst_scheduler_set_clock:
633 * @sched: the scheduler
634 * @clock: the clock to set
635 *
636 * Set the clock for the scheduler. The clock will be distributed
637 * to all the elements managed by the scheduler.
638 */
639void
640gst_scheduler_set_clock (GstScheduler * sched, GstClock * clock)
641{
642  GList *receivers;
643  GList *schedulers;
644
645  g_return_if_fail (sched != NULL);
646  g_return_if_fail (GST_IS_SCHEDULER (sched));
647
648  receivers = sched->clock_receivers;
649  schedulers = sched->schedulers;
650
651  gst_object_replace ((GstObject **) & sched->current_clock,
652      (GstObject *) clock);
653
654  while (receivers) {
655    GstElement *element = GST_ELEMENT (receivers->data);
656
657    GST_CAT_DEBUG (GST_CAT_CLOCK,
658        "scheduler setting clock %p (%s) on element %s", clock,
659        (clock ? GST_OBJECT_NAME (clock) : "nil"), GST_ELEMENT_NAME (element));
660
661    gst_element_set_clock (element, clock);
662    receivers = g_list_next (receivers);
663  }
664  while (schedulers) {
665    GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
666
667    GST_CAT_DEBUG (GST_CAT_CLOCK,
668        "scheduler setting clock %p (%s) on scheduler %p", clock,
669        (clock ? GST_OBJECT_NAME (clock) : "nil"), scheduler);
670    gst_scheduler_set_clock (scheduler, clock);
671    schedulers = g_list_next (schedulers);
672  }
673}
674
675/**
676 * gst_scheduler_auto_clock:
677 * @sched: the scheduler
678 *
679 * Let the scheduler select a clock automatically.
680 */
681void
682gst_scheduler_auto_clock (GstScheduler * sched)
683{
684  g_return_if_fail (sched != NULL);
685  g_return_if_fail (GST_IS_SCHEDULER (sched));
686
687  GST_FLAG_UNSET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
688
689  gst_object_replace ((GstObject **) & sched->clock, NULL);
690
691  GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler using automatic clock");
692}
693
694GstClockReturn gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter);
695
696/**
697 * gst_scheduler_clock_wait:
698 * @sched: the scheduler
699 * @element: the element that wants to wait
700 * @id: the clockid to use
701 * @jitter: the time difference between requested time and actual time
702 *
703 * Wait till the clock reaches a specific time. The ClockID can
704 * be obtained from #gst_clock_new_single_shot_id.
705 *
706 * Returns: the status of the operation
707 */
708GstClockReturn
709gst_scheduler_clock_wait (GstScheduler * sched, GstElement * element,
710    GstClockID id, GstClockTimeDiff * jitter)
711{
712  GstSchedulerClass *sclass;
713
714  g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
715  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
716
717  sclass = GST_SCHEDULER_GET_CLASS (sched);
718
719  if (sclass->clock_wait)
720    return sclass->clock_wait (sched, element, id, jitter);
721  else
722    return gst_clock_id_wait (id, jitter);
723}
724
725/**
726 * gst_scheduler_iterate:
727 * @sched: the scheduler
728 *
729 * Perform one iteration on the scheduler.
730 *
731 * Returns: a boolean indicating something usefull has happened.
732 */
733gboolean
734gst_scheduler_iterate (GstScheduler * sched)
735{
736  GstSchedulerClass *sclass;
737  gboolean res = FALSE;
738
739  g_return_val_if_fail (GST_IS_SCHEDULER (sched), FALSE);
740
741  sclass = GST_SCHEDULER_GET_CLASS (sched);
742
743  if (sclass->iterate) {
744    res = sclass->iterate (sched);
745  }
746
747  return res;
748}
749
750
751/**
752 * gst_scheduler_show:
753 * @sched: the scheduler
754 *
755 * Dump the state of the scheduler
756 */
757void
758gst_scheduler_show (GstScheduler * sched)
759{
760  GstSchedulerClass *sclass;
761
762  g_return_if_fail (GST_IS_SCHEDULER (sched));
763
764  sclass = GST_SCHEDULER_GET_CLASS (sched);
765
766  if (sclass->show)
767    sclass->show (sched);
768}
769
770/*
771 * Factory stuff starts here
772 *
773 */
774static void gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass);
775static void gst_scheduler_factory_init (GstSchedulerFactory * factory);
776
777static GstPluginFeatureClass *factory_parent_class = NULL;
778
779/* static guint gst_scheduler_factory_signals[LAST_SIGNAL] = { 0 }; */
780
781GType
782gst_scheduler_factory_get_type (void)
783{
784  static GType schedulerfactory_type = 0;
785
786  if (!schedulerfactory_type) {
787    static const GTypeInfo schedulerfactory_info = {
788      sizeof (GstSchedulerFactoryClass),
789      NULL,
790      NULL,
791      (GClassInitFunc) gst_scheduler_factory_class_init,
792      NULL,
793      NULL,
794      sizeof (GstSchedulerFactory),
795      0,
796      (GInstanceInitFunc) gst_scheduler_factory_init,
797      NULL
798    };
799
800    schedulerfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
801        "GstSchedulerFactory", &schedulerfactory_info, 0);
802  }
803  return schedulerfactory_type;
804}
805
806static void
807gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass)
808{
809  GObjectClass *gobject_class;
810  GstObjectClass *gstobject_class;
811  GstPluginFeatureClass *gstpluginfeature_class;
812
813  gobject_class = (GObjectClass *) klass;
814  gstobject_class = (GstObjectClass *) klass;
815  gstpluginfeature_class = (GstPluginFeatureClass *) klass;
816
817  factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
818
819  if (!_default_name) {
820    if (g_getenv ("GST_SCHEDULER")) {
821      _default_name = g_strdup (g_getenv ("GST_SCHEDULER"));
822    } else {
823      _default_name = g_strdup (GST_SCHEDULER_DEFAULT_NAME);
824    }
825  }
826  g_assert (_default_name);
827}
828
829static void
830gst_scheduler_factory_init (GstSchedulerFactory * factory)
831{
832}
833
834
835/**
836 * gst_scheduler_register:
837 * @plugin: a #GstPlugin
838 * @name: name of the scheduler to register
839 * @longdesc: description of the scheduler
840 * @type: #GType of the scheduler to register
841 *
842 * Registers a scheduler with GStreamer.
843 *
844 * Returns: TRUE, if the registering succeeded, FALSE on error.
845 *
846 * Since: 0.8.5
847 **/
848gboolean
849gst_scheduler_register (GstPlugin * plugin, const gchar * name,
850    const gchar * longdesc, GType type)
851{
852  GstSchedulerFactory *factory;
853
854  g_return_val_if_fail (plugin != NULL, FALSE);
855  g_return_val_if_fail (name != NULL, FALSE);
856  g_return_val_if_fail (longdesc != NULL, FALSE);
857  g_return_val_if_fail (g_type_is_a (type, GST_TYPE_SCHEDULER), FALSE);
858
859  factory = gst_scheduler_factory_find (name);
860  if (factory) {
861    g_return_val_if_fail (factory->type == 0, FALSE);
862    g_free (factory->longdesc);
863    factory->longdesc = g_strdup (longdesc);
864    factory->type = type;
865  } else {
866    factory = gst_scheduler_factory_new (name, longdesc, type);
867    g_return_val_if_fail (factory, FALSE);
868    gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
869  }
870
871  return TRUE;
872}
873
874/**
875 * gst_scheduler_factory_new:
876 * @name: name of schedulerfactory to create
877 * @longdesc: long description of schedulerfactory to create
878 * @type: the gtk type of the GstScheduler element of this factory
879 *
880 * Create a new schedulerfactory with the given parameters
881 *
882 * Returns: a new #GstSchedulerFactory.
883 */
884GstSchedulerFactory *
885gst_scheduler_factory_new (const gchar * name, const gchar * longdesc,
886    GType type)
887{
888  GstSchedulerFactory *factory;
889
890  g_return_val_if_fail (name != NULL, NULL);
891
892  factory = gst_scheduler_factory_find (name);
893
894  if (!factory) {
895    factory =
896        GST_SCHEDULER_FACTORY (g_object_new (GST_TYPE_SCHEDULER_FACTORY, NULL));
897    GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
898  } else {
899    g_free (factory->longdesc);
900  }
901
902  factory->longdesc = g_strdup (longdesc);
903  factory->type = type;
904
905  return factory;
906}
907
908/**
909 * gst_scheduler_factory_destroy:
910 * @factory: factory to destroy
911 *
912 * Removes the scheduler from the global list.
913 */
914void
915gst_scheduler_factory_destroy (GstSchedulerFactory * factory)
916{
917  g_return_if_fail (factory != NULL);
918
919  /* we don't free the struct bacause someone might  have a handle to it.. */
920}
921
922/**
923 * gst_scheduler_factory_find:
924 * @name: name of schedulerfactory to find
925 *
926 * Search for an schedulerfactory of the given name.
927 *
928 * Returns: #GstSchedulerFactory if found, NULL otherwise
929 */
930GstSchedulerFactory *
931gst_scheduler_factory_find (const gchar * name)
932{
933  GstPluginFeature *feature;
934
935  g_return_val_if_fail (name != NULL, NULL);
936
937  GST_DEBUG ("gstscheduler: find \"%s\"", name);
938
939  feature = gst_registry_pool_find_feature (name, GST_TYPE_SCHEDULER_FACTORY);
940
941  if (feature)
942    return GST_SCHEDULER_FACTORY (feature);
943
944  return NULL;
945}
946
947/**
948 * gst_scheduler_factory_create:
949 * @factory: the factory used to create the instance
950 * @parent: the parent element of this scheduler
951 *
952 * Create a new #GstScheduler instance from the
953 * given schedulerfactory with the given parent. @parent will
954 * have its scheduler set to the returned #GstScheduler instance.
955 *
956 * Returns: A new #GstScheduler instance with a reference count of %1.
957 */
958GstScheduler *
959gst_scheduler_factory_create (GstSchedulerFactory * factory,
960    GstElement * parent)
961{
962  GstScheduler *sched = NULL;
963
964  g_return_val_if_fail (factory != NULL, NULL);
965  g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
966
967  if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
968    g_return_val_if_fail (factory->type != 0, NULL);
969
970    sched = GST_SCHEDULER (g_object_new (factory->type, NULL));
971    sched->parent = parent;
972
973    GST_ELEMENT_SCHED (parent) = sched;
974
975    /* let's refcount the scheduler */
976    gst_object_ref (GST_OBJECT (sched));
977    gst_object_sink (GST_OBJECT (sched));
978  }
979
980  return sched;
981}
982
983/**
984 * gst_scheduler_factory_make:
985 * @name: the name of the factory used to create the instance
986 * @parent: the parent element of this scheduler
987 *
988 * Create a new #GstScheduler instance from the
989 * schedulerfactory with the given name and parent. @parent will
990 * have its scheduler set to the returned #GstScheduler instance.
991 * If %NULL is passed as @name, the default scheduler name will
992 * be used.
993 *
994 * Returns: A new #GstScheduler instance with a reference count of %1.
995 */
996GstScheduler *
997gst_scheduler_factory_make (const gchar * name, GstElement * parent)
998{
999  GstSchedulerFactory *factory;
1000  const gchar *default_name = gst_scheduler_factory_get_default_name ();
1001
1002  if (name)
1003    factory = gst_scheduler_factory_find (name);
1004  else {
1005    /* FIXME: do better error handling */
1006    if (default_name == NULL)
1007      g_error ("No default scheduler name - do you have a registry ?");
1008    factory = gst_scheduler_factory_find (default_name);
1009  }
1010
1011  if (factory == NULL)
1012    return NULL;
1013
1014  return gst_scheduler_factory_create (factory, parent);
1015}
1016
1017/**
1018 * gst_scheduler_factory_set_default_name:
1019 * @name: the name of the factory used as a default
1020 *
1021 * Set the default schedulerfactory name.
1022 */
1023void
1024gst_scheduler_factory_set_default_name (const gchar * name)
1025{
1026  g_free (_default_name);
1027
1028  _default_name = g_strdup (name);
1029}
1030
1031/**
1032 * gst_scheduler_factory_get_default_name:
1033 *
1034 * Get the default schedulerfactory name.
1035 *
1036 * Returns: the name of the default scheduler.
1037 */
1038const gchar *
1039gst_scheduler_factory_get_default_name (void)
1040{
1041  return _default_name;
1042}
Note: See TracBrowser for help on using the repository browser.