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.