PipeWire 1.4.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
Streams
See also
Stream

Overview

Streams are used to exchange data with the PipeWire server. A stream is a wrapper around a proxy for a pw_client_node with an adapter. This means the stream will automatically do conversion to the type required by the server.

Streams can be used to:

  • Consume a stream from PipeWire. This is a PW_DIRECTION_INPUT stream.
  • Produce a stream to PipeWire. This is a PW_DIRECTION_OUTPUT stream

You can connect the stream port to a specific server port or let PipeWire choose a port for you.

For more complicated nodes such as filters or ports with multiple inputs and/or outputs you will need to use the pw_filter or make a pw_node yourself and export it with pw_core_export.

Streams can also be used to:

  • Implement a Sink in PipeWire. This is a PW_DIRECTION_INPUT stream.
  • Implement a Source in PipeWire. This is a PW_DIRECTION_OUTPUT stream

In this case, the PW_KEY_MEDIA_CLASS property needs to be set to "Audio/Sink" or "Audio/Source" respectively.

Create

Make a new stream with pw_stream_new(). You will need to specify a name for the stream and extra properties. The basic set of properties each stream must provide is filled in automatically.

Once the stream is created, the state_changed event should be used to track the state of the stream.

Connect

The stream is initially unconnected. To connect the stream, use pw_stream_connect(). Pass the desired direction as an argument.

The direction is:

  • PW_DIRECTION_INPUT for a stream that consumes data. This can be a stream that captures from a Source or a when the stream is used to implement a Sink. An application will use a PW_DIRECTION_INPUT stream to record data. A virtual sound card will use a PW_DIRECTION_INPUT stream to implement audio playback.
  • PW_DIRECTION_OUTPUT for a stream that produces data. This can be a stream that plays to a Sink or when the stream is used to implement a Source. An application will use a PW_DIRECTION_OUTPUT stream to produce data. A virtual sound card or camera will use a PW_DIRECTION_OUTPUT stream to implement audio or video recording.

Stream target

To make the newly connected stream automatically connect to an existing PipeWire node, use the PW_STREAM_FLAG_AUTOCONNECT and set the PW_KEY_OBJECT_SERIAL or the PW_KEY_NODE_NAME value of the target node in the PW_KEY_TARGET_OBJECT property before connecting.

Stream formats

An array of possible formats that this stream can consume or provide must be specified.

Format negotiation

After connecting the stream, the server will want to configure some parameters on the stream. You will be notified of these changes with the param_changed event.

When a format param change is emitted, the client should now prepare itself to deal with the format and complete the negotiation procedure with a call to pw_stream_update_params().

As arguments to pw_stream_update_params() an array of spa_param structures must be given. They contain parameters such as buffer size, number of buffers, required metadata and other parameters for the media buffers.

Buffer negotiation

After completing the format negotiation, PipeWire will allocate and notify the stream of the buffers that will be used to exchange data between client and server.

With the add_buffer event, a stream will be notified of a new buffer that can be used for data transport. You can attach user_data to these buffers. The buffers can only be used with the stream that emitted the add_buffer event.

After the buffers are negotiated, the stream will transition to the PW_STREAM_STATE_PAUSED state.

Streaming

From the PW_STREAM_STATE_PAUSED state, the stream can be set to the PW_STREAM_STATE_STREAMING state by the PipeWire server when data transport is started.

Depending on how the stream was connected it will need to Produce or Consume data for/from PipeWire as explained in the following subsections.

Consume data

The process event is emitted for each new buffer that can be consumed.

pw_stream_dequeue_buffer() should be used to get the data and metadata of the buffer.

The buffer is owned by the stream and stays alive until the remove_buffer callback has returned or the stream is destroyed.

When the buffer has been processed, call pw_stream_queue_buffer() to let PipeWire reuse the buffer.

Although not strictly required, it is recommended to call pw_stream_dequeue_buffer() and pw_stream_queue_buffer() from the process() callback to minimize the amount of buffering and maximize the amount of buffer reuse in the stream.

It is also possible to dequeue the buffer from the process event, then process and queue the buffer from a helper thread. It is also possible to dequeue, process and queue a buffer from a helper thread after receiving the process event.

Produce data

The process event is emitted when a new buffer should be queued.

When the PW_STREAM_FLAG_RT_PROCESS flag was given, this function will be called from a realtime thread and it is not safe to call non-reatime functions such as doing file operations, blocking operations or any of the PipeWire functions that are not explicitly marked as being RT safe.

pw_stream_dequeue_buffer() gives an empty buffer that can be filled.

The buffer is owned by the stream and stays alive until the remove_buffer event is emitted or the stream is destroyed.

Filled buffers should be queued with pw_stream_queue_buffer().

Although not strictly required, it is recommended to call pw_stream_dequeue_buffer() and pw_stream_queue_buffer() from the process() callback to minimize the amount of buffering and maximize the amount of buffer reuse in the stream.

Buffers that are queued after the process event completes will be delayed to the next processing cycle.

Obtaining timing information

With pw_stream_get_time_n() and pw_stream_get_nsec() on can get accurate timing information of the data and the graph in the pw_time. See the documentation of these functions.

Driving the graph

Starting in 0.3.34, it is possible for a stream to drive the graph. This allows interrupt-driven scheduling for drivers implemented as PipeWire streams, without having to reimplement the stream as a SPA plugin.

A stream cannot drive the graph unless it is in the PW_STREAM_STATE_STREAMING state and pw_stream_is_driving() returns true. It must then use pw_stream_trigger_process() to start the graph cycle.

pw_stream_trigger_process() will result in a process event, where a buffer should be dequeued, and queued again. This is the recommended behaviour that minimizes buffering and maximized buffer reuse.

Producers of data that drive the graph can also dequeue a buffer in a helper thread, fill it with data and then call pw_stream_trigger_process() to start the graph cycle. In the process event they will then queue the filled buffer and dequeue a new empty buffer to fill again in the helper thread,

Consumers of data that drive the graph (pull based scheduling) will use pw_stream_trigger_process() to start the graph and will dequeue, process and queue the buffers in the process event.

Request processing

A stream that is not driving the graph can request a new graph cycle by doing pw_stream_trigger_process(). This will result in a RequestProcess command in the driver stream. If the driver supports this, it can then perform pw_stream_trigger_process() to start the actual graph cycle.

Disconnect

Use pw_stream_disconnect() to disconnect a stream after use.

Configuration

Stream Properties

Stream Rules

Environment Variables

The environment variable PIPEWIRE_AUTOCONNECT can be used to override the flag and force apps to autoconnect or not.