Scheduling The scheduler is responsible for managing the plugins at runtime. Its main responsibilities are: Preparing the plugins so they can be scheduled. Monitoring state changes and enabling/disabling the element in the chain. Choosing an element as the entry point for the pipeline. Selecting and distributing the global clock. The scheduler is a pluggable component; this means that alternative schedulers can be written and plugged into GStreamer. The default scheduler uses cothreads to schedule the plugins in a pipeline. Cothreads are fast and lightweight user-space threads. There is usually no need to interact with the scheduler directly, however in some cases it is feasible to set a specific clock or force a specific plugin as the entry point in the pipeline. Chain-based elements Chain based elements receive a buffer of data and are supposed to handle the data and perform a gst_pad_push. The basic main function of a chain-based element is like: static void chain_function (GstPad *pad, GstBuffer *buffer) { GstBuffer *outbuffer; .... // process the buffer, create a new outbuffer ... gst_pad_push (srcpad, outbuffer); } Chain based function are mainly used for elements that have a one to one relation between their input and output behaviour. An example of such an element can be a simple video blur filter. The filter takes a buffer in, performs the blur operation on it and sends out the resulting buffer. Another element, for example, is a volume filter. The filter takes audio samples as input, performs the volume effect and sends out the resulting buffer. Loop-based elements As opposed to chain-based elements, loop-based elements enter an infinite loop that looks like this: GstBuffer *buffer, *outbuffer; while (1) { buffer = gst_pad_pull (sinkpad); ... // process buffer, create outbuffer while (!done) { .... // optionally request another buffer buffer = gst_pad_pull (sinkpad); .... } ... gst_pad_push (srcpad, outbuffer); } The loop-based elements request a buffer whenever they need one. When the request for a buffer cannot be immediately satisfied, the control will be given to the source element of the loop-based element until it performs a push on its source pad. At that time the control is handed back to the loop-based element, etc... The execution trace can get fairly complex using cothreads when there are multiple input/output pads for the loop-based element. Cothread switches are performed within the call to gst_pad_pull and gst_pad_push; from the perspective of the loop-based element, it just "appears" that gst_pad_push (or _pull) might take a long time to return. Loop based elements are mainly used for the more complex elements that need a specific amount of data before they can start to produce output. An example of such an element is the MPEG video decoder. The element will pull a buffer, perform some decoding on it and optionally request more buffers to decode, and when a complete video frame has been decoded, a buffer is sent out. For example, any plugin using the bytestream library will need to be loop-based. There is no problem in putting cothreaded elements into a GstThread to create even more complex pipelines with both user and kernel space threads. The optimal scheduler Explain opt a bit, chains, groups, and how it affects execution.