GstInterpipe

Introduction

Overview

GstInterpipe is a Gstreamer plug-in that allows communication between two independent pipelines. The plug-in consists of two elements:

  • interpipesink
  • interpipesrc

Generally speaking, the idea is that given a source pipeline:

v4l2src ! interpipesink name=video_src

Various sink pipelines may listen to it by:

interpipesrc listen-to=video_src ! xvimagesink
interpipesrc listen-to-video_src num-buffers=1 ! jpegenc ! filesink location=snapshot.jpeg 

The state of each pipeline is independent, each one can manage events by their own and can be attached or detached at any moment.

The concept behind the Interpipes Project is to simplify the construction of GStreamer applications, which often has the complexity of requiring dynamic pipelines. It transforms the construction process from low level pad probe manipulation to the higher level setting an element's parameter value. Application developers don't get mired down in stalled pipelines because one branch of a complex pipeline changed state.

For example, take a look in a complex pipeline like the one in the figure 1:

 
Figure 1: Complex Pipeline

The complex pipeline of figure 1 can be constructed into smaller, independent pipelines using interpipe elements as it is illustrated in the figure 2:

 
Figure 2: Pipeline using Interpipes

This way the stream flow in a complex pipeline is reduced to simply set the correct listeners in the interpipe elements taking away the complexity of re-configuring pads or some other complex and error-prone logic.

Features and Limitations

The GstInterpipe project exposes the following characteristics:

  • Inspired by intervideosrc/intervideosink
  • Uses appsrc and appsink as a base
  • Generic data handling
  • Multiple dynamic interpipesink - interpipesrc connections
  • Replace tee and selector elements allowing dynamic pipeline flow control with GStreamer Daemon

The principal features the plug-in exposes are the following. These ones are explained with further detail later.

  • Buffer transfer
    Interpipesink will transfer automagically the buffers it receives to all the interpipesrcs that are currently listening to it.
  • Dynamic switching
    Interpipesrc can switch the interpipesink they are listening to at any time just by setting the property to the new value. No need to worry about the pipeline's state, dangerous events like EOS, pad probes, valves, selectors, pad links, etc...
  • Caps negotiation
    Even though interpipes break a big pipeline into smaller ones, the caps negotiation process takes into account all of them. This means that it is guaranteed that the negotiated caps will be supported by the source and all its listeners (or fail due to missing valid intersection).
  • Event forwarding
    Similar to buffers, events may be forwarded from the interpipesinks to the interpipesrcs, and viceversa. The project takes into account downstream and upstream events, as well as in-bounds and out-of-bands events.
  • Timestamp synchronization
    The base times of independent pipelines will likely be different. Given that a buffer will be transferred from one pipe to another, this may represent a problem in situations where synchronization is a must. GstInterpipe takes care of this situation by compensating the buffer's timestamps according to the pipeline's base time, ensuring appropriate synchronization.

The current release exposes the following limitations and known bugs:

  • Specialized clocks
    At the time being, pipelines negotiate their clock independently. If a pipeline uses a special clock (i.e.: GstAudioSinkClock), the associated pipes (being independent) may negotiate different clocks, typically GstSystemClock. This could be a big problem if, for example, synchronization between streams is required. It is currently responsibility of the application to set the special clock in all the involved pipes by calling gst_pipeline_set_clock.

Getting the Software

GstInterpipe is an open source project and can be downloaded from GitHub. The project is hosted at:

TODO

As with every open source project, there's an open invitation to provide feedback to the maintainers as bug reports, feature requests and even source code collaborations. The following table summarizes the recommended methods to collaborate with RidgeRun:

Collaboration Method
Bug report GitHub's issue tracker
Feature request GitHub's issue tracker
Patch Submission Pull request

Installation Guide

Dependencies

The following packages are needed in order to build and use gst-interpipe:

  • gstreamer-1.0
  • gstreamer-plugins-base-1.0
  • gstreamer-app-1.0
  • gstreamer-check-1.0

These are likely already installed in your OS distribution. In case you want to double check and install the missing packages, run the following commands according to your OS:

Debian Based

This includes Ubuntu, Kubuntu, Debian, etc...

sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev

Mac OSX

Using Mac Ports:

sudo port install gstreamer1 gstreamer1-gst-plugins-base

Building the project

In order to build the project run the following commands. Note that the libdir may vary according to your system.

./autogen.sh --libdir /usr/lib/x86_64-linux-gnu/gstreamer-1.0/
make

The autogen.sh script will automatically run the configure script. In case a more complex configuration is needed, the configure step may be executed manually:

./autogen.sh --noconfigure
./configure --libdir /usr/lib/x86_64-linux-gnu/gstreamer-1.0/ <additional advanced options>
make

Finally, the status of the current version may be checked by running the unit tests:

make check

Installing the plugin

The plugin is installed to the GStreamer's default plug-in location in the file system by running:

sudo make install

If you don't want to install the plugin in the default location, it may also be found by setting GST_PLUGIN_PATH to the library location. For example:

GST_PLUGIN_PATH=/home/mgruner/gst-interpipe-1.0/gst/interpipe/.libs gst-inspect-1.0 interpipe

User Guide

The following sections describe in detail the different capabilities of the elements, configurations and examples.

Features

Buffer Forwarding

The main purpose of the GstInterpipe Project is to communicate buffers from one pipeline to another. This can be done in a safe way, without worrying about the states or events of any of the pipelines. To set an interpipesrc (listener) to listen to a specific interpipesink (node), all it is needed is to set the listen-to property. A NULL or empty listen-to will disconnect the listener from any node. The following table summarises the properties involved in buffer transfer.

Property
Element interpipesrc
Name listen-to
Description The name of the node to listen to
Special Values NULL Stop listening
(empty) Stop listening


Property
Element interpipesink
Name name
Description The name of the node. It can only be set during construction.
Special Values


The following figures, and their respective gst-launch pipelines illustrate this concept:

gst-launch-1.0 \
videotestsrc ! interpipesink name=camera \
interpipesrc listen-to="" ! fakesink
 
Detached pipelines
gst-launch-1.0 \
videotestsrc ! interpipesink name=camera \
interpipesrc listen-to="camera" ! fakesink
 
Attached pipelines

Dynamic Switching

One of the greatest strengths of GstInterpipe is the ability of an interpipesrc to switch between different interpipesinks at runtime. To do so, change the listen-to property. Similarly, disconnections and reconnections can be performed by clearing and setting the property accordingly. When performing dynamic switching, caps must be taken into consideration. Specifically, a switch can be performed to a node in two scenarios:

No other listeners
Caps are re-negotiated between the two pipelines, looking for the optimum caps.
Existing listeners
The sink pipeline must support the caps already configured by the node and listeners, otherwise it'll fail.

The following figure illustrates this concept:

 
Dynamic Switch Scenarios

The caps re-negotiation capability can be disabled with the allow-renegotiation property. The following table summarises the involved property:

Property
Element interpipesrc
Name allow-renegotiation
Description Allow the interpipesrc to renegotiate caps when attached to an interpipesink with different caps.
Special Values

The switch can be disabled entirely by setting the block-switch property.

Property
Element interpipesrc
Name block-switch
Description Allow changing the node a listener is currently listening to.
Special Values

Programatically, the dynamic switch can be performed as the following:

/* Create pipelines */
GstElement *pipe1 = gst_parse_launch ("videotestsrc ! interpipesink name=camera1", NULL);
GstElement *pipe2 = gst_parse_launch ("videotestsrc ! interpipesink name=camera2", NULL);
GstElement *pipe3 = gst_parse_launch ("interpipesrc name=src listen-to=camera1 ! fakesink", NULL);

/* Grab a reference to the interpipesrc */
GstElement *src = gst_bin_get_by_name(pipe3, "src");

/* Perform the switch */
g_object_set (src, "listen-to", "camera2", NULL);

Caps Negotiation

GstInterpipe takes into account the node and all its listeners during the caps negotiation process. It is guaranteed that the resulting supported set of caps will be an intersection between all the listeners and node caps. This only applies to the listeners that are connected during the caps negotiation process. If a listener is adhered later, it will be handled independently (see Dynamic Switching).

The following figure shows this concept.

 
Caps negotiation process

Event Forwarding

As with buffers, events can be transferred from the nodes to the listeners (and viceversa). GStreamer handles three types of events:

  • Upstream Events: events that travel contrary to the buffer flow
  • Downstream Out-Of-Bounds Events: events traveling in the same direction as the buffer flow, but sent immediately.
  • Downstream In-Bounds Events: events traveling in the same direction as the buffer flow, but sent serialised with the buffers.

GstInterpipe supports the three types of events, each one under different considerations. Additionally, the EOS is treated with special care, hence controlled by independent properties. The following sections describe these scenarios

Upstream Events

Upstream events are sent from the listeners to the node. Upstream events are only transferred if the event emitter is the only listener connected to the node. This was designed this way in order to avoid changing the node state to the other listeners. The following image describes this situations:

 
Upstream events transfer

Downstream Out-Of-Bounds Events

Out-Of-Bounds downstream events are sent from the node to the listeners. These events are sent to all of the listeners as soon as they are received. By setting the forward-events, the node can be configured to avoid sending events. By setting the accept-events, individual listeners can be configured to avoid receiving events. The following tables summarise these properties:

Property
Element interpipesink
Name forward-events
Description Allow the interpipesink to forward any kind of events to the listeners
Special Values


Property
Element interpipesrc
Name accept-events
Description Accept events coming from the node
Special Values

Graphically, the following figure shows different configuration examples.

 
Downstream out-of-bounds event transfer

Downstream In-Bounds Events

In-bound downstream events travel from the node to all the listeners. The main difference is that they travel inlined with the buffer flow. Internally, both the interpipesink and interpipesrc con queue buffers, so serial events are queued as well so that they are pushed at the precise moment they need to be sent. The same set of properties control the transmission of these events.

Graphically, this can be appreciated as the following image:

 
Downstream in bounds event transfer

End-Of-Stream Events

EOS events are a special type of in-bounds downstream events. The same queuing principles apply to these. However, this event typically causes drastic pipeline consequences, to it is likely that a pipeline could want to receive all event types, but the EOS. For this reason, the EOS transfer can be controlled by setting forward-eos to disable EOS transfer completely from the node, or accept-eos to selectively block the EOS in individual listeners. The following table summarises the properties.

Graphically, this can be appreciated as the following image:

 
Downstream in bounds event transfer
Property
Element interpipesink
Name forward-eos
Description Allow the interpipesink to forward EOS events to the listeners
Special Values


Property
Element interpipesrc
Name accept-eos
Description Accept EOS events coming from the node
Special Values

Timestamp Synchronization

Properties

Examples