1 Introduction
Upipe is a flexible dataflow framework. It is primarily designed to be the core of a multimedia player, transcoder or streamer. The framework organizes the processing of incoming data buffer inside a pipeline of modules. It exposes core types for buffers and modules (called "pipes"), and the API of communication between pipes and between the application and pipes.
Unlike most multimedia frameworks, Upipe was specified bottom-up. It implies that an application using Upipe is not restricted to a single high-level API, but can also implement and use any of the lower-level programming interfaces. It is also always possible to build higher-level interfaces. Its core data structures are expected to work efficiently without needlessly depending on each other, and are independently unit-tested.
The concept was completely designed and created in 2012, with today's computing architectures in mind. In particular, all platforms are nowadays more or less super-scalar (even your cell phone), and Upipe has been written to take advantage of several cores when needed. It may at first be surprising to notice that none of the core modules of Upipe deal with threads. However, the basic data structures have been implemented with lock-less or wait-less algorithms and therefore do not depend on the number of threads. Upipe's philosophy is to let the application (or higher-level APIs) create FIFOs and threads when it is necessary, not when the developer of the framework found it fancy to put a thread there, that would end up using 0.01% of a core and add unwanted latency.
Since it doesn't require its own thread architecture, it also doesn't require a specific event loop manager. It can therefore be incorporated quite easily into event loops coming from other projects, like glib, Qt or Ecore. By default it comes with an optional libev support.
In Upipe, all data processing originates from any number of "pumps" which trigger on certain events. Typical threading APIs such as mutex or condition variable aren't used, and are replaced with asynchronous events triggering pumps.
Another key design choice is the separation of data processing from decision taking. "Pipes" are not supposed to make any decision (such as selecting this elementary stream or decoding to 720x576), and whenever an action is necessary, an event is sent to "probes" provided by the application, which would typically send a control command to the pipe, or dynamically create (recreate) a part of the pipeline by allocating new pipes.
Upipe's standard distribution will include standard probes for the simpler cases, but an application is always free to override their behaviour and take different decisions.