Added status of the documents
[platform/upstream/gstreamer.git] / docs / random / omega / plan-generation
1 OUTDATED
2 --------
3
4 Plan generation happens at transition from NULL to READY (and PLAYING to READY right now, need to fix
5 that).  By way of some logic in gst_bin_change_state(), gst_bin_create_plan() is only called for the
6 outer Bin, usually a Pipeline.  This keeps things from getting nasty later on.
7
8 A major new concept in plan generation is that of the 'manager'.  This is the element that is reponsible
9 for running a given element.  In general, Pipelines and Threads are the only managing-capable elements
10 (have the MANAGER flag set), since they are the only ones with real scheduling authority (because they
11 have a process context to play with, basically).
12
13 gst_bin_set_manager() is called to set the manager element of the bin and all it's children and their
14 children.  However, there's one important trick: it won't recurse into child Bins that have the MANAGER
15 flag set.  This avoids some highly redundant recursion.
16
17 When create_plan() is called on the outside Pipeline, the first thing it does is call
18 set_manager(self,self).  As noted above, this recursion will not proceed into child Bins that have the
19 MANAGER flag set.
20
21 The next step is to recursively generate the plan (yes, head-recursive).  This gives child Bins the
22 opportunity to generate their plan first, causing a inside-to-outside sequence.  This matches the way
23 the scheduling is arranged now, where the plan for a Src/Connection outside a Bin is handled by that
24 Bin, not it's parent.  But we must be very careful not to stomp on that plan in the parent Bin.
25
26 Because create_plan() is called on all Bins, but we can only set up scheduling state in MANAGER bins,
27 create_plan() must perform create_plan() recursion, but not do anything else *unless* the MANAGER bit is
28 set.  It shouldn't even call set_manager() unless it's a MANAGER itself, because calling it otherwise
29 would waste time doing the work again.  Basically, from the standpoing of setting the manager,
30 create_plan() recursion starts it when the current Bin is a MANAGER, and set_manager() stops when it
31 finds the next one.  create_plan()'s further recursion eventually starts the process back up again
32 furtuer down the hierarchy, until everything is covered.
33
34 For all MANAGER Bins, the last step is to actually create the scheduling plan.  This is still one of the
35 nastiest chunks of code in the whole project, and probably will do nothing but get worse from now on (it
36 got better recently, but only because I took a chainsaw to the code and broke everthing...).  It will
37 remain similar to what it is now, but with some definite differences.
38
39 First task is now to find all the elements that we're responsible for.  This is normally a recursive
40 process, because the structure is an arbitrary tree.  However, something like the following should work 
41 (bin is self):
42
43   GSList *elements = NULL;
44   GList *children;
45   GSList *waiting_bins = NULL;
46   GstBin *waiting_bin;
47
48   waiting_bins = g_slist_prepend (waiting_bins,bin);
49
50   while (waiting_bins) {
51     // retrieve the top of the stack and pop it
52     waiting_bin = GST_BIN (waiting_bins->data);
53     waiting_bins = g_slist_remove (waiting_bins,waiting_bin);
54
55     // walk the list of elements, and find bins
56     children = waiting_bin->children;
57     while (children) {
58       // add it to the list of elements
59       elements = g_slist_prepend (elements, children->data);
60
61       // if it's a bin and it's not a managing bin,
62       // shove it on the list of bins to recurse into
63       if (GST_IS_BIN (children->data) && 
64           !GST_FLAG_IS_SET (GST_ELEMENT (children->data)))
65         waiting_bins = g_slist_prepend (waiting_bins,children->data);
66
67       children = g_list_next (children);
68     }
69   }
70
71 The code makes the assumption that the manager of every element is the same until such time as a
72 different managing parent appears in the hierarchy.  This is the result of the aforementioned nested
73 recursion of create_plan() and set_manager(), but may not remain the case forever.  The above loop
74 should probably be slightly re-written to work solely on whether or not the Bin in question is the
75 element's manager.  This means that the child Bins are *always* recursed into, in case there's a rogue
76 element inside of one of them that's supposed to be managed.
77
78 At the same time all the elements managed by this bin are found (i.e. in the inner loop), we can
79 determine some useful bits of information, such as testing for several cases that require the use of
80 cothreads.  The availability of manager information at this point may aid significantly in this
81 decision.
82
83 Finally, the scheduling plan is generated, based on all the elements to be managed by the Bin (the list
84 of which may span several 'generations' of Bins and elements).  Elements which have peers in child
85 self-managed Bins are left alone on for the pad in that makes that connection.  This should keep the
86 parent Bins from stepping all over state set up by the child Bins, by establishing clear implicit
87 ownership on the pad level, based on the managing Bins' relationship to the pad.