Pipelines

class "pipeline" {
   ipc_pipe
   comp_list : list of components
   buffer_list : list of buffers
   pipe_task
   sched_comp : comp_dev *
   status : uint32_t
}
hide pipeline methods

class sof_ipc_pipe_new {
   comp_id
   pipeline_id
   sched_id
   ...
}
hide sof_ipc_pipe_new methods
note right: attributes provided\nthrough ipc

class task
hide task members
hide task attributes
note right: task registered\nin scheduler

pipeline -- sof_ipc_pipe_new : ipc_pipe
pipeline - task : "pipe_task"

Figure 31 Pipeline structure

Creating a Pipeline

participant "pipeline" as ppl

-> ppl : pipeline_new(pipe_desc, cd)
   ppl -> heap : rzalloc(RZONE_RUNTIME, ...)
   ppl -> ppl : sched_comp = cd
   note right: sched_comp is used as root comp for pipeline scheduling
<-- ppl

Figure 32 Creating a pipeline

The scheduling component (sched_comp) is configured by the driver inside the IPC request. It is usually set to the dai component id for pipelines that are attached to a dai instance and are driven by that dai’s IO events.

Executing an Operation

Most of the pipeline functions sets the operation id and executes a common routine, either component_op_downstream() in case of a playback path or component_op_upstream() otherwise.

participant "pipeline" as ppl

-> ppl : <pipeline operation> (op = COMP_OPS_...)
   alt SOF_IPC_STREAM_PLAYBACK
      ppl -> ppl : comp_op_downstream(op)
   else
      ppl -> ppl : comp_op_upstream(op)
   end
<-- ppl

Figure 33 Pipeline Operation

Propagating the Operation Downstream

participant "pipeline" as ppl
participant "component" as comp
-> ppl : comp_op_downstream(op_data,\nstart, current, previous)
   note right: start, current, and previous are struct *comp_dev
   alt op_data->op == COMP_OPS_PARAMS
      ppl -> comp : comp_install_params(current)
      ppl -> comp : comp_params(current)
   else COMP_OPS_CMD
      ppl -> comp : comp_cmd(current)
      ppl -> ppl : pipeline_cmd_update(current)
   else COMP_OPS_PREPARE
      ppl -> comp : comp_prepare(current)
   else COMP_OPS_RESET
      ppl -> comp : comp_reset(current)
   else COMP_OPS_BUFFER
      note right: error, handled by other API calls
   end
   loop for each current's sink
      ppl -> ppl : component_op_downstream(..., current = consumer @ sink/source)
      note right: recursive call
   end
<-- ppl

Figure 34 Going downstream

Propagating the Operation Upstream

The comp_op_upstream() algorithm is identical except for the loop at the end that runs over the sources and calls itself recursively for producers.

Resetting Pipeline

participant "pipeline" as ppl

-> ppl : pipeline_reset()
   ppl -> ppl : <pipeline operation> (COMP_OPS_RESET)
<-- ppl

Figure 35 Resetting a pipeline

Configuring Audio Parameters & Preparing for Use

actor driver as drv
participant ipc
participant "pipeline" as ppl

drv -> ipc : ipc_stream_pcm_params()
   activate ipc
   ipc -> ppl : pipeline_params()
      activate ppl
      ppl -> ppl : <pipeline operation> (COMP_OPS_PARAMS, first = pcm_dev, params)
   ipc <-- ppl
   deactivate ppl

   ipc -> ppl : pipeline_prepare()
      activate ppl
      ppl -> ppl : <pipeline operation> (COMP_OPS_PREPARE)
      ppl -> ppl : component_prepare_buffers_downstream/upstream()
   ipc <-- ppl
   deactivate ppl
drv <-- ipc
deactivate ipc

Figure 36 Configuring audio parameters

Scheduling

A pipeline’s task (see _Processing_) may be scheduled at a certain point in time using pipeline_schedule_copy(start). In order to schedule the next stream copy operation in idle (see pre-loader), pipeline_schedule_copy_idle() should be used.

Processing

participant "pipeline" as ppl

-> ppl : pipeline_task()
   activate ppl
   ppl -> ppl : pipeline_copy()
      activate ppl
      ppl -> ppl : pipeline_copy_from_upstream()
         activate ppl
         deactivate ppl
      ppl -> ppl : pipeline_copy_to_downstream()
         activate ppl
         deactivate ppl
   deactivate ppl
<-- ppl
deactivate ppl

Figure 37 Pipeline task routine called by the scheduler