6 - remove loop/get/chain from GstElement and add a "iterate" method.
7 The iterate method is called with the event (or events) that
8 triggered it, performs some action, and resets the events (file
9 descriptors becoming readable, semaphores, pads becoming readable
10 or writable, or a time occurs).
12 - Add GstLoopElement, GstChainElement, etc. for compatibility.
14 - Remove existing state handling and create 2 states, "playing" and
15 "stopped". "playing" means that the iterate() method of the
16 element may be called, that is, the element is allowed to move
17 buffers, negotiate, etc. "stopped" means that no gstreamer-ish
18 things happen to an element, only gobject-ish. A separate
19 reset() method will handle the difference between READY and NULL.
21 - Add a flag "ready" to GstElement that is under the control of the
22 element. If the element is ready to stream, it sets this flag,
23 and the entire pipeline starts streaming. (This is basically
24 the difference between PAUSED and PLAYING.) For example, osssink
25 won't set the ready flag until the device is opened and there is
26 a buffer available to write to the device.
28 - Scheduling of elements and movement of buffers will be timed by
35 Pipeline: sinesrc ! osssink
37 - The application creates the pipeline and sets it to "playing".
39 - The clock is created and set to "paused".
41 - sinesrc.iterate() decides to watch for the event "src pad
42 negotiation" and sets the available caps on the pad.
44 - osssink.iterate() opens device, determines available caps, and
45 sets the available caps on the pad. Then it decides to wait for
46 "sink pad negotiation".
48 - The scheduler realizes that the two elements are waiting for
49 negotiation, so it negotiates the link.
51 - sinesrc.iterate() sets the "ready" flag (because it needs no more
52 preparation to stream) and decides to watch for the event "src
53 pad ready to accept buffer".
55 - osssink.iterate() decides to watch for the event "sink pad has
58 - The scheduler realizes that sinesrc.srcpad is now ready, so it
59 calls sinesrc.iterate()
61 - sinesrc.iterate() creates a buffer and pushes it, and decides to
62 wait for the same event.
64 - The scheduler realizes that osssink.sinkpad now has a buffer, so
65 it calls osssink.iterate().
67 - osssink.iterate() is now ready to stream, so it sets the "ready"
68 flag and waits for "time 0".
70 - The pipeline is now completely ready, so the clock may be
71 started. A signal is fired to let the application know this
72 (and possibly change the default behavior).
74 - The clock starts with the time 0. The scheduler realizes this,
75 and decides to schedule osssink.
77 - osssink.iterate() is called, and writes the buffer to the device.
78 This starts the clock counting. (Actually, the buffer could be
79 written by the clock code, since presumably the clock is related
80 to osssink.) iterate() then waits for "sink pad has available
83 We're now basically in streaming mode. A streaming cycle:
85 - osssink.iterate() decides the audio output buffer is full enough,
86 so it waits for "time X", where X is the time when the output
87 buffer will be below some threshold.
89 - osssink.iterate() waits for "sink pad has available buffer"
91 - sinesrc.iterate() creates and pushes a buffer, then waits for
97 - osssink can set a hard deadline time, which means that if it is
98 not scheduled before that time, you'll get a skip. Skipping
99 involves setting osssink to "not ready" and pauses the clock.
100 Then the scheduler needs to go through the same process as above
103 - As a shortcut, osssink can say "I need a buffer on the sinkpad
104 at time X". This information can be passed upstream, and be used
105 in filters -- filter.sinkpad says "I need a buffer at time X-N",
106 where N is the latency of the filter.
111 Pipeline: osssrc ! osssink
113 - The application creates the pipeline and sets it to "playing".
115 - The clock is created and set to "paused".
117 - negotiation happens roughly as in example #1, although osssrc
118 additionally opens and prepares the device.
120 - osssrc.iterate() sets the "ready" flag (because it needs no more
121 preparation to stream) and waits for "time 0", since it presumably
122 can't wait for the file descriptor (audio input hasn't been
123 enabled on the device yet.)
125 - osssink.iterate() decides to watch for the event "sink pad has
128 - The scheduler realizes the deadlock and (somehow) tells osssink
129 that it can't pre-roll. (This needs more work) In other words,
130 osssink can't be the clock master, but only a clock slave.
132 - osssink.iterates() agrees to start at time SOME_LATENCY, sets the
133 "ready" flag, and waits for a buffer on its sink pad.
135 - The pipeline is now completely ready, so the clock may be
136 started. A signal is fired to let the application know this
137 (and possibly change the default behavior).
139 - The clock starting causes two things to happen: osssrc starts
140 the recording of data, and osssink starts the outputting of data.
141 The data being output is a chunk of silence equal to SOME_LATENCY.
143 - osssrc.iterate() is called for "time 0", does nothing, and waits
144 on the file descriptor (via the scheduler, of course). All waiting
145 on file descriptors should have an associated timeout.
147 - osssrc.iterate() is called when the file descriptor is ready,
148 reads a chunk of data, and pushes the buffer. It then waits for
149 its file descriptor to be ready.
151 - osssink.iterate() is called
156 fakesrc ! tee ! fakesink tee0. ! never_accept_a_buffer_sink
158 sinesrc ! osssink videotestsrc ! ximagesink
160 fakesrc ! fakesink (pausing)
162 sinesrc ! identity ! osssink