You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: basic_pipeline/11_Pipeline.md
+37-90Lines changed: 37 additions & 90 deletions
Original file line number
Diff line number
Diff line change
@@ -6,30 +6,30 @@ In many real-life scenarios, this part would be the only thing you would need to
6
6
7
7
## Defining the pipeline
8
8
9
-
The pipeline is another behavior introduced by the Membrane Framework. To make the module a pipeline, we need to make it `use Membrane.Pipeline`. That is how we will start our implementation of the pipeline module, in the `lib/Pipeline.ex` file:
9
+
The pipeline is another behavior introduced by the Membrane Framework. To make the module a pipeline, we need to make it `use Membrane.Pipeline`. That is how we will start our implementation of the pipeline module, in the `lib/pipeline.ex` file:
10
10
11
-
**_`lib/Pipeline.ex`_**
11
+
**_`lib/pipeline.ex`_**
12
12
13
13
```elixir
14
14
15
15
defmoduleBasic.Pipelinedo
16
16
17
-
useMembrane.Pipeline
17
+
useMembrane.Pipeline
18
18
...
19
19
end
20
20
```
21
21
22
-
You could have guessed - all we need to do now is to describe the desired behavior by implementing the callbacks! In fact, the only callback we want to implement if the pipeline is the `handle_init/1` callback, called once the pipeline is initialized - of course, there are plenty of other callbacks which you might find useful while dealing with a more complex task. You can read about them [here](https://hexdocs.pm/membrane_core/Membrane.Pipeline.html#callbacks).
22
+
You could have guessed - all we need to do now is to describe the desired behavior by implementing the callbacks! In fact, the only callback we want to implement if the pipeline is the `handle_init/2` callback, called once the pipeline is initialized - of course, there are plenty of other callbacks which you might find useful while dealing with a more complex task. You can read about them [here](https://hexdocs.pm/membrane_core/Membrane.Pipeline.html#callbacks).
23
23
Please add the following callback signature to our `Basic.Pipeline` module:
24
24
25
-
**_`lib/Pipeline.ex`_**
25
+
**_`lib/pipeline.ex`_**
26
26
27
27
```elixir
28
28
29
29
defmoduleBasic.Pipelinedo
30
30
...
31
31
@impltrue
32
-
defhandle_init(_opts) do
32
+
defhandle_init(_context, _options) do
33
33
34
34
end
35
35
end
@@ -45,110 +45,57 @@ With such a concept in mind, it's possible to create reliable and fault-tolerant
45
45
[Here](https://blog.appsignal.com/2021/08/23/using-supervisors-to-organize-your-elixir-application.html) there is a really nice article describing that concept and providing an example of the actor system. Feel free to stop here and read about the supervision mechanism in Elixir if you have never met with that concept before.
46
46
Our pipeline will also be an actor system - with the `Basic.Pipeline` module being the supervisor of all its elements.
47
47
As you have heard before - it is the supervisor's responsibility to launch its children's processes.
48
-
In the Membrane Framework's pipeline there is a special action designed for that purpose - [`:spec`](https://hexdocs.pm/membrane_core/Membrane.Pipeline.Action.html#t:spec_t/0).
49
-
As you can see, you need to specify the `Membrane.ParentSpec` for that purpose.
50
-
It consists of:
48
+
In the Membrane Framework's pipeline there is a special action designed for that purpose - [`:spec`](https://hexdocs.pm/membrane_core/Membrane.Pipeline.Action.html#t:spec/0).
49
+
As you can see, you need to specify the `Membrane.ChildrenSpec` for that purpose.
51
50
52
-
-`:children` - map of the pipeline's (or a bin) elements
53
-
-`:links` - list consisting of links between the elements
54
-
55
-
Please stop for a moment and read about the [`Membrane.ParentSpec`](https://hexdocs.pm/membrane_core/Membrane.ParentSpec.html).
51
+
Please stop for a moment and read about the [`Membrane.ChildrenSpec`](https://hexdocs.pm/membrane_core/Membrane.ChildrenSpec.html).
56
52
We will wait for you and once you are ready, we will define our own children and links ;)
57
53
58
-
Let's start with defining what children we need inside the `handle_init/1` callback! If you have forgotten what structure we want to achieve please refer to the [2nd chapter](02_SystemArchitecture.md) and recall what elements we need inside of our pipeline.
54
+
Let's start with defining what children we need inside the `handle_init/2` callback! If you have forgotten what structure we want to achieve please refer to the [2nd chapter](02_SystemArchitecture.md) and recall what elements we need inside of our pipeline.
Remember to pass the desired file paths in the `:location` option!
82
-
We have just created the map, which keys are in the form of atoms that describe each of the children and the values are particular module built-in structures (with all the required fields passed).
83
-
84
-
Now we have a `children` map which we will use to launch the processes. But the Membrane needs to know how those children elements are connected (and, in fact, how the pipeline is defined!). Therefore let's create a `links` list with the description of the links between the elements:
We hope the syntax is visually descriptive enough to show what is the desired result of that definition. Just to be sure let us go through it bit-by-bit.
104
-
Each pipeline's "branch" starts with the `link/1` which takes as an argument an atom corresponding to a given element. All the further elements in the branch can be accessed with the use of the `to/1` function, expecting an atom that identifies that element to be passed as an argument. Note, that the mentioned atoms must be the same as the ones you have used as keys in the `children` map!
105
-
`|>` operator allows "linking" of the elements accessed in the way described above, via their [pads](../glossary/glossary.md#pad). By default, the elements' link will be using an `:input` pad as the input pad and an `:output` pad as the output pad.
106
-
`via_in/1` allows specifying an input pad with a given name. Since in a [mixer](../glossary/glossary.md#mixer) there are two input pads (`:first_input` and `:second_input`, defined in `Basic.Elements.Mixer` module with `def_input_pad` and `def_output_pad` macros), we need to distinguish between them while linking the elements.
107
-
Of course, there is also a `via_out/1` function, which is used to point the output pad with the given identifier, but there was no need to use it.
108
-
In the case of other elements we do not need to explicitly point the desired pads since we are taking advantage of the default pads name - `:input` for the input pads and `:output` for the output ones (see what names we have given to our pads in the elements other than the mixer!). However, we could rewrite the following `links` definitions and explicitly specify the pad names:
The spec list using Membrane's DSL is enough to describe our pipeline's topology. The child keywords spawn components of the specified type and we can use the `|>` operator to link them together. When the pads that should be linked are unamibiguous this is straightforward but for links like those with `Mixer` we can specify the pads using `via_in/1`. There also exists a `via_out/1` keyword which works in a similar way.
86
+
As you can see the first argument to `child/2` is a component identifier, but it's also possible to have anonymous children using `child/1`, which just has Membrane generate a unique id under the hood.
139
87
140
88
Our pipeline is ready! Let's try to launch it.
141
89
We will do so by starting the pipeline, and then playing it. For the ease of use we will do it in a script.
0 commit comments